블로그 이미지
평범하게 살고 싶은 월급쟁이 기술적인 토론 환영합니다.같이 이야기 하고 싶으시면 부담 말고 연락주세요:이메일-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도 상당히 낮은 도구이기 때문에 반드시 사용해보기를 권장한다.

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

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'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

Selenium Test Suite 수행

ALM/Test Automation | 2013.12.29 01:50 | Posted by 조대협

Selenium IDE로 만든 Test Case는 Test Suite로 저장해서, command line 상에서 테스트를 수행할 수 있다.


먼저 작성했던, Test cae를 IDE에서 Test Suite로 저장한다.

다음 Command line에서 selenium server를 수행하여, Suite를 실행한다.

java -jar selenium-server-standalone-2.39.0.jar -multiwindow -htmlSuite "{브라우져종류}" "{테스트하고자하는URL}" "{테스트SUITE HTML 파일 경로-절대경로}" "{테스트 결과가 저장될 HTML 파일명"} 으로 수행하면 된다

이때 브라우져 종류는 *chrome으로하면 firefox가, *explorer로 하면, IE를 수행해서 테스트를 수행한다.


예) C:\dev\tools\selenium>java -jar selenium-server-standalone-2.39.0.jar -multiwindow -htmlSuite "*chrome" "http://www.naver.com" "c:\dev\tools\selenium\naver_selenium_sample_suite" "C:\dev\tools\selenium\result.html"


아래는 테스트 결과 생성된 리포트 이다.




저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'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

Selenium WebDriver와 RC 차이

ALM/Test Automation | 2013.12.24 00:20 | Posted by 조대협

How Does WebDriver ‘Drive’ the Browser Compared to Selenium-RC?

Selenium-WebDriver makes direct calls to the browser using each browser’s native support for automation. How these direct calls are made, and the features they support depends on the browser you are using. Information on each ‘browser driver’ is provided later in this chapter.

For those familiar with Selenium-RC, this is quite different from what you are used to. Selenium-RC worked the same way for each supported browser. It ‘injected’ javascript functions into the browser when the browser was loaded and then used its javascript to drive the AUT within the browser. WebDriver does not use this technique. Again, it drives the browser directly using the browser’s built in support for automation


출처 : http://docs.seleniumhq.org/docs/03_webdriver.jsp


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'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

Selenium 테스트 메모

ALM/Test Automation | 2013.12.24 00:11 | Posted by 조대협

Firefox selenium IDE를 이용하여 Record 가능. 간단하게 IDE내에서 Command 추가등도 가능

아래는 네이버에서 "조대협" 으로 검색하여, 검색 결과에 "조대협의 블로그" 문자열이 나오면 성공하는 테스트 케이스 




작성 완료후 Export하면

Java/JUnit 3,4 , Test NG

Ruby,Python,C# 등으로 TG Export 가능


아래는 JUnit4로 Export한 소스 코드

package com.example.tests;


import com.thoughtworks.selenium.*;

import org.junit.After;

import org.junit.Before;

import org.junit.Test;

import static org.junit.Assert.*;

import java.util.regex.Pattern;


public class selenium_TC_naver {

private Selenium selenium;


@Before

public void setUp() throws Exception {

selenium = new DefaultSelenium("localhost", 4444, "*chrome", "http://www.naver.com/");

selenium.start();

}


@Test

public void testSelenium_TC_naver() throws Exception {

selenium.open("/");

selenium.click("id=query");

selenium.type("id=query", "조대협");

selenium.click("id=search_btn");

selenium.waitForPageToLoad("30000");

assertTrue(selenium.isTextPresent("조대협의 블로그"));

}


@After

public void tearDown() throws Exception {

selenium.stop();

}

}

다음은 Junit 4/Web Driver용으로 Export한 소스
package com.example.tests;

import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.Select;

public class SeleniumTCNaverWebdriver {
  private WebDriver driver;
  private String baseUrl;
  private boolean acceptNextAlert = true;
  private StringBuffer verificationErrors = new StringBuffer();

  @Before
  public void setUp() throws Exception {
    driver = new FirefoxDriver();
    baseUrl = "http://www.naver.com/";
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
  }

  @Test
  public void testSeleniumTCNaverWebdriver() throws Exception {
    driver.get(baseUrl + "/");
    driver.findElement(By.id("query")).click();
    driver.findElement(By.id("query")).clear();
    driver.findElement(By.id("query")).sendKeys("조대협");
    driver.findElement(By.id("search_btn")).click();
    // Warning: assertTextPresent may require manual changes
    assertTrue(driver.findElement(By.cssSelector("BODY")).getText().matches("^[\\s\\S]*조대협의 블로그[\\s\\S]*$"));
  }

  @After
  public void tearDown() throws Exception {
    driver.quit();
    String verificationErrorString = verificationErrors.toString();
    if (!"".equals(verificationErrorString)) {
      fail(verificationErrorString);
    }
  }

  private boolean isElementPresent(By by) {
    try {
      driver.findElement(by);
      return true;
    } catch (NoSuchElementException e) {
      return false;
    }
  }

  private boolean isAlertPresent() {
    try {
      driver.switchTo().alert();
      return true;
    } catch (NoAlertPresentException e) {
      return false;
    }
  }

  private String closeAlertAndGetItsText() {
    try {
      Alert alert = driver.switchTo().alert();
      String alertText = alert.getText();
      if (acceptNextAlert) {
        alert.accept();
      } else {
        alert.dismiss();
      }
      return alertText;
    } finally {
      acceptNextAlert = true;
    }
  }
}


저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

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
Software Testing Proces  (0) 2009.04.09

테스트 팀의 조직 구조

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 : 테스트 대상 시스템 이외의 부분(위에 언급한 부분) 에 대한 제품 모니터링과 튜닝을  지원한다.

저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'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

JUnit Max

ALM/Test Automation | 2009.05.06 09:49 | Posted by 조대협
블로그를 기웃거리다가 찾아낸 툴인데
JUnit을 만들고 실행하지 않고, 바로 코딩 단계에서 테스팅을 해줄 수 있는 도구.
직접 동영상을 보는게 이해하기가 빠를듯한데.
상당히 편리하다.
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

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
Selenium (UI 테스트 자동화)  (1) 2009.02.09

Software Testing Proces

ALM/Test Automation | 2009.04.09 10:25 | Posted by 조대협
Testing process
View more presentations from Byungwook.
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

테스트 팀의 조직 구조  (1) 2012.08.21
JUnit Max  (1) 2009.05.06
Software Testing Proces  (0) 2009.04.09
Cloud 컴퓨팅을 이용한 대용량 Selenium 테스트  (0) 2009.02.18
Selenium (UI 테스트 자동화)  (1) 2009.02.09
EasyMock을 이용한 단위 테스트  (4) 2008.11.07

Selenium이 UI Base 테스팅 툴로 널리 쓰이는 것은 기정 사실로 알고 있는 것이고,
대용량 부하 테스트를 할 경우, 환경 마련이 만만하지 않은데,
Amazon의 E2C 클라우드를 이용해서 Selenium으로 대규모 부하 테스트를 할 수 있는 사이트가 있어서 소개 합니다.
인데, Selenium 스크립트를 만든후에, 로드하면 Amazon 클라우드를 이용하여 부하테스트를 하고, 그 결과를 리포팅 합니다.

Load R*와 같은 툴을 사용할 수 없는 곳이나, 이미 Selenium으로 테스트 코드를 구현해 놓은 곳에서는 저비용으로 매우 유용하게 사용할 수 있겠네요.
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

JUnit Max  (1) 2009.05.06
Software Testing Proces  (0) 2009.04.09
Cloud 컴퓨팅을 이용한 대용량 Selenium 테스트  (0) 2009.02.18
Selenium (UI 테스트 자동화)  (1) 2009.02.09
EasyMock을 이용한 단위 테스트  (4) 2008.11.07
테스트 자동화 도구들  (0) 2008.08.07

Selenium (UI 테스트 자동화)

ALM/Test Automation | 2009.02.09 12:46 | Posted by 조대협
UI 테스트 프레임웍이다.
강규영님의 강좌 동영상을 보니까는, Fire Fox에 화면 Recorder까지 나와서 상당히 현실적으로 쉽게 테스트 케이스를 만들 수 있을것 같고..
무엇보다 테스트 스크립트 자체가 Meaningful 하기 때문에, 스크립트가 테스트케이스가 될 수 있다.

그런데 요즘 이상하게 프로젝트 할때 UI테스트할일이 없어진다.
Integration성 프로젝트만 해서 그런지.. 아니면 요즘 RIA CLIENT가 많아서 그런지...
Enterprise System에서는 Pure HTML로 된 페이지를 보기가 힘든것 같다.
저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

Software Testing Proces  (0) 2009.04.09
Cloud 컴퓨팅을 이용한 대용량 Selenium 테스트  (0) 2009.02.18
Selenium (UI 테스트 자동화)  (1) 2009.02.09
EasyMock을 이용한 단위 테스트  (4) 2008.11.07
테스트 자동화 도구들  (0) 2008.08.07
Junit best practices  (0) 2008.03.12
TAG Selenium, test

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);

       }

 


 

 

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

테스트 자동화 도구들

ALM/Test Automation | 2008.08.07 14:49 | Posted by 조대협

www.opensourcetesting.com

selenimum과 함께 쓰기 좋은 도구 http://cubictest.openqa.org/
STAF http://sourceforge.net/projects/staf

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Junit best practices

ALM/Test Automation | 2008.03.12 14:45 | Posted by 조대협
http://www.javaworld.com/javaworld/jw-12-2000/jw-1221-junit.html?page=1

시간 나면 한번 읽어봐야 쓰겄다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

테스트 코드 커버러지와 단위 부하 테스트

(Test Code Coverage & Unit performance test)

 

자바스터디 조대협 (http://bcho.tistory.com)

현재 BEA Systems Korea에서 Senior 컨설턴트로 엔터프라이즈 애플리케이션 개발과 미들웨어 SOA에 대해 컨설팅을 진행하고 있다.

온라인 자바 사이트 http://www.javastudy.co.kr 의 초기 시샵이며, 한국 자바 개발자 협의회 JCO의 초대 부회장을 맏았다.

 

이번 글에서는 테스트가 애플리케이션을 어느정도 테스트했는지를 측정하는 코드 커버러지와, Japex 테스트 프레임웍을 이용한 부하 테스트 방법에 대해서 알아보도록 한다.

1.코드 커버러지 (Code Coverage)

* 테스트 커버러지란?
우리가 단위 테스트나 통합 테스트와 같은 일련의 테스트 작업을 수행하였을때, 이 테스트가 전체 테스트를 해야 하는 부분중에서 얼마만큼을 테스트 했는지를 판단해야 한다.
예를 들어, 20가지의 기능을 가지고 있는 애플리케이션이 있을때, 몇가지 기능에 대해서 테스트를 했는가와 같이, 수행한 테스트가 테스트의 대상을 얼마나 커버했는지를 나타내는 것이 테스트 커버러지이다. 이 커버러지율을 기준으로 애플리케이션이 릴리즈가 가능한 수준으로 검증이 되었는가를 판단하게 된다.

위에서 예를 든것과 같이 기능에 대한 테스트 완료여부를 커버러지의 척도로 삼을 수 도 있다.
좀더 작은 범위의 테스트인 단위 테스트의 경우는 개개의 클래스나 논리적인 단위의 컴포넌트 각각을 테스트하기 때문에, 테스트에 대한 커버 범위를 각각의 클래스 또는 소스 코드의 각 라인을 척도로 삼을 수 있는데, 테스트가 전체 소스코드중에서 얼마나를 커버했는지를 나타내는것이 "코드 커버러지(Code Coverage)" 이다.

* 코드 커버러지 툴의 원리
코드 커버러지 툴의 주요 기능은 실행중에 해당 코드라인이 수행이 되었는가? 아닌가를 검증하는것이다. 이를 위해서 커버러지 툴은 클래스의 각 실행 라인에 커버러지 툴로 로깅을 하는 로직을 추가 하는 것이 기본 원리이다.

예를 들어 아래와 같이 간단한 HelloWorld라는 소스가 있을 때, 소스 커버러지 툴을 거치게 되면 <그림 2> 와 같은 형태의 소스 코드를 생성해내게 된다.

public class HelloWorld(){
  public void HelloBcho(){

  System.out.println(Hello Bcho);

}

public void HelloHyunju(){

System.out.println(Hello Hyunju);

}

}

< 그림 1. 원본 소스 코드 >

 

public class HelloWorld(){
  public void HelloBcho(){

    CoverageTools.log(클래스 및 라인 관련 정보1);

  System.out.println(Hello Bcho);

CoverageTools.log(클래스 및 라인 관련 정보2);

}

public void HelloHyunju(){

CoverageTools.log(클래스 및 라인 관련 정보3);

System.out.println(Hello Hyunju);

CoverageTools.log(클래스 및 라인 관련 정보4);

}

}

< 그림 2. 코드 커버러지 로그 수집이 추가된 코드>

 

그림 2와 같이 변형된 코드가 수행되게 되면 코드 수행에 따른 로그가 생성되게 되고, 이를 분석하여 코드중에 어느 부분이 수행되였는지를 보여주는 것이 코드 커버러지 툴의 기능이다.

이렇게 기존의 클래스에 커버러지 분석을 위한 분석 코드를 추가 하는 작업을 instrument 라고 하고 크게 정적 기법과 동적 기법 두가지를 지원한다.

정적 기법은 애플리케이션이 수행되기 이전에 소스코드나 컴파일이 완료되어 있는 클래스 파일을 instrument하여 instrumented class들을 만든후 그것을 수행하는 방식이고, 원본 class를 가지고 애플리케이션을 수행하여 런타임시에 클래스가 로딩되는 순간에 클래스에 Instrumentation을 하는 것이 동적 방식이다.

 동적 방식은 AOP (Aspect Oriented Programming)이나, APM (Application Performance Monitoring)에서 많이 사용하는 방법이다. 그러나 이 방식의 경우 런타임에서 code instrumentation을 하는 부하가 발생하기 때문에, instrumentation양이 AOP APM에 비해서 압도적으로 많은 Code Coverage툴의 경우에는 정적인 instrumentation 방식이 좀더 유리 하다. 단 정적 방식의 경우 컴파일후에도 instrumentation을 한번 거쳐야 하고, coverage를 분석하기 위한 애플리케이션 묶음(JAR,WAR)과 운영을 위한 애플리케이션 묶음이 다르기 때문에 용도에 따라서 매번 다시 배포(DEPLOY)해야 하는 번거로움이 있다.

 툴에 따라서 instrumentation 방식이 다르기 때문에 애플리케이션의 성격과 규모에 따라서 적절한 instrumentation을 사용하는 툴을 사용하기 바란다.

 

* Cobertura를 이용한 커버러지 분석

많이 사용하는 코드 커버러지 분석 도구로는 상용으로 www.atlassian.com Clover, http://www.instantiations.com/ Code Pro Analytix 등이 있다.

대표적인 오픈소스로는 EMMA Cobertura가 있다. EMMA의 경우 동적,정적 Instrumentation을 모두 지원하며, Eclipse 플러그인도 지원한다.

Cobertura의 경우 정적 Instrumentation만 지원하지만 사용 방법이 매우 쉽기 때문에, 여기서는 Cobertura를 이용한 Code Coverage분석 방법을 설명한다.

Cobertura를 이용하기 위해서는 http://cobertura.sourceforge.net 에서 다운 받아서 설치한다.

<!-- 1)클래스 패스 정의 -->

<path id="cobertura.class.path">

  <pathelement location="${cobertura.home}/cobertura.jar"/>

  <fileset dir="${cobertura.home}/lib" includes="*.jar" />

</path>

 

<!-- 2) 태스크 정의 -->

<taskdef resource="tasks.properties" classpathref="cobertura.class.path" />

 

<!-- 3) 빌드 -->

<target name="build">

<!-- 컴파일후에, EAR 파일로 패키징을 한다. -->

<javac debug=true >

</target>

 

<!-- 4) Code Instrumentation -->

<target name="instrument_cobertura" dependes="build">

 <cobertura-instrument todir="${workspace.dir}"

  datafile="${workspace.dir}/cobertura.ser" >

   <includeClasses regex="bcho.*" />

   <instrumentationClasspath>

      <pathelement location="${ear.file}/>

   </instrumentationClasspath>

  </cobertura-instrument>

</target>

 

<!-- 5)Code Coverage Report generation -->

<target name="report_cobertura" >

   <cobertura-report format="html" desdir="리포트 HTML이 저장될 디렉토리"

      datafile="${workspace.dir}/cobertura.ser">

      <fileset dir="원본 소스 코드가 있는 디렉토리 >

           <include name="**/*.java" />

   </cobertura-report>

</target>

< 그림 3 . Cobertura 사용을 위한 ANT TASK >

 

1) Cobertura를 인스톨한 디렉리를 ${cobertura.home} Property로 정의하고, 클래스 패스를 지정한다.

2) Cobertura에 대한 ANT TASK를 이용하기 위해서 <taskdef>를 이용하여 cobertura classpath에 정의된 TASK를 정의한다.

3) 다음으로 애플리케이션을 빌드하고, JAR WAR,EAR등으로 패키징한다. (Instrument code를 넣기 위해서 패키징은 필수 사항은 아니다. ) 이때 커버러지 분석에서 결과가 제대로 표시되게 하기 위해서 <javac> 컴파일 옵션에 debug=true를 추가한다.

4) 컴파일과 패키징이 완료된 자바 애플리케이션에 대한 Instrumentation을 수행하기 위해서 <cobertura-instrument> 테스크를 사용한다.

 todirInstrument된 애플리케이션 (EAR Instrument할 경우, Instrument EAR파일이 이 경로에 저장된다.) 저장될 디렉토리이며, datafile은 커버러지를 분석한 결과 데이터를 저장할 파일명이다.

 다음으로 커버러지를 분석할 클래스명을 지정하는데, <includeClasses> 라는 엘리먼트를 이용하여, regular expression을 사용하여 클래스의 범위를 지정한다. 예제에서는 bcho.*로 시작하는 패키지의 클래스만 Instrument를 하도록 지정하였다.

 그리고 마지막에 Instrument를 할 class 파일들의 위치를 지정하는데, <instrumentationClasssPath> class들이 저장된 경로를 지정하거나 또는 EAR등으로 패키징된 파일 경로를 지정한다.

 예제에서는 EAR파일을 Instrument하는것으로 지정하였다.

여기까지 진행한후 ant instrument_cobertura를 수행하면, ${workspace.dir} instrumented ear 파일이 생성된다.

 

Instrumented 된 애플리케이션을 서버에 배포하거나 단독 수행 애플리케이션일 경우 실행을 한다. 이때 JUnit을 이용한 테스트를 수행해도 되고, 손으로 직접 기능을 수행해봐도 된다. Instrumented 된 애플리케이션은 모든 수행 결과에 대한 로그를 저장하기 때문에 특정 테스팅 프레임웍을 사용하지 않아도 된다.

이때 수행되는 애플리케이션에 Cobertura에 대한 Coverage 로그를 저장할 디렉토리를 지정해야 하는데, JAVA에서 -D옵션을 이용하여

 -Dnet.sourceforge.cobertura.datafile=위의 ANT 스크립트에서 지정한 *.ser 파일의 절대 경로

를 지정해야 *.ser파일에 제대로 커버러지 분석 결과가 저장된다.

 

필자의 경우에는 JUnit + Cactus를 이용하여 EJB 2.1 WebLogic에서 수행하였다.

애플리케이션의 실행 또는 테스트가 끝난후 애플리케이션을 종료하면 (WAS의 경우 WAS를 종료해야 한다.) 종료시에 커버러지 데이터를 *.ser 파일에 기록하게 된다. (런타임시에는 *.ser파일에 결과가 기록되지 않는다.)

 

*.ser파일에 기록된 커버러지 분석 값은 바이너리 형태로 사용자가 볼 수 없기 때문에 이를 리포트로 생성한다.

<그림 3>에서 "report_cobertura 라는 타겟을 정의하였는데,

<cobertura-report> 엘리먼트에서 HTML 리포트가 저장될 디렉토리를 destdir로 지정하고, *.ser의 위치를 datafile attribute로 지정한다.

 그리고, 원본 소스 코드가 있는 디렉토리를 <fileset>으로 지정해주면 destdir HTML형식으로 커버러지 분석 리포트가 생성된다.

사용자 삽입 이미지

<그림 4. 테스트 커버러지 클래스 레벨 리포트 >

그림 4에서 보는것과 같이 전체 코드에 대해서 테스트가 전체 코드중 몇 %를 수행했는지를 나타내 준다. 결과에서 주의할점은 HelloEJBBean의 경우 86%의 커버러지가 나오지만 나머지 클래스들은 N/A 또는 0%가 나온다.

 이는 EJB 2.1로 코딩한 EJB의 경우 사용자는 HelloEJBBean만 코딩을 하지만 나머지 클래스들은 빌드과정에서 WAS가 자동으로 생성해주는데, 자동으로 생성된 클래스(Home, Interface,Stub )에 대한 위치 정보가 없기 때문에, N/A또는 0으로 그 결과가 표시되는 것이다. 이런 경우에는 <cobertura-instrument> 엘리먼트에서 <includeClasses>와 같은 엘리먼트로 <excludedClasses>라는 엘리먼트를 이용하여 특정 클래스들을 Instrumentation에서 제거할 수 있다.

 이런 경우에는 <excludedClasses regex=*Home /> 등을 정의해서 자동 생성되는 클래스들을 제거하거나 또는 반대로, <included Classes=bcho.*\.*Bean/> 으로 해서 bcho.* 패키지에서 Bean으로 지정되는 부분에 대해서만 Instrumentation을 수행할 수 있다.

 

사용자 삽입 이미지

<그림 5. 테스트 커버러리 코드 레벨 리포트 >

 

연두색으로 표시되는 부분, (27,35,41,42,43,47 라인)은 수행된 라인이고 그 옆에 숫자는 수행된 횟수를 나타낸다.

분석 결과를 보면 sayHello 메서드에서 isMale이 항상 true 14번 수행이 되었고 false인 경우에 대한 코드는 수행 되지 않았음을 확인할 수 있다.

 

여기 까지 간단하게 Cobertura를 이용한 코드 커버러지 분석 방법에 대해서 알아보았다.

 

* 코드 커버러지의 척도

코드 커버러지 분석에서 가장 어렵고 논란의 여지가 많은 부분은 목표 커버러지율이다. 혹자들은 테스트가 80% 이상의 코드 커버러지를 가져야 한다고 주장하는데, 일반적인 Value Object 그 많은 Util 클래스등등을 감안할 때, 80%는 상당히 높은 수준이다. 필자의 경우에는 60%도 쉽지 않는 수준이라도 보는데, 이 척도에 대한 기술적인 지표가 필요할 경우 CMM(Capability Maturity Model)등을 참고하기 바란다.

 개인적인 생각으로는 Coverage rate를 올리는 것 보다 중요도가 높은 모듈의 Coverage rate만을 관리하는 것이 효율적이라고 생각한다.

 전체 클래스가 1000개가 있을 때, 이 클래스들을 논리적인 컴포넌트로 묶은 후 (UML Conceptual Mode, Logical Model, Implementation Model Logical Model 단위로) 이 소프트웨어 컴포넌트에 대한 위험도와 복잡도를 지정하여 이를 Ranking하여 상위 순서에서 기준에 따라서 중요 컴포넌트만 Test Coverage를 관리하도록 하는 것을 권장한다.

 커버러지 분석에 대한 수치는 고객이나 메니져 입장에서 전체 시스템중 80%가 테스트 되었습니다.와 같은 의미로 받아 들여지기 때문에, 30%,60% 와 같은 기준은 받아들여지기가 어렵다. 몇 달은 테스트를 했는데, 60% rate로 매우 중요한 시스템을 오픈한다면 당신이라면 accept하겠는가?

 그렇지만 실제 애플리케이션의 전체 코드를 테스트 하는 것은 어렵고 대부분 중요 문제는 상위 10~30%의 모듈에서 발생한다. 만약 100%의 테스트 커버러지가 가능하다면 IBM이나 MS와 같은 첨단 거대 기업에서 만든 소프트웨어들에서 버그가 존재하고, 우주로 쏘아 올리는 로켓에서 문제가 생기겠는가?

 그래서 테스트 코드 커버러지를 도입하기 전에 무엇보다 중요한 것은 어떤 툴이나 커버러지 분석을 자동화하는 것이 아니라, 코드 커버러지를 적용할 소프트웨어 컴포넌트의 범위와 목표 커버러지율을 정의하고 이에 대해서 이해 당사자 (Stakeholder-고객,메니져 등)로부터 동의를 얻어내는 것이 선행되어야 한다.

 그후에 테스트 코드 커버러지 검사를 통해서 특히 단위 테스트의 정확도를 높이는 방향으로 애플리케이션의 완성도를 높이는 방향으로 개발을 진행하도록 한다.

 

2.부하 테스트 (Stress Test)

마지막으로 살펴볼 부분은 단위테스트에 대한 부하테스트에 대해서 살펴보고자 한다.

 

* 부하 테스트

부하테스트는 대상 애플리케이션에 동시에 대용량의 요청을 넣어서, 애플리케이션의 가용 용량, 속도와 같은 성능적인 척도를 측정하고, 대용량 요청시에도 애플리케이션이 문제가 없이 작동하는지를 확인하는 과정이다. (1회의 테스트 과정에서 설명하였다.)

보통 Load Runner Apache JMeter,MS WebStress등을 이용하여 애플리케이션의 기능에 대해서 부하 테스트를 수행하지만, 여기서 설명하고자 하는 부하테스트는 소프트웨어 컴포넌트에 대한 부하 테스트 이다.  필자의 경우 이를 국지적 부하테스트 라고 정의 하는데, 단위 테스트에 대해서 부하를 넣어서 테스트를 진행하는 방법이다.

 부하 상태에서 소프트웨어 컴포넌트에서 발생할 수 있는 문제는 크게 응답 시간 저하와, synchronized 또는 IO에 의한 lock 경합 현상,deadlock 그리고 메모리 사용량에 대한 이슈가 가장 크다. 이런 문제는 대규모의 전체 애플리케이션 부하테스트가 아니더라도 국지적인 단위 테스트에 대해서 부하를 줄 경우에도 어느정도 검출이 가능하다.

 

이런 단위테스트에 대한 부하 테스트로는 성능 테스트 프레임웍으로 JUnitPerf등이 있지만 여기서는 Japex라는 테스팅 프레임웍을 설명하도록 한다. (http://japex.dev.java.net )

Japex의 경우 별도의 코딩을 할 필요가 없이 기존의 JUnit에 설정을 추가하는 것만으로 JUnit에 대해서 부하 테스트가 가능하다.

 

* Japex를 이용한 부하 테스트

Japex를 사용하기 위해서는 http://japex.dev.java.net에서 Japex 라이브러리를 다운 받은후

java com.sun.japex.Japex config파일

로 수행하면 된다.

또는 같은 방식으로 ANT task에서 정의할 수 있다.

<pathelement id="class.path">

  <pathelement location="컴파일된 애플리케이션 클래스패스"/>

  <fileset dir="${JAPEX_HOME}/lib" includes="*.jar"/>

  <fileset dir="${JAPEX_HOME}/jsdl" includes="*.jar"/>

  <fileset dir="컴파일된 애플리케이션 클래스패스"/>

</pathelement>

 

<target name="run_japex">

 <java dir=." fork="true" classname="com.sun.japex.Japex" >

   <classpath refid="class.path" />

   <arg line="${Japex config 파일}" />

 </java>

</target>

< 그림 6. Japex ANT 스크립트 >

 

다음으로 japex config 파일을 지정해야 하는데 다음과 같이 지정한다.

<?xml version="1.0" encoding="UTF-8"?>

<testSuite name="ParsingPerf" xmlns="http://www.sun.com/japex/testSuite" >

 <param name="japex.classPath" value="애플리케이션이 빌드된 디렉토리 (클래스 경로)" />

 <param name="japex.classPath" value="Japex home/jsdl/*.jar" />

 <param name="japex.resultUnit" value="ms" />

 <param name="japex.wrampupTime" value="0" />

 <param name="japex.runtime" value="00:03" />

 <param name="japex.numberOfThreads" value="20" />

 

 <driver name="JUnitDriver">

   <param name="japex.driverClass" value="com.sun.japex.jdsl.junit.JUnitDriver"/>

 </driver>

 

 <testCase name="testHello">

  <param name="testName" value="bcho.test.junit.HelloWorldTestCaseWrapper" />

 </testCase>

</testSuite>

 

<그림 7. Japex config 파일 ${Japex config 파일} >

 

중요한 parameter로는

l        japex.resultUnit 은 성능 결과치에 대한 단위 (, 밀리세컨드 등)

l        japex.wrampumTime은 성능 테스트시 본 테스트전에 시스템을 워밍업 하는 시간 (캐쉬 초기화등등).

l        japex.runtime은 실제 테스트를 수행하는 시간

l        japex.numberOfThreads는 동시에 부하를 주는 클라이언트 수이다.

그리고 JUnit Japex로 호출하기 위해서 driver JUnit 드라이버를 지정하여 로딩하고 <testCase> 엘리먼트에 testName으로 JUnit 테스트 슈트를 지정하여 해당 슈트가 Japex의 설정에 따라 부하테스트가 되도록 한다.

테스트가 끝나면 테스트 결과를 다음과 같이 여러 형태의 그래프로 표현할 수 있다.

사용자 삽입 이미지사용자 삽입 이미지

< 그림 8. Japex로 생성한 성능 테스트 그래프 >

 

매우 간단하게 Japex를 이용한 단위 부하테스트를 소개했지만, Japex JUnit 뿐만 아니라 driver를 추가함으로써 여러 형태의 부하테스트를 지원할 수 있고, 상당히 여러 종류의 그래프를 출력할 수 있으며 개발자에게 별도의 개발이 없이 기존의 JUnit을 재활용하여 부하테스트를 가능하게 해주기 때문에, 상당히 유용한 테스팅 프레임웍이다.

 

3. 맺음말

지금까지 3회에 걸쳐서 자바 단위 테스트의 기본이 되는 JUnit, J2EE에서 유용한 DBUnit Cactus와 같은 확장된 프레임웍, 테스트 검증을 위한 커버러지 분석툴 그리고 단위 부하테스트까지 간단하게 살펴보았다.

사실 테스트에 대한 범위는 매우 넓고 광범위 하다. 우리가 살펴본 내용은 이제 막 걸음마를 뗀 수준에 불과 하지만, 단위 테스트가 무엇이고 어떻게 진행해야 할것인가에 대한 방향성을 제시하기 위한 내용이다.

 반드시 기억해야 하는 내용은

 테스트는 도입해야 한다.

 어떤 테스트 툴을 도입 하는가 보다는 어떻게 테스트를 할것인가?

가 가장 중요하다.

 

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

확장된 단위 테스트 도구

(Cactus & JUnitEE)

 

자바스터디 조대협 (http://bcho.tistory.com)

 지금까지 기본적인 단위 테스트 도구에 대해서 알아보았다.

좀더 상세화된 단위 테스트의 단계를 나눠 보면 다음과 같이 나눠볼 수 있다. 

l        Type 1.코드 단위 테스트

코드상의 로직에 대해서만 테스트를 수행한다.앞 장에서 살펴본 테스트 방법이 일반적인 코드 단위 테스트 방법이다.

그러나 EJB,Servlet과 같은 J2EE 컴포넌트에 대해서 로직이 Dependency를 가지는 경우에는 EJB,Servlet 객체를 직접 연동하는 경우 container (WAS)에 배포하고, 기타 환경 설정이 필요하기 때문에, 로직 테스트를 위해서는 container 환경을 구성하기 전에 동일한 인터페이스를 가지면서 실제 로직은 없고 간단한 return값만 주는 가상의 객체 (Mock Object)이용해서 테스트 한다. Mock Test의 경우는 Spring IOC (Inversion of control)의 기능을 이용하면 좀더 쉽게 테스트할 수 있다. 

l        Type 2. In-Container 테스트

In container테스트는 , 컴포넌트들의 상호 작용과 컴포넌트와 컨테이너간의 상호작용을 테스트 하는 케이스 인데, POJO기반의 객체의 경우 문제가 없지만 J2EE와 같이 Container 위에서 동작하는 컴포넌트인 경우 Container에 배포하고, Container내에서 테스트 케이스를 수행해야 한다.

예를 들어 Servlet 클래스는 WAS환경 위에서만 작동하기 때문에, 테스트 하기 위해서는 JUnit이용하여 Pure Java환경에서는 테스트할 수 없으며 반드시 WAS 환경위에서 테스트가 필요하다. 이렇게 Container 환경내에서 테스트하는 것을 in-container 테스트라 하며,이를 지워하는 테스트 프레임웍으로는 JUnitEE Apache Cactus 테스트이 있다.  

l        Type 3. Acceptance 테스트

사용자 요구 사항에 대한 기능 테스트 이다. 좀더 쉽게 설명하면 사용자의 Use Case에 대한 시나리오에 따라 테스트를 하는것인데, 예를 들어 사이트에 LogIn해서 Form에 어떤 값을 넣고 submit 버튼을 누르면 화면상에 어떤 데이터가 출력되어야 한다는 등의 기능적 시나리오에 대한 테스트 이다. HTML 기반의 기능 테스트를 지원하는 테스트 프레임웍으로는 HttpUnit과 이를 확장한 JWebUnit등이 있다. 

l        Type 4.성능 단위 테스트

Type 1~3는 기능에 대한 테스트를 수행하였다면, Type 4는 비기능적인 이슈중에서 성능에 대한 테스트 방법으로, 각 단위 컴포넌트의 수행 시간에 대한 테스트를 수행하는 것이다. 성능 단위 테스트를 지원하는 프레임웍으로는 JPerfUnit등이 있다. 

지금까지 확장된 단위 테스트 방법에 대해서 살펴보았다. 지금부터는 이런 확장된 단위테스트를 수행할 수 있는 구체적인 테스트 프레임웍에 대해서 소개하고자 한다. 

(1)  In-container test - Catcus & JUnitEE

Type 2에서 언급한 in-container 테스트를 위한 프레임웍으로는 Apache Catcus JUnitEE이 있다.

두 프레임웍 모두 In-container 테스트를 가능하게 해주지만, JUnitEE의 경우 Catcus에 비해서 상대적으로 사용하기가 쉽다.JUnit TestCase를 구현해주고 JUnitEE의 서블릿을 설치하면, WAS에 리모트로 테스트를 수행할 수 있으며, 웹브라우져로도 테스트가 가능하다.

 Catcus의 경우 사용법은 JUnitEE에 비해서는 비교적 어렵지만, Servlet,JSP,TagLib에 대한 좀더 전문화된 테스트 프레임웍을 제공한다. 

 

EJB의 경우 Remote Interface가 있는 경우에는 In-container가 아니더라도 WAS외부에서 JUnit이용해서 테스트가 가능하지만, Local Interface만 구현한 경우에는 In-container 테스트만 가능하다. Servlet,JSP를 제외한 EJB,JMS,JNDI등의 J2EE컴포넌트들은 In-container test가 아니더라도, JUnit이용하여 리모트로 테스트 하는 것이 가능하다.

그러나 J2EE 솔루션 패키지(EAI,EP,ESB) 의 경우 J2EE의 호출 환경이 container 내에서만 호출되도록 디자인된 경우도 있기 때문에 필수적으로 In-container 테스트를 진행해야 할경우도 있다.

 In-container test의 경우 별도의 테스트 프레임웍 도입에 대한 비용(시간과 교육)이 필요한 만큼 필요성에 대해 고민한 다음 도입 여부를 결정하는 것이 필요하다.

 

 1)    JUnitEE

JUnitEE는 단순하게, TestCase를 컨테이너 안에서 수행할 수 있게 해주는데 그 목적을 둔다. 앞에서 작성한 JUnit 테스트 클래스인 HelloWorldTest EmpDAOTest Tomcat 컨테이너 안에서 수행해보자

 먼저 JUnit,DBUnit,JUnitEE 라이브러리를 다운로드 받은 후 dbunit-2.2.jar,junit.jar junitee.jar webapp WEB-INF/lib 디렉토리에 복사한다.

WEB-INF/web.xml JUnitEETestServlet을 아래와 같이 설정한다.

 

  <servlet>

    <servlet-name>JUnitEETestServlet</servlet-name>

    <description>JUnitEE test framework</description>

    <servlet-class>org.junitee.servlet.JUnitEEServlet</servlet-class>

  </servlet>

 

  <servlet-mapping>

    <servlet-name>JUnitEETestServlet</servlet-name>

    <url-pattern>/TestServlet/*</url-pattern>

  </servlet-mapping>

< 예제. JUnitEE 테스트 서블릿 설치 >

WEB-INF/testCase.txt라는 파일을 아래와 같이 작성한다. 이 파일에는 TestCase 클래명을 정의한다. 이 클래스명으로 JUnitEE가 단위테스트를 실행할 수 있게 된다.

# test Case Def

bcho.test.HelloWorldTest

bcho.simpledb.test.EmpDAOTest

<예제. JUnitEE에서 테스트 클래스를 지정하는 방법 >

위의 방법은 testCase.txt이용하여 TestCase를 지정하는 방법인데, 그 외에도 JUnitEEWar Ant task이용하여 자동으로 testCase.txt를 생성해낼 수 도 있으며 또는 web.xml servlet init parameter testCase가 들어있는 jar파일을 지정하는 방법등을 이용하여 테스트 케이스 클래스를 지정할 수 있다.

다음으로 Tomcat을 기동한후 http://ip:port/webapp_contextname/TestServlet을 수행한다.

사용자 삽입 이미지

<그림. JUnitEE의 테스트 선택화면 >

웹 화면상에서 등록한 테스트 케이스를 확인할 수 있으며 선택해서 테스트를 진행하게 되면, 다음과 같이 결과를 웹상으로 확인할 수 있다.

사용자 삽입 이미지
< 그림 JUnitEE의 테스트 결과 >

간단하게 JUnitEE이용해서 In-container 테스트를 수행하는 방법에 대해서 알아보았다.EJB JMS같은 J2EE컴포넌트들 역시 같은 방법으로 테스트가 가능하다.

또한 예제의 테스트 방법은 웹브라우져를 통해서 테스트를 수행하는 방법이었는데, 이 외에도 ant task이용해서 ant이용하여 테스트 자동화에 포함하는것도 가능하다. 

2)     Cactus

( http://jakarta.apache.org/cactus/)

또다른 in-container 단위 테스트 프레임웍인 Cactus  에 대해서 알아보자, Cactus Apache 자카르타 프로젝트의 일부로,JUnitEE JUnit 클래스를 서버에서 단순호출 해주는데 비해서 Cactus J2EE컴포넌트에 대한 좀더 정교한 테스트를 지원한다.

Cactus에서 지원하는 J2EE 컴포넌트로는 Servlet/JSP, Filter, TagLib,EJB 테스트들이 있으며, 이러한 테스트를 위한 클래스들을 지원한다.

 예를 들어 Servlet을 테스트하고자 할 때 JUnitEE를 사용하면 단순한 Java 객체로밖에 Servlet을 테스트할 수 밖에 없다. 그러나Servlet을 제대로 테스트하기 위해서는 HttpRequest 내용을 채워넣고, Servlet을 수행한후 Cookie Session 값들을 체크하고, HttpResponse의 내용을 체크해야 한다. 이런 일련의 작업들을 개발자가 일일이 Pure Java Code이용해서 테스트 코드를 만들어내기란 여간 까다로운 작업이 아니다.

 Cactus에서는 이러한 HttpRequest,Cookie,HttpReponse,Session,ServletConfig Servlet을 테스트하기 위해서 필요한 클래스들을 내장 클래스 형식으로 지원하여 쉽게 Servlet을 테스트할 수 있도록 해준다.

 JSP ServletFilter들도 마찬가지 원리로 지원해주게 된다. 

이해를 돕기 위해서 간단한 서블릿을 테스트하는 환경을 만들어보자.

서블릿은 Http Request를 통해서 id passwd를 입력받고, 이 값을 비교해서 맞으면 session id값을 저장하고 Login이 성공하였음을 response로 보내는 간단한 서블릿이다.

public class LogInServlet extends HttpServlet {

 

  public void doGet(HttpServletRequest req, HttpServletResponse res)

      throws ServletException, IOException {

 

    PrintWriter out = res.getWriter();

    HttpSession session = req.getSession();

 

    String id = req.getParameter("id");

    String passwd = req.getParameter("passwd");

 

    if(checkLogin(id,passwd)){

        // 로그인이 성공하였으면 세션에 ID 저장한다.

        session.setAttribute("id", id);

          out.print(id+" Login failed");

    }

   

    out.print(id+" Login success");

}// doGet

:

 

< 테스트할 서블릿 > 

이 서블릿을 테스트하기 위해서 Cactus로 테스트 케이스를 만든후, id passwd HttpRequest로 보낸후, session id가 저장되는지 확인한후, HttpResponse“success” 라는 문자열을 리턴하는지 확인하면,  서블릿이 정상적으로 동작하는 것을 확인할 수 있다.

Cactus로 만드는 테스트 클래스는 org.apache.cactus.ServletTestCase를 상속 받아서 구현되어야 하며, beginXXX testXXX,endXXX 메서드를 구현해야 한다.

beginXXX메서드는 test를 수행하기 전에 WebRequest 객체를 받아서 HttpRequest를 만드는 역할을 하고, testXXX에서는 실제로 테스트를 수행하며, endXXX에서는 Servlet의 수행이 끝난후에 WebResponse 객체를 받아서 HttpResponse 내용으로 테스트 결과를 검증하는 과정을 거친다. 

아래 샘플코드를 살펴보자

package bcho.servlet.test.catcus;

 import org.apache.cactus.Cookie;

import org.apache.cactus.ServletTestCase;

import org.apache.cactus.WebRequest;

import org.apache.cactus.WebResponse;

 import bcho.servlet.LogInServlet;

 public class TestLogInServlet extends ServletTestCase{

       public void beginLogin(WebRequest theRequest)

       {

             theRequest.addParameter("id", "bcho");

             theRequest.addParameter("passwd","passwd");

       }

       public void testLogin()

       {

           LogInServlet servlet = new LogInServlet();

             try{

                 servlet.init(config);

                

                 // Call method to test

                 servlet.doGet(request, response);

           }catch(Exception e){

               e.printStackTrace();

               assertTrue(false); // Exception 발생하였을 경우 실패로 간주한다.

               return;

           }

           // Perform some server side asserts

      

           assertEquals("bcho", session.getAttribute("id"));

       }

 

       public void endLogin(WebResponse theResponse)

       {

           // Asserts the returned HTTP response

             // 리턴되는 HTML 로그인 성공 메세지가 있는지 확인한다.

             String responseTxt = theResponse.getText();

             assertTrue(responseTxt.indexOf("success") > 0);

            

       }

 

}

< Cactus 서블릿 테스트 케이스 >

 beginLogin에서 request객체에 addParameter id passwd를 저장한다.testLogin에서 servlet.doGet을 수행하고, session“id”“bcho”라는 문자열이 저장되었는지 확인한다.endLogin에서는 servlet에서 나온 HttpResponse“success”라는 문자열이 있는지를 확인한다.

서블릿과 서블릿 테스트 클래스가 완성되었으면 이 환경을 서버에 배포해서 테스트를 수행해보자.

먼저 WEB-INF/lib 디렉토리에 http://jakarta.apache.org/cactus 에서 다운 받은 cactus 관련 라이브러리를 복사한다.

( cactus.jar , common-httpclient.jar,common-logging.jar, junit.jar , aspectjrt.jar ) 다음으로 위에서 만든 서블릿 클래스들을 WEB-INF/classes의 패키지 디렉토리에 알맞게 복사한다. 

다음으로 cactus 서블릿들인 ServletRedirector ServletTestRunner 클래스를 WEB-INF/web.xml에 다음과 같이 설정한다.

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

  <display-name> Einstein Unit Tester Web Application </display-name>

       <servlet>

         <servlet-name>ServletRedirector</servlet-name>

         <servlet-class>org.apache.cactus.server.ServletTestRedirector</servlet-class>

         <init-param>

           <param-name>param1</param-name>

           <param-value>value1 used for testing</param-value>

         </init-param>

       </servlet>

     

       <servlet>

         <servlet-name>ServletTestRunner</servlet-name>

         <servlet-class>org.apache.cactus.server.runner.ServletTestRunner</servlet-class>

       </servlet>

      

       <servlet-mapping>

           <servlet-name>ServletRedirector</servlet-name>

           <url-pattern>/ServletRedirector</url-pattern>

       </servlet-mapping>

      

       <servlet-mapping>

           <servlet-name>ServletTestRunner</servlet-name>

           <url-pattern>/ServletTestRunner</url-pattern>

       </servlet-mapping>

 

      

</web-app>

 

 서버를 기동하고, 웹브라우져에서 다음과 같은 URL로 접근하면 테스트 결과를 얻을 수 있다.

http://{ip}:{port}/{context-root}/ServletTestRunner?suite={서블릿테스트클래스명}

 필자는 localhost 8080포트에서 context-root Catcus로 배포하였고, 테스트 서블릿은 위에서 작성한데로, bcho.servlet.test.catcus.TestLogInServlet으로 구성하였기 때문에, 테스트 URL은 아래와 같이 구성 된다.

 http://localhost:8080/Catcus/ServletTestRunner?suite=bcho.servlet.test.catcus.TestLogInServlet

 브라우져에서 테스트해서 테스트가 성공하면 다음과 같은 결과를 얻을 수 있다. 

사용자 삽입 이미지

XML 형식이 아니라 좀더 정재되고 보기 편한 형태로 테스트 리포트를 보고 싶을 경우에는 Apache Jakarta 프로젝트에서 제공하는 XSL을 적용하면 되는데, XSLhttp://jakarta.apache.org/cactus/misc/cactus-report.xsl 에서 다운 받을 수 있다.

다운 받은 cactus-report.xsl WebApplication context-root 디렉토리에 저장한후에 QueryString으로 xsl=cactus-report.xsl xsl 파일을 다음과 같이 지정할 수 있다. http://localhost:8080/Catcus/ServletTestRunner?suite=bcho.servlet.test.catcus.TestLogInServlet&xsl=cactus-report.xsl

 XSL을 저장하여 리포트를 생성한 결과는 다음과 같다. 

사용자 삽입 이미지

지금까지 Catcus이용해서In-container 테스트를 하는 방법을 살펴보았다.

테스트를 브라우져에서 진행하였는데, 단위테스트는 위에서도 설명하였듯이 빌드 작업의 일부로 진행이 되고, 빌드는 통상적으로 자동화가 되기 때문에 Catcus이용한 단위테스트 역시 빌드과정에 자동화되어 포함되어야할 필요가 있다.

지금부터는 대표적인 자바 빌드 도구인 ANT를 통해서 Catcus 테스트를 자동화하는 방법에 대해서 알아보도록 하자.

 먼저 디렉토리 구조를 살펴보자, 필자의 경우 다음과 같은 디렉토리 구조를 구성하였다.

사용자 삽입 이미지
*.java 파일은 src 디렉토리에 위치하였으며, 개발에 필요한 각종 jar 파일은 lib 디렉토리에 저장하였다. web.xml과 같은 config 파일은 conf 파일에 저장하였다.

 ANT로 빌드를 진행하면, *.class 파일은 ./build 디렉토리에 저장되고, ./build디렉토리에 저장된 클래스와 ./lib 디렉토리의 라이브러리 그리고 ./conf/web.xml 파일은 pack 디렉토리에서 Cactus.war라는 파일로 패키징되서 저장된다.

 다음은 작성한 ANT 스크립트이다. BUILD에서부터 WAR 파일 생성까지를 진행하고, “cactus-test” 라는 task에서 cactus 테스트를 수행하도록 설정하였다. (진하게 블록으로 표시한 부분) 빌드와 패키징 부분에 대한 설명은 생략하고 cactus 이용 ANT TASK 부분을 살펴보자. 

<project name="CactusTest" default="cactus-test" >

         <!--

       ============================================================================================

        기본 환경 정보 설정

        =============================================================================================

        -->    

        <!-- 기본 디렉토리 정보 -->

        <property name="project.name" value="Cactus"/>

        <property name="lib" value="./lib"/>

        <property name="src" value="./src"/>

        <property name="build" value="./build"/>

        <property name="packaging" value="./pack"/>

        <property name="conf" value="./conf"/>

 

        <property name="cactus.home" value="D:\dev\lib\jakarta-cactus-13-1.7.2"/>

        <property name="cactus.testlog" value="c:\temp\test-report"/>

        <property name="tomcat.home" value="D:\dev\apache-tomcat-5.5.23\"/>

 

        <!-- jar 파일 경로 -->

        <property name="cactus.jar" value="${cactus.home}/lib/cactus-1.7.2.jar"/>

        <property name="cactus-ant.jar" value="${cactus.home}/lib/cactus-ant-1.7.2.jar"/>

        <property name="commons-httpclient.jar" value="${cactus.home}/lib/commons-httpclient-2.0.2.jar"/>

        <property name="commons-logging.jar" value="${cactus.home}/lib/commons-logging-1.0.4.jar"/>

        <property name="aspectjrt.jar" value="${cactus.home}/lib/aspectjrt-1.2.1.jar"/>

        <property name="cargo.jar" value="${cactus.home}/lib/cargo-0.5.jar"/>

        <property name="servletapi.jar" value="${lib}/servletapi-2.3.jar"/>

        <property name="junit.jar" value="${lib}/junit-3.8.1.jar"/>

 

        <!-- class path 설정 -->

        <path id="cactus.classpath">

            <pathelement location="${cactus.jar}"/>

            <pathelement location="${cactus-ant.jar}"/>

            <pathelement location="${commons-httpclient.jar}"/>

               <pathelement location="${commons-logging.jar}"/>

               <pathelement location="${aspectjrt.jar}"/>

               <pathelement location="${cargo.jar}"/>

               <pathelement location="${junit.jar}"/>

        </path>

        <!--

        =============================================================================================

        Task 정의

        =============================================================================================

        -->    

        <!-- Cactus task 정의 -->

        <taskdef resource="cactus.tasks" classpathref="cactus.classpath"/>

       

        <!-- Clean -->

        <target name="clean">

               <delete dir="${build}"/>

               <mkdir dir="${build}" />

               <mkdir dir="${packaging}" />

        </target>

        <!--

        =============================================================================================

        컴파일

        =============================================================================================

        -->    

        <!-- 소스 컴파일 -->

        <target name="compile"  >

               <javac srcdir="${src}" destdir="${build}">

                       <classpath>

                              <path refid="cactus.classpath"/>

                              <pathelement location="${servletapi.jar}"/>

                       </classpath>

               </javac>

        </target>

        <!--

        =============================================================================================

        패키징

        ${build} 생성된 클래스들과, ${conf} 있는 web.xml 설정 정보를 모아서 하나의 WAR파일로 패키징 한다.

        =============================================================================================

        -->    

        <!-- WAR 패키징 -->

        <target name="packaging" depends="compile" >

               <war warfile="${packaging}/${project.name}.war"      webxml="${conf}/web.xml" >

                       <classes dir="${build}" />

                       <lib dir="${lib}"/>

               </war>

        </target>

       

        <!--

        =============================================================================================

        배포

        LOCAL Machine으로 배포하는 스크립트로 tomcat /webapps 디렉토리에 war파일을 복사한다.

        =============================================================================================

        -->    

        <!-- 배포 -->

        <target name="deploy" depends="packaging" >

               <copy file="${packaging}/${project.name}.war" todir="${tomcat.home}/webapps"/>

        </target>

       

        <!--

        =============================================================================================

        테스트

        =============================================================================================

        -->           

        <!-- Cactus 테스트 -->

        <target name="cactus-test">

                <!-- Run the tests -->

                 <cactus  warfile="${packaging}/${project.name}.war" fork="yes"

                       printsummary="yes"

                     failureproperty="tests.failed"> 

                       <classpath>

                              <path refid="cactus.classpath"/>

                              <pathelement location="${servletapi.jar}"/>

                              <pathelement location="${build}"/>

                       </classpath>

                   <containerset>

                       <!--

                       <tomcat5x dir="D:\dev\apache-tomcat-5.5.23" port="8080"      />

                               -->

                       <generic name="local tomcat" port="8080">

                            <startup target="dummy"/>

                            <shutdown target="dummy"/>

                       </generic>

                      

                   </containerset>

 

                   <formatter type="brief" usefile="false"/>

                   <formatter type="xml"/>

                   <batchtest todir="${cactus.testlog}">

                     <fileset dir="./src">

                       <include name="**/Test*.java"/>

                     </fileset>

                   </batchtest>

                 </cactus>

                 <!-- JUnit(cactus) 테스트 리포트 생성 -->

                 <junitreport todir="${cactus.testlog}">

                       <fileset dir="${cactus.testlog}" includes="TEST*.xml"/>

                       <report todir="${cactus.testlog}" format="frames"/>

                 </junitreport>

                      

                 <fail if="tests.failed"> cactus Test failed</fail>

        </target>

        <target name="dummy">

        </target>

       

       

</project>

                      

<Cactus 실행용 ANT 스크립트 >

 l        cactus 용 테스크 정의하기

먼저 ant cactus 테스크를 추가하자.

CLASSPATH cactus에 필요한 클래스들을 추가한후 taskdef이용하여 cactus.tasks resource로 정의하면 cactus 관련된 task들을 정의할 수 있다. (cactus.tasks는 실제로 cactus에 관련된 jar파일 내에 존재한다.)

        <!-- class path 설정 -->

        <path id="cactus.classpath">

            <pathelement location="${cactus.jar}"/>

            <pathelement location="${cactus-ant.jar}"/>

            <pathelement location="${commons-httpclient.jar}"/>

               <pathelement location="${commons-logging.jar}"/>

               <pathelement location="${aspectjrt.jar}"/>

               <pathelement location="${cargo.jar}"/>

               <pathelement location="${junit.jar}"/>

        </path>

      

        <taskdef resource="cactus.tasks" classpathref="cactus.classpath"/>

    

이제는 cactus 관련 테스크들을 사용할 수 있다.

 l        cactus 테스크 사용

실제로 cactus 테스크를 사용해야 하는데, 테스크의 내용을 나눠보면 크게, 테스트할 WAR파일 설정, CLASSPATH 설정,테스트용 서버 정보 설정, 테스트할 유닛들 지정 및 로그 정리 절차로 나눠볼 수 있다.

 

<cactus  warfile="${packaging}/${project.name}.war" fork="yes"

printsummary="yes" failureproperty="tests.failed">

 

warfile 속성에 테스트할 (서버에 배포한) war 파일을 지정하고, failureproperty에 실패값을 지정한다. 그리고 해당 target 마지막 부분에 이 failureproperty 값으로 아래와 같이 실패 처리를 한다..

<fail if="tests.failed"> cactus Test failed</fail>

만약 이 처리를 하지 않으면 cactus 단위 테스트가 실제로 실패하더라도 ant target에 대한 결과는 Successful로 처리된다.

 다음으로 cactus 테스트에서 사용할 클래스 패스를 지정하는데, cactus 관련 클래스들 이외에, 테스트에 사용된 클래스들을 사용하기 위한 lib들이 포함되어야 하며, 반드시 빌드된 테스트 클래스들을 CLASSPATH에 포함 시켜야 한다. (아래 굵게 표시한 부분)

 

<classpath>

<path refid="cactus.classpath"/>

<pathelement location="${servletapi.jar}"/>

<pathelement location="${build}"/>

</classpath>

 

cactus in-container 테스트이기 때문에 테스트할 컨테이너를 꼭 지정해야 하는데,catcus에서는 테스트할 서버를 직접 기동해서 WAR파일을 배포하는 것 까지 자동화 할 수 있다.Tomcat Orion,Resin,WebLogic까지 지원하는데 자세한 내용은 cactus의 문서를 참고하도록 하고 필자는 generic이란 element이용하여, 단순하게, 테스트할 서버의 URL PORT만 지정하였다. (테스트할 서버는 서블릿과 테스트 서블릿이 배포된 서버를 의미한다.)

<containerset>

<generic name="local tomcat" port="8080">

      <startup target="dummy"/>

      <shutdown target="dummy"/>

</generic>

</containerset>

:

<target name="dummy">

</target>

 

그리고 두개의 element 를 지정해야 하는데, startupshutdown 엘리먼트이다.

이 엘리먼트는 서버가 기동되어 있지 않은 경우 실행되어 서버를 기동시키고 테스트가 끝난후에 서버를 자동으로 내리는 역할을 하는 “target”을 지정해야 한다. (필수 element 이다.)

필자는 서버의 기동과 정지를 ANT 내에서 처리 하지 않고 직접 처리하였기 때문에, “dummy”라는 아무 작업도 하지 않는 target을 정의하여 지정하였다.

다음으로 Unit 테스트에 대한 로그를 저장하는 설정을 진행한다. <formatter> 라는 element를 사용하는데 Cactus JUnit의 확장이기 때문에 JUnit formatter element를 지원한다.

여기서 사용한 formatter type 속성은 두가지로 brief xml 을 사용하였다.

Brief는 테스트의 실패이유를 대략적으로 출력해주는 속성이고 xml은 테스테에 대한 각종 정보(통계,프로퍼티등등)을 상세하게 저장해주는 속성이다.

brief 값은 usefile=”false” 로 설정하여, stdout(화면)으로 출력하도록 하였고, xml usefile을 설정하지 않아서 파일로 저장되도록 하였다. 파일 경로는 다음 설명할 <batchtest> element에서 지정되는 todir 디렉토리에 저장되게 된다.

 

<formatter type="brief" usefile="false"/>

<formatter type="xml"/>

 

이제 실제로 테스트할 테스트 클래스들을 선택해야 하는데 한꺼번에 지정하기 위해서 fileset element이용하여, Test*.java 로 된 모든 테스트 클래스들을 수행하도록 하였고, 로그 파일은 todir로 정의된 ${cactus.testlog} 디렉토리에 저장되도록 설정하였다.

 

<batchtest todir="${cactus.testlog}">

      <fileset dir="./src">

        <include name="**/Test*.java"/>

      </fileset>

</batchtest>

 

cactus 테스트를 수행하기 위한 준비가 완료되었고 여기까지 설정하면 실제로 테스트를 수행할 수 있다.

 

여기에 하나 덧붙여서 설명하면, 테스트 결과는 formatter에서 type=”xml”로 설정한 부분이 XML파일로 저장된다. 그러나 이 파일을 읽기가 쉽지 않기 때문에, xml 파일을 이용하여 보기 쉬운 HTML로 테스트 결과를 생성해주는데 junitreport element를 사용할 수 있다.

<junitreport todir="${cactus.testlog}">

       <fileset dir="${cactus.testlog}" includes="TEST*.xml"/>

       <report todir="${cactus.testlog}" format="frames"/>

 </junitreport>

아래는 <junitreport> 이용하여 테스트 결과를 HTML로 생성한 결과이다.

사용자 삽입 이미지
<그림 junitreport이용하여 Cactus 테스트 결과를 HTML로 생성한 결과 >

자아, 이제 cactus이용한 테스트와 리포트 생성까지 모두 살펴보았다.

다소 복잡하기는 하지만 JUnitEE보다 훨씬 더 정교한 J2EE 컴포넌트 테스트를 지원하고, ANT 스크립트 역시 개발 빌드 과정에서 필요한 부분에 약간만 더 해진것이기 때문에 정교한J2EE 컴포넌트 테스트를 진행하기 위해서는 Cactus를 사용하는 것을 권장한다.

 

 

 

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Test Coverage Rate

ALM/Test Automation | 2008.02.11 10:30 | Posted by 조대협
테스트 Coverage rate에 대해 고민하던중 재미있는 글 하나 발견
사실 Coverage rate를 올리는것도 중요하지만, Coverage rate는 value있는 test 로 cover가 되어야 한다. 코드 Coverage rate를 올리는것 자체는 중요하지 않다.
얼마만큼 꼼꼼한 테스트가 도느냐가 문제이지...

여러 문서들을 찾아보니까는 보통 80%의 Coverage를 이야기 하는데, 이정도의 Coverage라면, 적어도 개발 과정 전에 Test 에 대한 방법이 고려된 상태에서 개발을 해야지 않는다면 개발 중간에 일정에 미칠 IMPACT가 어마어마할것이다.
지금 프로젝트는 60~70% 정도를 고민중인데..
어떻게 될려나?

==
http://www.artima.com/weblogs/viewpost.jsp?thread=204677

Agitating Thoughts & Ideas
How Much Unit Test Coverage Do You Need? - The Testivus Answer
by Alberto Savoia
May 4, 2007
Summary
Answer to the question: "What is Testivus' wisdom concerning the proper percentage of test coverage?"

Advertisement
 

Referring to "The Way of Testivus" entry:

http://www.artima.com/weblogs/viewpost.jsp?thread=203994

Morgan Conrad asked: "What is Testivus' wisdom concerning the proper percentage of test coverage?"

Here you go Morgan.

Testivus On Test Coverage

Early one morning, a programmer asked the great master:

“I am ready to write some unit tests. What code coverage should I aim for?”

The great master replied:

“Don’t worry about coverage, just write some good tests.”

The programmer smiled, bowed, and left.

...

Later that day, a second programmer asked the same question.

The great master pointed at a pot of boiling water and said:

“How many grains of rice should put in that pot?”

The programmer, looking puzzled, replied:

“How can I possibly tell you? It depends on how many people you need to feed, how hungry they are, what other food you are serving, how much rice you have available, and so on.”

“Exactly,” said the great master.

The second programmer smiled, bowed, and left.

...

Toward the end of the day, a third programmer came and asked the same question about code coverage.

“Eighty percent and no less!” Replied the master in a stern voice, pounding his fist on the table.

The third programmer smiled, bowed, and left.

...

After this last reply, a young apprentice approached the great master:

“Great master, today I overheard you answer the same question about code coverage with three different answers. Why?”

The great master stood up from his chair:

“Come get some fresh tea with me and let’s talk about it.”

After they filled their cups with smoking hot green tea, the great master began to answer:

“The first programmer is new and just getting started with testing. Right now he has a lot of code and no tests. He has a long way to go; focusing on code coverage at this time would be depressing and quite useless. He’s better off just getting used to writing and running some tests. He can worry about coverage later.”

“The second programmer, on the other hand, is quite experience both at programming and testing. When I replied by asking her how many grains of rice I should put in a pot, I helped her realize that the amount of testing necessary depends on a number of factors, and she knows those factors better than I do – it’s her code after all. There is no single, simple, answer, and she’s smart enough to handle the truth and work with that.”

“I see,” said the young apprentice, “but if there is no single simple answer, then why did you answer the third programmer ‘Eighty percent and no less’?”

The great master laughed so hard and loud that his belly, evidence that he drank more than just green tea, flopped up and down.

“The third programmer wants only simple answers – even when there are no simple answers … and then does not follow them anyway.”

The young apprentice and the grizzled great master finished drinking their tea in contemplative silence

신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Cobertrua의 분석 리포트를 보면 Line Coverage율과, BranchCoverage율이 나오는데.
이 값이 정학하게 나오지 않고 N/A로 나오거나, 100%로 나오는 경우가 있는데
이건 클래스를 컴파일할때 디버깅 모드로 컴파일하지 않아서 발생하는 문제이다.
이를 해결하기 위해서
ANT TASK에서 <javac debug="true"...> 옵션을 추가해주면 된다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Cactus에서 이미 만들어놓은 JUnit 케이스를 재활용할 수 있는데.
만들어놓은 JUnit을 서버로 올려서 TestRunner를 이용하여 브라우져에서 실행하면 그대로 실행된다.

만약 ANT TASK에서 호출하고자 할때는 기존 JUnit케이스를 다음과 같이 ServletTestCase로 묶어야지 호출이 가능하다.
==

Cactus is able to run pure JUnit TestCase on the server side. This is done by using the ServletTestSuite Test Suite that wraps your existing Test Cases. For example:

public class TestJUnitTestCaseWrapper extends TestCase
{
    public static Test suite()
    {
        ServletTestSuite suite = new ServletTestSuite();
        suite.addTestSuite(TestJUnitTestCaseWrapper.class);
        return suite;
    }

    public void testXXX()
    {
    }
}
==

* addTestSuite(원래JUnitCase.class)를 하면 된다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
서버쪽에서 Cobertura를 이용한 커버러지 분석을 할때
주의할점은

Cobertura는 기본적으로 ASM을 이용하여, 테스트를 진행할 코드에 커버러지 분석 코드를 삽입하는 방식이다. (AOP와는 다르게 STATIC한 방식을 사용)
그렇기 때문에, Instrumented 된 코드가 반드시 실행되도록 클래스패스에 삽입 하거나 또는 패키징 할때 Instrumented 되지 않은 코드를 WEB-APP에 먼저 복사한후 그 다음에 Instrumented된 코드를 복사하여 Overwrite가 되게 해야 한다.

그리고, Cobertura는 커버러지 분석한 정보를 메모리에 담아 놨다가 서버가 shutdown될 당시에 한꺼번에 파일에 쓰기 때문에 메모리 요구량이 높을 수 있다.
그래서 각 단위 테스트마다 리스타트를 해서 메모리가 오버 되지 않게 유지 해야 한다.

기동 스크립트에서는
JAVA에 -D 옵션으로 -Dnet.sourceforge.cobertura.datafile=파일명.ser 로 지정하고
Cobertura에서 사용하는 파일들 corbertura.jar, asm, asm-tree, jakarta-oro.. jar들을 클래스 패스에 삽입해야 한다.

이렇게 하고 Instrumented된 코드를 수행하면, (비단 JUnit이 아니더라도) 수행한 내역을 *.ser 파일에 저장하게된다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

Cactus 테스트시 주의 할점

ALM/Test Automation | 2008.01.17 10:12 | Posted by 조대협
1.  junit/framework/Test 클래스를 못 찾는 문제
${ANT_HOME}/lib 디렉토리에 junit.jar 파일을 복사해 놓아야 한다.

2. cactus ant task 실행시 테스트 케이스를 못찾고 ClassNotFoundException 이 나오는 문제
<cactus> 태스크 내에.. 
 <classpath>
    <pathelement location="${build.dir}" />
  </classpath>
로 지정한다.
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

JUnitPerf

ALM/Test Automation | 2008.01.16 11:59 | Posted by 조대협
==

Decorate with style

Decorators aren't limited to a single decoration. For example, in Java™ I/O, it is possible to decorate a FileInputStream with an InputStreamReader with a BufferedReader (just remember this: BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("infilename"), "UTF8"))).

Decoration can happen on multiple levels, and so it is with JUnitPerf's TimedTests and LoadTests. When these two classes decorate each other, it leads to some compelling test scenarios, such as one where a load is placed on a business case and a time threshold is also applied. Or we could just combine the previous two test scenarios as follows:

  • Place a load on the testCreate() method.
  • Specify that every thread must finish within the time threshold.

Listing 4 shows what happens when I apply the above specifications by decorating a normal Test with a LoadTest, which is decorated by a TimedTest:


Listing 4. A decorated load and timed test
public static Test suite() {
 int users = 10;
 Timer timer = new ConstantTimer(100);
 long maxElapsedTime = 2000; 	 
 return new TimedTest(new LoadTest(
   new WidgetDAOImplTest("testCreate"), users, timer), 
     maxElapsedTime);  		
}

As you see, the testCreate() method is run 10 times (each thread launching 100 milliseconds apart), and each thread must complete within two seconds or the entire test scenario will fail.

출처 : Tong - exospace님의 JAVA통
==
위와 같은 방식으로, 기존 JUnit Test case를 Thread수, Thread당 수행 시간, 허용가능 응답시간으로 나눠서 테스트가 가능함.

대신 리포팅 기능이 약한데.
Japex는 리포팅 기능이 매우 강력한 반면, 허용 가능 응답시간이 없는것이 단점.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

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

Cobertura를 이용한 커버러지 테스트시 주의할 사항  (1) 2008.01.17
Cactus 테스트시 주의 할점  (0) 2008.01.17
JUnitPerf  (0) 2008.01.16
단위 테스트 1회 (JUnit)  (1) 2007.11.23
Test Coverage 분석툴  (0) 2007.11.08
Cactus 실행용 ANT 스크립트  (0) 2007.09.13
TAG JUnitPerf
 

티스토리 툴바