1.배경
프로젝트 초창기 PMO와 QAO팀은 프로젝트의 품질을 높이기 위한 방안에 대하여 논의를 진행했다. 단위 기능에 대한 검증은 기존에 사용하던 바와 같이 Junit 을 통해 해결을 할 수 있었으나 각 비즈니스 도메인 사이의 연계에 대한 검증은 아직 정확한 솔루션을 결정하지 못한 상태였다. 프로젝트의 도메인 성격상 각 채널의 인터페이스를 통한 실행이 주를 이루었으며 UI와 관련된 업무의 비중이 낮은 상황이었다. UI와 관련된 통합테스트 도구는 검토 대상에서 제외하였으며 인터페이스를 통한 테스트도구를 중심으로 선정 대상을 검토하여 최종적으로는 WIKI를 통해 FIT 를 실행할 수 있는 Fitnesse를 선택하게 되었다. 이제 Fitnesse를 선택하면서 고민하고 결정했던 사항들과 진행 프로세스에 대해서 이야기하고자 한다.
2.통합테스트 환경 준비
2.1 Fitnesse 도입시 고려사항
Fitnesse의 사용 결정 이후 통합테스트 프레임워크 도입 이후 어떠한 사항들을 고려해야 하는지 여러 이해관계자들이 모여 논의를 진행하였다.
- 테스트 대상을 어떻게 선정할 것인가?
- 테스트를 수행하는 주체는 누가 될 것인가?
- 얼마나 많은 테스트 테이블을 작성해야 하는가?
2.1.1 통합 테스트 프레임워크 도입 필요성을 이해관계자 모두 공감하는가?
통합테스트 프레임워크를 도입하기로 결정한 직후 당면한 사항은 실제 업무를 수행해야 하는 이해관계자들의 반발이었다. "통합 테스트의 도입으로 인해 시스템 개발과는 관련 없는 부가적인 일이 더 추가되었으며 이러한 업무도입은 오히려 개발 생산성을 떨어뜨려 전체 프로젝트 일정에 영향을 줄 것이다" 라는 것이 대다수 이해관계자들의 의견이었다. 전체 프로젝트를 총괄하는 PM과 품질관리를 수행해야 하는 QAO의 강력한 의지가 필요한 시점이었다. 자동화된 테스트의 목적 중 하나인 리그레이션 방지와 리그레이션 테스트 검증 그리고 시스템 리팩토링 시 변경사항의 영향도 검증, 내부 로직 변경에 의한 외부 연계 시스템의 영향도 검증에 최소의 비용으로 최대의 효과를 나타낼 수 있다는 점을 이해관계자들에게 납득 시켰다. 자동화된 테스트 프레임워크로부터 얻는 이점을 경험하지 못한 개발자들에게는 여전히 불필요하다는 의견을 가지고 있었지만 PMO의 강력한 의지로 Fitnesse 가 도입되었다.
- 문제가 발생한 이후에 원인을 찾아서 해결 할 것인가?
- 아니면 문제가 발생하기 이전에 검증을 수행하여 미리 해결할 것인가?
시스템 배포 이전에 도메인 간의 변경사항이 미치는 영향을 미리 검증하여 운영서버 장애를 방지한다는 점에서 구성원들의 필요성을 공감하도록 유도하는 것이 중요하다.
2.1.2 테스트를 대상을 어떻게 선정할 것인가?
테스트를 도입해야 하는 여러 비즈니스들 중에서 통합테스트 프레임워크로 검증해야 하는 대상을 어떻게 선정할 것인가는 Fitnesse 도입 이후로 당면한 첫번째 과제이다. 수많은 비즈니스 중에서 통합테스트를 통해 검증해야 하는 비즈니스를 1차로 선정하여야 한다. 그리고 항상 검증결과가 비교되기 위해서는 입력값 대비 결과값이 항상 일정해야 하므로 테스트 선정시에 고려되어야 한다. 주어진 개발일정 내에서 소화하기 힘들 만큼 테스트 대상을 선정한다면 오히려 주객이 전도되는 상황이 벌어지므로 테스트 적용 우선순위를 정하고 적용여부는 개발일정에 탄력적으로 적용해야 한다.
- 다양한 테스트 상황을 고려할 수 있을 만큼 테스트 프레임워크 Fitnesse가 유연한가?
- 테스트 대상 DATA가 실시간으로 변화하는가?
- 도메인간 연계를 고려해야 할 만큼 중요도가 높은 비즈니스 인가?
- 업무의 우선순위가 높은가?
- 개발팀에게 주어진 개발일정 내에서 소화할 수 있는가?
Fitnesse는 입력 값 과 결과 값을 WIKI페이지에 입력하고 검증을 수행 하므로 항상 결과에 대한 기대 값은 동일해야 한다는 제약사항이 존재한다. 테스트 대상 시스템 중 경로탐색 서버는 실시간 교통정보에 따라 경로가 달라지므로 입력 값에 따른 경로결과를 검증하는데 문제가 발생했다. 이러한 비즈니스 상황을 해결하기 위하여 교통정보를 갱신하지 않는 테스트 대상 서버를 별도로 구축하는 방안과 교통정보를 반영하지 않는 경로탐색 비즈니스만 검증대상으로 선정하고 실시간 경로탐색 기능은 수작업을 통한 검증방안 2가지가 검토되었다. 교통정보가 반영되지 않더라도 비즈니스 검증에 영향도가 적으며 교통정보 반영 탐색기능은 다양한 방식의 검증이 이루어져야 하므로 이 경우에는 수작업 검증을 포함하는 두 번째 방안으로 최종 결정하였다. 변화하는 정보가 있는 경우는 비즈니스의 중요도 및 테스트 서버 환경 구축에 대하여 논의가 필요하다.
2.1.3 테스트를 수행하는 주체는 누가 될 것인가?
통합테스트 도입으로 인해 고려되어야 하는 사항중의 하나는 "통합테스트를 수행하는 주체는 누구인가?" 그리고 "각각의 이해관계자는 어떤 역할을 수행해야 하는가?" 이다.
가장 대표적인 이해관계자는 역시 업무담당자와 QA담당자, 개발자로 들 수 있다. 우리 프로젝트에서는 명확하게 구분되는 업무담당자의 역할을 가진 이해관계자가 없었으며 AS-IS 시스템을 새로운 아키텍쳐를 반영한 신 시스템으로 변환하는 것이 목적이었기에 기존 시스템 운영담당자의 도움을 받아 정의한 비즈니스를 QA담당자가 반영하는 것으로 결정하였다. QA담당자는 비즈니스를 검증하기 위한 업무를 정의하며 정의된 업무를 Fitnesse 시스템의 WIKI에 반영하는 역할을 담당하였다. 개발자는 QA담당자와 협의하여 정의된 비즈니스를 반영하기 위하여 Fixture를 작성하기로 했다. 이해관계자의 역할이 정리된 이후 대두된 문제는 각각의 도메인 개발자들이 작성한 Fixture와 이를 반영하기 위한 컴포넌트는 누가 개발하는가에 대한 문제였다. 그리고 개발된 Fitnesse 서버를 프로젝트 종료시점까지 담당할 팀을 결정하는 것이었다. QA팀은 테스트 담당자이지만 시스템이나 프로그래밍에 대한 지식이 없으므로 통합테스트 서버를 유지할 수 없다는 의견을 내놓았고 각각의 도메인 개발팀에서는 자신의 팀에서 담당할 여유가 없다는 점에서 해당 테스트 시스템을 담당하기를 거부했다. 팀장 회의를 거쳐 아키텍쳐 팀에서 Fixture 배포 프로세스와 관련 공통 컴포넌트를 개발하고 Fitnesse 서버의 시스템적인 문제를 담당하며 QAO에서 Fitnesse 서버를 운영 하면서 테스트 통계 및 비즈니스 테스트 반영 프로세스를 담당하기로 결정하였다. 각 개발팀은 테스트 컴포넌트의 도메인 로직을 반영한 fixtrue를 개발하며 배포는 CI를 통해 주기적으로 테스트 수행하도록 하였다.
2.1.4 얼마나 많은 테스트 테이블을 작성해야 하는가?
테스트 대상을 선정하고 비즈니스 케이스를 선정해야 한다. 가능하면 많은 비즈니스 케이스를 도출하여 반영하면 좋겠지만 시스템의 성능과 비즈니스 중요도, 경우의 수를 고려하여 결정해야 한다. QAO와 업무담당자가 협의하고 비즈니스 케이스를 결정하였으며 해당 비즈니스를 업무별로 분류하여 WIKI 페이지를 작성하였다. 하나의 WIKI 패이지에서는 가독성을 고려하여 테스트 테이블을 작성해야 하며 가능하면 3개 미만의 테이블을 작성하는 것을 추천한다. 이 이상의 테스트 테이블이 포함되면 테스트 테이블의 테스트 DATA 양에 따라 너무 많은 테스트 정보가 주입되어 오히려 가독성을 떨어트려 효율적인 테스트 DATA 관리를 어렵게 한다.
2.2. Fitnesse 통합테스트 아키텍쳐 검토
개발자가 작성한 Fixture와 실제 테스트 대상 시스템 간의 연동구조는 아래와 같이 고려해 볼 수 있다. 수행 프로젝트에서는 각각의 채널서버와 도메인 업무 서버로 분류되고 Spring 을 통한 Remote 호출로 서비스가 제공된다. 이러한 구조에 맞추어 3가지 경우의 테스트 서버 구축방안을 고려할 수 있다.
- Fitnesse 서버 내부의 로컬호출 검증
- Fitnesse 서버에서 각 업무서버로 Spring Remote 호출
- Fitnesse 서버에서 각 업무서버로 Http 호출
2.2.1 Fitnesse 서버 내부 로컬 호출
처음 Fitnesse 서버를 구성할 때에는 Fitnesse 서버 내부에서 각각의 업무 컴포넌트를 모두 배포하고 로컬호출 하는 구조를 적용하였다. Fitnesse 서버가 업무팀 서버와의 의존성이 없어 독립성이 보장되므로 적절한 구조로 판단 하였다. 모든 업무팀의 컴포넌트가 배포되었으며 프로젝트 중반까지 아무 문제 없이 운영되었다. 하지만 비즈니스 로직 개발이 진행됨에 따라 소스가 계속 추가되고 많은 메모리를 사용하는 로직들이 늘어남에 따라 비정기적으로 메모리 부족현상이 발생하기 시작하였다. 메모리 부족현상을 해결하기 위하여 Fitnesse 서버의 VM 옵션을 변경하였으나 해당 문제가 해결되지 않았다. Fitnesse 서버는 테스트 케이스를 실행할 때 새로운 프로세스를 invoke 시키고 테스트를 수행하는데 이때 VM옵션은 default로 적용되어 실행된다. 이러한 구조로 인해 Fitnesse 서버 시작옵션의 조정은 각 테스트 프로세스의 옵션에 영향을 주지 못하여 메모리 부족현상을 근본적으로 해결하지 못하였다. 문제를 해결하기 위하여 테스트 서버를 별도로 구축하고 원격 호출하는 방안이 검토되었으며 각 업무 팀 별 통합테스트 서버를 원격으로 호출하여 사용하는 것으로 문제를 해결하였다.
2.2.2 Fitnesse 서버 리모트 호출
Fitnesse 서버 내부의 메모리 이슈를 해결하여 위하여 원격 호출 구조로 변경한 이후 또 다른 문제를 만났다. 개발 서버가 아닌 통합테스트 서버에 배포가 되어 어느 정도 검증이 완료된 컴포넌트가 배포되면 오류가 줄어들 것이라고 예상하였으나 지속적으로 컴포넌트의 인터페이스가 변화하고 있기에 각 통합테스트 서버간 컴포넌트의 인터페이스 불일치로 인한 오류가 테스트 검증을 진행하는데 방해요소가 되었다. 새로운 컴포넌트가 배포되고 여러 업무서버에서 사용되는 공통 컴포넌트인 경우 각각의 통합테스트에 동시에 배포될 수 있도록 CI서버를 구축하고 주기적으로 통합테스트 서버를 재 배포하여 버전 일치화를 시켰다. 리모트 호출구조의 테스트 환경에서는 Fitnesse 서버와 각 개별 업무서버간에 컴포넌트가 반드시 일치되어야 하며 컴포넌트를 일치화 시킬 수 있는 시스템 적인 장치가 고려되어야 한다.
2.2.3 Fitnesse 서버 HTTP 호출
채널 시스템은 외부시스템에게 REST 서비스를 제공한다. REST 서비스는 기존의 fixture에서 Spring Context를 얻어 컴포넌트의 인터페이스를 바로 호출하는 방식으로는 검증되지 않는 비즈니스로 분류되었으며 이에 대한 검증이 필요하다는 의견이 있었다. 프로젝트의 최종 목표 중 하나인 외부시스템으로 REST 서비스를 제공하는 것에 대한 검증을 위하여 Fixture 에서 HTTP로 채널서버를 호출하여 로직을 검증하는 구조를 추가 하였다.
3.통합테스트 프로세스 수행
3.1 계획수립
통합테스트 환경이 준비가 되면 QAO팀에서 테스트 일정을 수립한다. QAO의 일정 수립 시 반드시 개발팀의 개발일정을 참고해야 하며 개발일정에 따라 테스트 일정이 계획 될 수 있도록 개발팀과 상세한 논의를 수행해야 한다. 개발팀에서는 전체 테스트 일정을 참고하여 개발일정과 비교하여 세부 개발일정을 계획해야 한다.
3.2 테스트 대상 선정 및 테스트 DATA 준비
테스트 대상을 선정할 때에는 해당 도메인의 기능을 분류하고 중요도 순으로 기능을 분류하여 선택하여야 한다. 테스트 대상이 결정되면 테스트 를 위한 입력 정보와 결과정보를 정리하여 Fitnesse 테스트 케이스를 작성할 준비를 한다.
3.3 테스트 케이스 작성
테스트 케이스를 작성할 준비가 완료되고 Fitnesse 서버가 준비되면 QAO에서 WIKI에 테스트 정보를 입력한다.
3.3.1 Fitnesse WIKI 구조 정의
각 도메인 별로 업무를 분류하고 WIKI에서 입력한다. 프로젝트를 진행하면서 테스트 케이스가 늘어나고 비즈니스의 변경사항으로 인해 개발대상에서 제외하는 업무들이 생겨 WIKI의 구조들이 여러 번 변경되었다. 개발환경에 맞추어서 적절히 WIKI의 구조를 선정하고 테스트 케이스를 입력하는 것이 좋다.
3.3.2 Fitnesse WIKI 명명규칙 정의
WIKI의 작성은 QAO가 담당하고 해당 TEST case의 Fixture는 개발자가 개발하는 방식에서 상호간에 공유하는 영역에 대한 정확한 용어정의가 필요하다. 최초 QAO에서 각 항목에 대한 용어를 정의하였고 개발팀과 협의하여 다듬어 나갔다. 정해진 표준에 맞추어지지 않는 항목들에 대해서는 fixture 개발 당시 QAO와 협의하여 항목을 정의하여 사용하는 것이 좋다
WIKI 에서는 위와 같이 각 항목에 대한 용어를 정의하였다. 개발자는 Fixture를 개발할 때 해당 항목에 일치하는 attribute 또는 메소드를 Fixture 클래스에 작성하여 상세 기능을 구현하였다.
3.3.3 Fitnesse Fixture 클래스 명명규칙 정의
Fixture를 구현할 Java 프로젝트를 생성한다. 프로젝트에서는 하나의 Fixture 프로젝트를 생성하고 각 업무 도메인 별 패키지를 구성하여 Fixture를 개발하였다. Fixtrue 클래스는 모두 PostFix 로 fixture를 붙였고 기타 지원 클래스와 테스트클래스를 구분하였다. 초창기 테스트 케이스가 적을 때는 문제가 없었으나 개발이 진행되면서 각 업무팀 기능 개선으로 인해 Fixture 클래스에 오류가 생기고 이로 인해 테스트 프로젝트가 배포가 되지 않는 문제가 빈번하게 발생하였다. 매주 테스트 통계를 정리하는 날마다 이러한 오류를 수정하고 정리하는 것이 QAO팀의 일과가 되기도 하였다. 이 문제를 해결하기 위하여 각 도메인 별 Fixture클래스를 분리하는 방안을 검토하기도 하였으나 실현하지는 못하였다. 각 팀에서 작성한 로직의 오류로 인하여 전체 테스트 로직의 수행이 멈추는 것을 방지하기 위하여 각 업무 도메인 별로 별도의 프로젝트를 구성하는 것을 추천한다.
3.4 테스트 케이스 수행
Fitnesse 에서 수행되는 테스트는 정기적으로 수행되어야 한다. 프로젝트에서 최초 하루 1회 야간 컴포넌트 빌드 시간에 배포되어 테스트가 수행되었다. 프로젝트가 일정 수준 진행된 이후 각 도메인 별 통합테스트 서버가 수시로 재 배포되는 상황에서 하루 1회 검증만으로는 안정성을 보장하기 어렵다는 의견이 나와 1시간에 한번씩 테스트를 수행하는 것으로 변경하였다. 프로젝트에서는 서버 환경 및 프로젝트 상황에 맞추어 통합테스트 시행 주기를 결정하여야 한다. 테스트 수행 결과는 Fitnesse 서버의 테스트 히스토리에서 확인 할 수 있으며 테스트 수행결과는 정기적으로 QAO에 의해서 취합되고 각 개발팀장에게 공유되어야 한다.
3.5 테스트 케이스 통계 및 보고
Fitnesse 에서 수행된 결과는 매주 주말에 집계되며 주간회의 시간에 보고되어 테스트 추이를 논의하였다. Fitnesse의 테스트 시행도 중요하지만 테스트 수행 통계를 바탕으로 프로젝트 상황을 파악하는 것도 중요한 사항이다. 현재 테스트 성공률로 프로젝트의 품질을 예측할 수 있으며 중요한 로직의 개발 추이를 확인 할 수 있다.
위의 표에서 초반부에 검증 Req수는 증가하는데 검증률이 감소하는 시점이 있다. 해당 도메인 업무팀에서 특정 시점에 인터페이스가 수행조차 할 수 없이 개발 품질이 감소하고 있다는 의미이고 어떤 원인으로 인한 것 인지, 장기적 요소가 될 것인지 판단하여 검증률이 증가하도록 노력해야 하는 중요 시점으로 볼 수 있다. 후반부에 특정 Req수가 증가했다가 감소하는 패턴을 확인 할 수 있는 데 이 시점에 비즈니스의 변경으로 특정 업무의 개발 요건이 취소되었고 그로 인해 관련 테스트 코드가 제거되는 상황이 발생한 상황이 반영되었다. QAO는 이러한 통계에서 변환되는 상황으로 검증해야 하는 대상이 변경되었고 이후 베타 테스트 및 성능 테스트 시 대상이 되는 중요 로직이 감소하였음을 알 수 있다
위의 표는 테스트 성공률에 대한 일정기간 추이를 나타낸 표이다. Fitnesse의 성공률은 테스트 케이스의 조건이 성공,에러 등 상황에 맞게 정확한 값을 확인한 경우 성공으로 표기한다. 성공률이 100%라는 의미는 모든 테스트 케이스가 정상적으로 동작했다는 의미이며 100%이하의 조건은 테스트 케이스에 맞지않는 로직이 개발되어 있다는 점에서 프로젝트의 품질을 판단할 수 있다. 중간 기간쯤에 RSD팀의 테스트 성공률이 0%로 하락한 부분이 확인되는데 이 시점에 해당팀은 전체 기능을 재개발하는 리팩토링을 진행하였다 이로 인해 리팩토링이 완료될 때 까지 테스트 성공률이 저하 되었으며 관련 기능을 사용하는 채널업무영역에서도 비슷한 시기에 테스트 성공률이 저하 되었다.
4.마무리
Fitnesse 도입함으로써 각 팀의 개발품질을 효율적으로 관리할 수 있었고 지속적인 테스트를 수행함으로써 내재된 오류를 선 발견하여 조치하는 이점도 얻을 수 있었다. 자동화된 통합테스트를 도입하게 되면 테스트 비용을 줄어들 것이라 판단했지만 개발자들이 직접 개발해야 하는 fixture 로 인해 개발부담을 호소하는 것도 프로젝트에서 풀어야 하는 과제이다. 어떤 테스트 코드도 동일하지만 100개의 무의미한 테스트 코드 보다는 1건의 의미 있는 테스트 코드가 더 좋다. Fitnesse 를 도입하기도 결정을 했다면 의미 있는 테스트를 위해 품질 좋은 테스트 코드를 확보하는데 주력해야 할 것이다.