블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-bwcho75골뱅이지메일 닷컴. 조대협


Archive»


 
 

TestLink를 이용한 Test Case 관리

조대협 (http://bcho.tistory.com)


테스트 케이스가 어떻게 요구 사항에 맵핑이 되는지, 테스트 케이스의 시나리오는 어떻게 되고 요구 되는 결과 (Expected Result)는 어떻게 되는지, 테스트 결과는 어떻게 되는지, 그리고 Version 별 릴리즈에 따른 테스트 계획과 결과는 어떻게 되는지를 관리할 수 있는 도구가 필요하다.

 대부분 테스트 엔지니어나 개발팀들이 위의 테스트 도구 자체에는 관심이 많은 것 처럼 보이지만, 정작 테스트 프로세스나 테스트 케이스 전체를 관리하기 위한 관리도구에는 그다지 집중하지 않는 것 처럼 보인다. 테스트 케이스 자체를 구현하는 것도 중요하지만, 전체 시스템에 대해 어떻게 테스트를 하고, 테스트에 대한 내용을 어떻게 관리할 것인가도 상당히 중요한 일이라고 본다.

그렇다고 거창하고 복잡한 프로세스가 필요하다는 이야기가 아니라 최소한의 테스트 조직에서 테스트 케이스에 대한 관리를 할 수 있는 툴이 필요하다는 것이다.

조금 쉽게 설명하면 테스트 케이스를 액셀로 만들어서 그 액셀 문서를 여러 사람이 나눠서 테스트를 진행하고 결과를 기입하던 절차를 자동화 했다고 생각하면 된다.

Test Link

오픈소스 도구중에서 널리 사용되고, Learning Curve가 낮은 도구중의 하나가 TestLink 라는 도구이다. http://testlink.org/

먼저 TestLink에서 사용되는 개념에 대해서 먼저 알아보자



Test Project

테스트 프로젝트는 테스트를 수행하는 프로젝트 자체를 이야기 한다. 블로그 서비스를 만들었을때 블로그 서비스 프로젝트”; 와 같은 단일 테스트 프로젝트로도 만들 수 있고, 내지는 블로그 서비스 모바일 클라이언트 테스트”, “블로그 서비스 웹 서비스 테스트와 같이 하나의 서비스에 대해서도 특성에 따라서 여러가지 프로젝트로 분할해서 테스트를 진행할 수 있다. 분할의 기준은 자유롭지만, 테스트 팀 단위로 분할 하는 것이 관리에 용이하다. (클라이언트 테스트 팀, 웹 테스트 팀 또는 미국 테스트 팀, 한국 테스트팀 등)

Test Specification

Test Spec은 테스트를 진행하고자 하는 테스트 케이스들의 집합이다.

Test Spec Test Suite, Test Case로 나뉘어져 있는데, Test Suite은 대분류, Teste Suite의 소분류의 테스트 케이스라고 보면 된다.

흥미로운 점중의 하나는 TestLink에서는 이 Test Case에 대한 버전 관리가 가능하다는 것이다. 예를 들어, “로그인이라는 Test Case, 예전에는 Facebook 계정을 이용한 로그인만을 테스트하는 케이스였는데, 향후에, 케이스가 추가 되서, Google 계정 로그인도 지원한다면, Test Case의 버전을 새로운 버전으로 정의할 수 있다.

Test Plan

테스트 플랜은 실제 진행하는 테스트를 의미한다. Test Project내에서, 테스트 대상 시스템의 특정 버전을 테스트 하기 위해서 Test Spec내의 Test Suite/Case를 모아 놓은 것을 Test Plan이라고 한다. Test Spec이 전체 테스트 케이스의 집합이라면, Test Plan에서는 실제로 이번에 테스트 할 Test Suite/Case들을 모아 놓은 subset이다. Test Plan Test Case를 맵핑할때, 실제 어느 Test Engineer가 테스트를 진행할지 Test Engineer assign할 수 있다.

Test Execution

Test Plan을 세웠으면, 실제로 각 Test Engineer가 자기에게 할당된 테스트를 수행하고, 테스트 결과 Pass/Fail 여부를 체크한다. 만약에 실패한 케이스일 경우에는 재 테스트를 하는데, 그 간 Minor Release가 되었을 경우에는 Minor Release 버전으로 테스트를 다시 해서 Pass 여부를 결정한다.

Test Report

마지막으로, 테스트 결과를 리포팅한다. 테스트 실패,성공 여부, 주요 Test Category (TestSuite)별 성공 실패 여부등을 리포팅 한다.

Test Link 사용 예제

그러면 이 흐름에 따라서 Test Link에서 실제로 어떻게 Test를 수행하는지를 알아보자. 먼저 TestLink를 인스톨하고

1.     Test Project 생성

먼저 Create New Project에서 테스트 프로젝트를 생성한다.

프로젝트 명과, 테스트 케이스에 적용할 prefix를 정의한다.



몇가지 옵션들이 있는데, TestLink BugZilla,Mantis,JIRA와 같은 버그 트랙킹 도구와 연동이 가능하다. “Issue Track Integration”을 선택하면, 버그 트랙킹도구를 연결할 수 있다. (별도의 Configuration이 필요하다.)

          • Ÿ   - Enable Requirement Feature : Requirement TestLink에 정의해서, Requirement à Test Case까지의 추적성을 부여할 수 있다.

          • Ÿ   - Enable Testing Priority : Test Case에 가중치를 부여할 수 있다.

          • Ÿ   - Enable Test Automation : 수동으로 테스트 하는 것이 아니라, Test Case SOAP UI Selenium과 같은 다른 테스트 도구를 연동하도록 설정할 수 있다. 

자 이제 테스트 프로젝트가 위의 그림처럼 생성되었다.


2.     Test Spec 작성

상단 메뉴에서 “Test Specification” 이라는 곳으로 들어가면 Test Suite/Case를 정의할 수 있다. 해당 메뉴로 들어가면 Test Suite/Case를 넣을 수 있는 화면이 나온다. 여기서 좌측 아래에 있는 트리를 선택한 후 오른쪽 버튼을 눌러서 Test Suite을 생성한다. Test Suite 이름과 간단하게, Test Suite에 대한 내용을 “Detail” 부분에 기술한다. 본인의 경우에는 이 Test Suite Scrum Epic 1:1 맵핑을 시키고, Epic에 있는 Description을 그대로 사용한다.

Test Suite Test Case의 집합으로, Test Case에 대한 대분류 정도로 생각하면 되고, 생성된 Test Suite들은 아래 그림과 같이 폴더 형태로 생성된다.


다음으로, 생성된 TestSuite (폴더)에서 오른쪽 버튼을 눌러서 Test Case를 생성한다.



Test Case는 개개별 테스트 시나리오로, 먼저 Summary 부분에 어떤 내용을 테스트 하는지 기술 하고, PreCondition을 입력한다. 예를 들어 Facebook 계정을 이용해서 로그인하는 시나리오를 테스트 한다면, Precondition사용자는 Facebook 계정을 가지고 있어야 한다.” 로 정의할 수 있다.

다음으로 구체적인 테스트 절차를 입력한다.

Step을 입력하는 버튼을 누르면, 아래와 같이 Step을 입력할 수 있는 부분이 나온다. 쉽게 이야기해서 테스트 절차가 된다. 각 단계별로 필요한 Action“Step actions”에 적어놓고, 우측에는 “Expected results”에 정상적으로 Action을 수행했을때 기대되는 결과를 기록한다.


위와 같이 Step by Step으로 action을 정의할 수 도 있지만 굳이 필요하지 않다면,아래 그립과 같이 하나의 action안에 전체 Step을 기술할 수 도 있다.



여기 까지 진행하면, Test Project Test 시나리오를 담은 Test Specification이 모두 완성되었다.


3.     Test Plan 작성

이제 실제로 테스트를 진행하기 위해서 Test Plan을 작성해보자. Home 메뉴에서 Test Plan Management를 선택한후에, 아래와 같이 Test Plan을 생성한다.



4.     Build Version 생성

다음으로 Test Plan내에서 사용할 Build Version을 정의한다.



처음에는 1.0과 같은 Major 버전을 정의하고, 개발팀에서 Minor 버전을 Release할때 마다 1.1, 1.2 식으로 Minor Version도 같이 생성한다. 그리고 각 버전에는 아래 그림과 같이 Release date를 선택해놓으면 관리하기가 편리하다.



5.     Test Suite/Case Test Plan Assign

이제 Test Plan Test Specification에 정의된 Test Case들을 맵핑해보자 메인화면에서 Test Plan Contents 라는 메뉴에서 “Add Remove Test Cases”를 선택한다.

아래와 같이 Test Case를 선택할 수 있는 창이 나오는데, 좌측 아래에서 Test Case를 골라서, 우측 상단에서 처럼 Test Engineer Test Taget Version을 선택한 후에, “Add Selected”를 선택하여, 테스트 케이스를 Test Engineer에게 할당한다.



이제 테스트 수행을 위한 준비가 다 되었다. 개별 Test Engineer에게 상세한 Test Scenario들이 모두 배정 되었다.


6.     Test Execution

이제 테스트를 수행하는데, Test Engineer들은 할당된 Test Spec Step action에 따라서 테스트를 수행하고, 성공/실패 여부를 아래 그림과 같이 선택한다.


위의 그림은 테스트가 성공했을때의 케이스이다. 만약에 Test가 실패하면, Failed라고 나타나는데, 이때 BUG management의 벌레 모양 버튼을 누르면 아래와 같이 버그 트랙킹 시스템에 등록된 버그 번호를 입력할 수 있다.



이렇게 버그 번호를 입력하면, Relevant bugs에 해당 버그에 대한 링크가 생성되고, 이 링크를 누르면, 해당 버그 트랙킹 시스템으로 이동한다. Relvant bugs 항목을 보면 이 Bug의 현재 처리 상태가 나온다. 위의 그림에서는 “Testing” 상태로 나타나는데, 이 상태는 버그 트랙킹 시스템의 상태를 그대로 출력해준다. Open이나 In Progress 처럼 개발자가 버그 수정을 하다가 수정이 끝나서 위의 그림처럼 “Testing”상태로 상태를 바꿔 놓으면, Test Engineer가 버그가 수정되었음을 인지하고, 버그 트랙킹 시스템에서 수정 결과와 버전을 확인한 후에, 그 버전(Minor 버전)을 선택하여 다시 Test를 수행한후 Pass/Fail 여부를 결정한다.

이 과정에서 TestLink와 버그 트랙킹 시스템간의 프로세스 연계가 중요하다.

테스트가 실패한 경우, Test engineer가 버그 트랙킹 시스템에 Bug를 등록해야 하고, Bug가 수정되면 개발자가 해당 Bug를 다시 Test Engineer에게 assign한후에, Test Engineer가 테스트를 확인하면, 버그 트랙킹 시스템에서 해당 Bug Close 처리하도록 하는 것이 권장되는 프로세스 이다.

Test Execution 시에, 1.0에서 발견된 버그라도 수정이 1.2 버전에서 수정되었다면, Test Execution에서 테스트 수행전에 “Build to Execute” 리스트박스에서 수정된 버전을 선택해서 테스트를 진행해줘야 한다.


7.     Reporting

테스트가 종료되었으면, 상단 메뉴의 “Test Reports”에서, 여러 형태의 테스트 리포트를 생성할 수 있다.



위의 그림은 Test Suite 별로 성공/실패 율과 전체 Test Case 수를 리포팅해주는 화면이다.

Test Link 향상된 기능

이외에도 Test Link는 앞에서 잠깐 언급한 바와 같이 Selenium,SOAPUI와 같은 테스트 도구 뿐만 아니라, JUnit과 같은 다양한 테스트 프레임웍 연동은 물론이거니와, Jenkins까지 같이 연계가 가능해진다.

기존에 테스트 도구만을 사용했을 때는 전체 테스트 현황이나 History, 상세한 테스트 케이스 특히 JUnit과 같은 코드가 아니라, Human readable한 형태로 테스트 케이스를 관리할 수 있게 해주며, 요구 사항에서 부터 Test Case 및 결과에 까지의 추적성을 보장해주기 때문에 매우 편리한 도구이다. Learning Curve도 상당히 낮은 도구이기 때문에 반드시 사용해보기를 권장한다.

그리고 누가 강조하지만, 도구는 도구일뿐이다. 어떻게 테스트팀의 구조를 잘 세팅하고, 프로세스를 잘 정의하느냐가 가장 중요한 항목이다.

'ALM > Test Automation' 카테고리의 다른 글

TestLink를 이용한 Test Case 관리 자동화  (2) 2013.12.31
Selenium Test Suite 수행  (0) 2013.12.29
Selenium WebDriver와 RC 차이  (0) 2013.12.24
Selenium 테스트 메모  (0) 2013.12.24
테스트 팀의 조직 구조  (1) 2012.08.21
JUnit Max  (1) 2009.05.06

LoadUI 테스트 결과

성능과 튜닝 | 2012.10.30 01:02 | Posted by 조대협

부하테스트툴로 고민중이던 Load UI를 테스트해봤다.

SOAPUI를 만든 업체의 제품이라서 신뢰가 갔는데.. 2012년 제품으로 제품의 성숙도에 의문이 있었다. 지금도 의문은 남아 있다.



전체적으로 Yahoo Pipe와 같이 Mash up의 느낌을 준다.

Wramp up 테스트, agent를 이용한 분산 환경 기반의 테스트등 기본적인 테스트와 Server Side 모니터링을 지원한다.

스크립트 언어로는 Groovy를 지원한다. 그리고 SOAP UI를 PLUG IN하여 부하 발생기로 사용할 수 있으며, Hudson과 같은 CI툴과 통합하여 regression 테스트 까지 지원한다.


전체적으로 기능 자체에는 부족함이 없어보인다.

Java 기반이고 UI는 Java FX를 사용해서 인지, Launch할때 좀 불안정하고, 전체적으로 대규모 테스트시에 UI가 Load Runner의 Windows Client에 비해서 불안정해 보인다.


Web Browser기반의 record&play기능이 없다.

오픈소스 버전과 Pro 버전이 있으며, pro 버전은 10,000USD이다.


테스트 팀의 조직 구조

ALM/Test Automation | 2012.08.21 15:27 | Posted by 조대협

테스트 팀의 조직 구조


Facebook Server Side Architecture Group (SSAG)

http://www.facebook.com/groups/serverside

조대협


테스트를 수행하는 테스트팀의 구조는 테스트 방법론이나 개발 조직, 개발팀의 개발 방법론에 따라 모두 차이가 있다. 여기서는 일반적으로 적용할 수 있는 테스트 조직 구조에 대해서 소개한다.

각각의 역할은 중첩 될 수는 있으나, 생략 될 수 는 없다.




테스트 팀

테스트팀은 테스트를 계획하고 주도적으로 수행하는팀이다. 테스트팀의 일반적인 구조는 다음과 같다.

Test Lead

전체 테스트에 대한 모든 것을 관장한다. 테스트 팀 관리 뿐만 아니라 시스템에 대한 전체 품질 관리를 포함하여 관리한다.

-       Define strategy, methodology : 시스템의 품질 보장을 위한 테스트 전략과 운영할 방법론을 찾고, 조직에 맞게 테스트 방법론을 설계 및 수립한다.

-       Define Process : 시스템 개발 및 테스트 단계에서 운용할 테스트 프로세스를 수립한다. 테스트 프로세스는 테스트 팀만이 사용하는 방법론이 아니라, 개발 및 출시 전과정에서 적용해야 한다. 즉 테스트 팀 뿐만 아니라 개발팀에서도 사용해야 하며, 출시 여부를 결정하는 마케팅팀에서도 이 테스트 프로세스에 영향을 받는다.
수립된 테스트 프로세스는 FIX된 체로 운용되는 것이 아니라 적용 과정을 거쳐서 시스템과 조직의 성격에 맞도록 계속해서 성숙 시켜 나가야 하는데, 이 역할 역시 Test Lead가 담당해야 한다.

-       Manage test project : 테스트팀을 운용 하고 관리한다. 인원을 뽑는 것에서 부터, 일정 관리, 예산 관리와 같이 팀 관리에 해당하는 모든 업무를 수행한다.

-       Communicate with other team : Test Lead의 역할 중 가장 중요한 역할 중 하나가, 다른 팀과의 의사 소통 가교 역할을 하는 것이다. 테스트는 테스트 대상을 가지고 있으며, 제품 출시 여부를 결정 기준이 되며, 테스트 중 발견된 결함을 개발팀에서 수정되어야 하며, 테스트 운영을 위해 필요한 인원에 대한 채용, 테스트에 필요한 툴 구입을 위해서 예산을 확보해야 한다. 이러한 모든 작업은 테스트팀 자체적으로 해결할 수 없고 타팀과의 협업을 통해서만 해결할 수 있기 때문에, 타 팀과의 의사 소통은 매우 중요한 역할이다.

-       Educate team : Test Lead는 테스트 수립된 전략과 프로세스, 방법론에 따라 테스트 팀 및 개발팀이 테스트 작업을 수행할 수 있도록 교육을 진행한다.

-       Define matrix : 시스템에 대한 품질, 테스트 팀의 진척률, 개발 프로세스에 대한 품질등을 체크할 수 있는 정량화된(수치화된) Matrix 표를 정의한다. 여기에 사용될 수 있는 Matrix는 다음과 같다.

1) Defect / KLOC : 소스코드 1000라인당 발견되는 Defect의 수
2) Test Coverage :
전체 테스트 대상에 대해서 테스트가 커버하는 범위로, 전체 소스코드에 대한 테스트가 커버한 소스코드 라인 (라인 커버리지), IF와 같은 분기문에 대한 커버리지를 분석하는 브랜치 커버리지, 전체 기능 대비 테스트한 기능에 대한 기능 커버리지 등이 있다.
3) Defect / Hour :
개발 시간별 발생한 Defect
4) Days test effot / Requirement :
하나의 요구 사항에 대해서 테스트 하는데 소요된 날짜

이러한 Matrix는 전체적인 제품의 품질 현황이나 개선 추이를 그래프로 한눈에 알아볼수 있기 때문에 많은 도움이 되며, 특히 Defect/KLOC, Defect/Hour 등의 척도는 개발 과정에서 발생하는 결함의 수와 이를 해결하는데 필요한 리소스를 산정할 수 있는 지표이기 때문에, 개발과정에서 소요되는 테스트 비용과 인력 계획의 기반 자료로 사용할 수 있다.

Test Designer

테스트 디자이너는 Test Lead에 의해 정의된 전략, 방법론, 프로세스에 따라 테스트 대상 시스템을 분석하고, 상세 테스트 전략을 수립한 후 상세 테스트 케이스를 디자인 한다.

-       Analysis & design test requirement : 테스트 대상 시스템의 기능, 요구 사항과 상세 아키텍쳐를 파악하고, Defect가 발생될 수 있는 부분을 탐색한 후에, Defect의 가능성이 있는 부분을 중심으로, 테스트 전략을 수립한다.

-       Design test case : 테스트 전략을 기반으로, 상세 테스트 케이스를 설계한다.

Test Operator

설계된 테스트 케이스 디자인에 따라서 상세 테스트 케이스를 구현 및 수행 한다.

-       Implement test case : 테스트 디자이너를 기반으로 상세 테스트 케이스를 구현한다.

-       Execute test case : 테스트를 검증하고, 테스트 과정에서 구현된 테스트를 수행한다.

-       Result document : 테스트 수행 과정에서 나온 데이타를 수집하고, 결과를 리포팅 한다.

-       Generate defect report : 테스트 과정에서 결함이 발견된 다면, 결함의 내용과 결함의 발생 절차를 기록한다.

-       Track defect : 향후 결함을 개발팀과 함께 FIX할 때, 개발자와 함께 Defect에 대한 수정에 대해서 의사 소통을 하고, 결함의 해결 과정을 자세하게 리포팅 한다.

-       Test tool set up : 필요에 따라서 테스트에 필요한 툴를 셋업 한다.

Test Environment Manager

일반적인 테스트 조직에서는 존재하지 않는 경우가 많은데, 테스트 환경을 셋업하고 유지하는 역할을 한다.

테스트 환경이란, 테스트 대상이 되는 대상 시스템을 테스트 환경에 배포한 환경과 테스트를 위해 사용되는 부하 발생 툴등의 테스트 툴, 테스트 과정중 대상 시스템을 관측하기 위한 모니터링 시스템 그리고 테스트에서 발견된 결함을 로깅하기 위한 결함 관리 시스템등으로 구성된다.

이런 테스트 환경의 구성은 개발팀 또는 테스트 엔지니어가 겸하는 경우가 많은데, 테스트 환경 구축 자체가 많은 시간이 들기 때문에 이를 구축하는 개발자나 테스트 엔지니어의 리소스가 허비되고 이로 인해서 개발일정이나 테스트 일정에 차질을 가지고 올 수 있기 때문에 명시적으로 테스트 환경을 셋업하고 유지하는 역할을 만들 필요가 있다.

그리고 개통 테스트 단계가 많은 시간이 소요되는 경우가 많은데, 개통 테스트에 많은 시간이 소요되는 주요한 원인은 테스트 환경 셋업과 점검에서 발생하는 경우가 많다. IP가 틀리고, 설정 정보가 잘못되고, 제대로 문서화 되어 있지 않은 등에 사소한 문제인 경우가 대부분인데, 이러한 문제를 사전에 예방하기 위해서

, 구축도 중요하지만 해당 환경을 계속적으로 유지해야 반복적인 회귀 테스트가 가능하다.

-       Set up test environment : 테스트 대상 시스템을 테스트 환경에 배포하고, 테스트에 필요한 테스팅 툴와 모니터링 툴들을 설치 관리한다. 그리고 이 환경에 대한 설정 정보를 문서화 하여 관리한다.

-       Monitor environment during test : 테스트가 진행되는 중에 모니터링 툴를 이용하여 테스트 환경 인프라와 테스트 시스템등에 대한 모니터링을 수행하고, 테스트 진행중 환경에 대한 모니터링 정보를 저장한다.

외부 지원팀

테스트는 대상 시스템에 대한 검증을 수행하는 작업이다. 작게 보면 테스트를 수행하는 조직이 만들지 않은 외부의 것을 검증하는 작업으로, 테스트의 주체는 테스트 대상을 잘 알지 못한다. 그래서 테스트에 필요한 기술적인 지원이 필요하다.

Development Team

테스트 환경에 대한 설정에서 부터 Defect에 대한 해결까지 개발팀에 대한 지원은 필수적이다.

-       Support test environment set up : 테스트 환경에 개발 대상 시스템을 배포한다. 개발 대상 배포 시스템의 설치는 테스트팀이 독립적으로 수행할 수는 없고 테스트 대상 시스템에 대한 지식이 있어야 하기 때문에 개발 당사자인 개발팀의 지원은 필수적이다.

-       Fix defect : 발생된 결함에 대해서 테스트 엔지니어로부터 현상과 관련 자료를 받아서, 결함을 수정하고 이에 대한 확인 작업을 같이 수행한다.

-       Monitoring test : 테스트 과정중에 테스트 대상 시스템에 대한 모니터링을 수행한다.

System Engineer

시스템 엔지니어는 테스트 대상 시스템 이외의 테스트 툴, 모니터링 툴, 하드웨어 인프라나 RDBMS 또는 미들웨어 등에 대한 모니터링 작업을 지원하는 엔지니어이다. 테스트 대상 시스템에 대한 지식은 개발자가 알고 있지만, 미들웨어와 같이 개발에 사용한 기반 시스템등에 대한 지식은 미약한 경우가 많기 때문에, 제품에 대한 전문적인 지식을 가지고 있는 기술 지원 엔지니어의 지원이 있다면 조금더 효율적인 테스트가 가능하다.

-       Monitoring & Tuning : 테스트 대상 시스템 이외의 부분(위에 언급한 부분) 에 대한 제품 모니터링과 튜닝을  지원한다.

'ALM > Test Automation' 카테고리의 다른 글

Selenium WebDriver와 RC 차이  (0) 2013.12.24
Selenium 테스트 메모  (0) 2013.12.24
테스트 팀의 조직 구조  (1) 2012.08.21
JUnit Max  (1) 2009.05.06
Software Testing Proces  (0) 2009.04.09
Cloud 컴퓨팅을 이용한 대용량 Selenium 테스트  (0) 2009.02.18

괜찮은 SOA 테스팅 툴 발견

아키텍쳐 /SOA | 2009.03.16 11:23 | Posted by 조대협
http://www.crosschecknet.com/

SOA 구현시 테스팅이 문제인데, 기존에 SOAP UI만 사용하다가 좋은 툴을 발견
HP TC와 연동도 되고, JUnit형태로도 뽑아져서 Regression(회귀) 테스트에도 반영 가능하단다.
InforWorld에서 SOA 테스팅 툴 부분에서 가장 좋은 점수를 받은 툴

EasyMock을 이용한 단위 테스트

ALM/Test Automation | 2008.11.07 18:06 | Posted by 조대협

 

Unit Test with Easy Mock

자바스터디 조대협(bwcho75@지메일.컴)

 단위 테스트는 소프트웨어 구성 요소의 각 컴포넌트를 독립된 환경에서 테스트 하는 것이다. 그렇지만 일반적으로 소프트웨어 컴포넌트는 혼자서 동작할 수 없고 다른 컴포넌트에 대해서 종속성(Dependency)를 가지고 있기 때문에 종속관계에 있는 컴포넌트가 완성되지 않거나 그 컴포넌트에 오류가 있으면 정상적으로 테스트를 진행할 수 없다.

이 문서를 읽기 전에 먼저 Junit 테스트에 대해서 숙지하기 바란다.
http://bcho.tistory.com/entry/단위-테스트-1회-JUnit

이런 문제를 해결하기 위해서 사용하는 것이 Mock Object 이다. Mock Object는 가상 오브젝트로 테스트를 위한 Operation만을 구현하여 테스트에 사용할 수 있다. 

이러한 Mock Object를 POJO (Plain Old Java Object)로 만들어서 직접 구현할 수 있지만 이러한 경우 모든 Interface를 구현해야 하고, 테스트 케이스가 해당 Mock Object에 대해서 종속성을 가지게 되며, 시나리오에 따라서 Mock Object를 따로 작성해야 하기 때문에 효율성이 떨어진다. 

이러한 문제를 해결하기 위해서 고안된 프레임웍이 EasyMock이라는 테스팅 프레임웍이다. 이 프레임웍은 Junit 3.8X와 4.X와 함께 사용되어 단위테스트에서 Mock Object 생성을 지원한다. 내부적으로 EasyMock은 Java의 Reflection을 이용하여 단위테스트 Runtime에서 가상 객체와 그 객체의 메서드를 생성하여 준다. 

1.       다운 로드 받기

http://www.easymock.org에서 easymock 2.4 를 다운로드 받는다.압축을 풀면 easymock.jar가 나온다. 이 파일을 이클립스 프로젝트내에 클래스 패스에 추가한다.

2.       클래스 작성

작성할 클래스는 RunCaculator라는 클래스로 두개의 메서드를 가지고 있다.

Ø         doSum 메서드는 Caculator라는 클래스를 호출하여 a,b 두개의 값을 더해서 리턴을 한다.

Ø         sayHello  메서드는 Caculator 클래스를 호출하여 입력받은 문자열을 출력한다.

package bcho.easymock.sample;

 

public class RunCaculator {

        Caculator cal;       

        public void setCal(Caculator cal) {

               this.cal = cal;

        }

         // return sum of a and b

        public int doSum(int a,int b){

              System.out.println("## summing "+a+"+"+b+"="+ cal.sum(a, b) ); 

               return cal.sum(a, b);

        }

        // echo string to console

        public void sayHello(String str){

               cal.echo(str);

        }

}

 3.       종속된 인터페이스 작성

Caculator 인터페이스는 두개의 메서드를 가지고 있다.

package bcho.easymock.sample;

public interface Caculator {

        public int sum(int a,int b);

        public void echo(String echo);

}

 Ø         A,B 두개의 값을 더해서 리턴하는 sum 메서드와

Ø         입력 받은 문자열을 화면으로 출력하는 echo 라는 메서드

4.       테스트 케이스 작성

테스트를 하고자 하는 클래스 RunCaculator는 이미 완성되어 있다. 그러나 이 클래스가 사용하는 인터페이스 Caculator에 대한 Implement Class가 없다. 이 Caculator에 대한 클래스를 EasyMock을 이용해서 Simulation 해볼것이다.

Mock Object의 사용 순서는 간단하다.

Ø         Mock Object를 생성한다.

Ø         Mock Object가 해야 하는 행동을 녹화한다. (record)

Ø         Mock Object의 행동을 수행하도록 한다. (replay)

Ø         테스트를 수행한다.

예를 통해서 살펴보자.
EasyMock 을 사용하기 위해서 easymock 정적 메서드들을 아래와 같이 Import 한다.

import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;

 테스트 케이스의 Set up에서 테스트를 할 객체를 생성하고 Mock object를 createMock 메서드를 이용해서 생성한다. 이때 인자는 생성하고자 하는 가상 객체의 클래스명(인터페이스명)을 주면 된다. 

public class CaculatorTest extends TestCase {

        Caculator mock;
        RunCaculator runner;
        protected void setUp() throws Exception {

               mock = createMock(Caculator.class);   // create Mock Object
               runner = new RunCaculator();
               runner.setCal(mock);
               super.setUp();
        }

 

먼저 Mock Object의 행동을 recording해야 하는데,

mock.메서드

로 정의하면 해당 행동이 recording 된다. 만약에 리턴값이 있을때에는

expect(mock.메서드).andReturn(리턴값)

식으로 정의하면된다.

예제를 보고 정리하면 앞으로 불릴 Mock object는 sum(1,2)라는 메서드가 호출될것이고 그에 대해서 리턴값을 3을 리턴한것이다. 라고 정의하는 것이다. sum(1,2)가 아닌 다른 인자로 호출이 되면 미리 레코딩 된 행동이 아니기 때문에 에러가 날것이고 마찬가지로 sum(1,2)가 호출되더라도 1회 초과로 호출되면 이 역시 예상된 행동이 아니기 때문에 에러가 발생된다.

 

        public void testDoSum() {
               expect(mock.sum(1,2)).andReturn(3);   // record mock action
               replay(mock);                         // replay mock          

               this.assertEquals(3,runner.doSum(1,2));              

               verify(mock);
        }

 아래의 예는 일부로 에러를 발생 시킨 경우인데 echo(Hello) 메서드가 한번만 호출되기로 되어 있었는데, 아래 테스트 케이스를 보면 echo(Hello)가 연속으로 두번 호출 된후 echo(Hello bcho)가 한번 호출되기 때문에 에러가 발생된다.

        public void testSayHello() {
               mock.echo("Hello");
               replay(mock);
               runner.sayHello("Hello");
               runner.sayHello("Hello");
               runner.sayHello("Hello bcho");
               verify(mock);

       }