[ETC] Cactus를이용한효율적인테스트전략

황제낙엽 2007.01.30 07:16 조회 수 : 33 추천:69

site_link1  
site_link2  
site_link3  
http://wiki.javajigi.net/pages/viewpage.action?pageId=279

Cactus를이용한효율적인테스트전략

Table of Contents

Introduction

;Cactus :Cactus 는 서블릿, jsp 커스텀 태그 , 서블릿 필터 등에 대해 컨테이너 테스팅 서비스를 제공하는 오픈 소스 프레임웍 이다. 커넥션 풀, EJB, jsp등의 다른 컨테이너 컴포넌트도 Cactus 에서 쉽게 테스트 될 수 있다. Cactus 는 JUnit프레임웤과 통합하여 사용자에게는 투명하게 redirector 를 사용할 수 있도록 할 수 있다.

Preview

Cactus 개발진의 분류에 따르면, 단위 테스트의 유형과 알맞은 프레임워크는 아래와 같이 세 가지로 살펴볼 수 있다.
유형 1. 코드 로직 단위 테스트(code logic unit testing): Mock Object 와 같은 프레임워크 사용이 적합하다.
유형 2. 통합 단위 테스트(integration unit testing): 컨테이너와의 상호작용을 테스트하는 방식으로, Cactus 사용이 적합하다.
유형 3. 기능 단위 테스트(functional unit testing): 서버 코드가 반환하는 값을 테스트하는 방식으로, HttpUnit 사용이 적합하다.


그림 : Cactus Ecosystem

Cactus는 크게 두 가지 목적 하에서 개발되었다
*첫째*는 J2EE 컴포넌트 모델과 잠재적으로 나타날 수 있는 기타 컴포넌트 유형 전체를 포괄할 수 있는 서버 측 자바 코드를 위한 편리한 단위 테스트 프레임워크의 제공이다.
*둘째*는 소스 코드뿐만 아니라 배포 기술자(deployment descriptor)등의 메타 데이터 파일까지 포함하여 어플리케이션을 구성하는 모든 파일에 대한 세밀한 단위 테스트를 지속적으로 수행할 수 있게 하는 것이다. 즉, 개발 시점에서 자동화된 방법으로 통합을 수월하게 하고자 한다.

  • 자동화된 테스트 유형

    Cactus

    ;Cactus 작동 원리 :아키텍춰참고

  1. 브라우저에서 URL을 통해 TestCase를 호출하며, JUnit Test Runner는 YYYTestCase의 runTest() 메소드를 호출한다.runTest() 메소드는 먼저 begin(WebRequest) 메소드가 있는 경우 이를 수행한다. 즉, 모든 테스트가 수행되기 전에 begin() 메소드가 호출된다.그리고 나서 beginXXX(WebRequest) 메소드가 있는 경우 이를 수행한다. beginXXX() 메소드에 전달된 WebRequest 매개변수를 이용하여,HTTP 헤더와 HTTP 매개변수 등이 설정된다.
  2. YYYTestCase.runTest() 메소드는 Redirector proxy에 HTTP 연결을 확립하여, HTTP 요청에 설정된 헤더 및 매개변수 데이터가 전달된다.
  3. Redirector proxy가 테스트 케이스의 서버 측에 대한 대리자(proxy) 역할을 한다. 즉, 테스트 케이스는 두 개의 인스턴스가 생성된다.먼저 JUnit Test Runner에 의해 클라이언트 측에서 인스턴스가 생성되고, Redirector proxy에 의해서 서버 측에서 다시 한번 인스턴스가 생성된다.클라이언트 측의 인스턴스는 begin(), beginXXX(), endXXX()와 end() 메소드 실행에 사용되고, 서버 측의 인스턴스는 textXXX() 메소드 실행에 사용된다.Redirector proxy는 테스트 케이스 클래스의 인스턴스외에도 서버 객체에 대한 래퍼(Wrappers)와 HTTP 세션 등을 생성한다.
  4. 테스트 클래스의 setUp(), testXXX() 및 teardown() 메소드가 순서대로 실행된다. 이들 메소드는 Redirector proxy에 의해 호출되며,JUnit과 같이 setUp()과 teardown() 메소드는 선택적이다.
  5. testXXX() 메소드는 JUnit의 assert API를 사용하여 테스트를 수행하고, 테스트를 위해 서버 측 코드를 호출하기도 한다.
  6. 테스트가 실패하는 경우, testXXX() 메소드는 Exception을 발생시키며, 이는 Redirector proxy에 의해 검출된다.
  7. Exception을 발생시, Redirector proxy는 Exception 관련 정보를 클라이언트 측에 전달하고, JUnit에 의해서 화면에 출력된다.
  8. 정상 수행의 경우, YYYTestCase.runTest() 메소드는 endXXX(WebResponse)가 있는 경우 이를 수행한다.
    endXXX() 메소드에서 JUnit assert API나 Cactus가 제공하는 헬퍼 유틸리티를 이용하여 HTTP 헤더와 쿠키 및 서블릿의 출력 스트림을 점검할 수 있다.
    endXXX() 메소드 수행 이후, end(WebResponse) 메소드가 있는 경우 이를 실행한다.

Catcus 설치
설치는 클라이언트 측과 서버 측을 생각해야 한다.
클라이언트 측은 요청이 웹 컨테이너로 보내지는 부분이고, 서버측은 테스트가 실제로 실행되는 부분이다.
http://jakarta.apache.org/cactus/ 에서 설치 과정및 필요한 파일들은 구할 수 있다.
;시스템 요구 사항:Java Virtual Machine A Java 1.2 or greater compatible virtual machine must be present. Note that all servlet engines require a JVM to run so if you are already using servlets you already have one installed. Servlet/J2EE Engine A Servlet 2.x/J2EE 1.x compliant servlet engine for running your Cactus tests must be present.

1 단계. Tomcat 설치 - Cactus를 사용하기 위해서는 Tomcat 4.0 이상이 설치되어 있어야 한다.
2 단계. Cactus 설치 - Cactus 다운로드 페이지에서 Cactus 압축 파일을 다운로드 한다.2004년 7월 25일 현재 최신 파일은 1.7 버전이다. 압축을 해제한 이후에 하위에 나타나는 lib 디렉토리에서 다음 의 필수 파일을 TOMCAT_HOME[1] 하위의 /common/lib 에 복사한다.

cactus-1.7.jar
commons-httpclient-2.0.2.jar
commons-logging-1.0.4.jar
httpunit-1.6.jar
aspectjrt-1.2.1.jar
junit-3.8.1.jar

3 단계. Cactus 테스트 클래스를 서버의 클래스 패스에 설정한다. Cactus 는 주어진 테스트케이스를 서버와 클라이언트 양측에서 실행하므로 필요하다. 이 단계를 생략하면 redirector 서블릿이 테스트 케이스를 로드할 때 ClassNotFoundException이 발행하게 된다.
4 단계. 준비된 클래스들을 서버 클래스 패스의 test 아래로 이동시킨다. 실제로, 모든 코드의 최신 버전은 테스트가 실행되는 서버에 준비되어 있어야 한다.
5 단계. 여러 Cactus redirector에 URL을 맵핑한다. 이 작업은 Cactus 테스트를 포함하는 웹 애플리케이션의 web.xml에서 작성한다.
6 단계. 만약 커스텀 태그 테스트가 있으면, 이전 단계에서 지정한 장소의 웹 애플리케이션에 redirector.jsp 를 추가한다.

Cactus 아키텍쳐

아키텍쳐


그림 출처: http://jakarta.apache.org/cactus/images/archi.jpg
웹서버에서 사용되는 암시적인 오브젝트를 생성하기 위해,
Cactus 는 HTTP통신의 요청-응답 사이클을 복제(replicate)해야 한다.
이를 위해 Cactus 는 우선, 클라이언트 측에서 실행하고 서버측에서 실행하여 한 덩어리로 동작한다는 것을 보여야 한다.
Cactus 프레임웤을 만든이는 이 작업을 테스트 케이스를 사용하여 간단히 처리하도록 하고 있다.
이때 테스트 케이스는 클라이언트와 서버 양측에 각각 작성토록 한다.
*실행시작

Cactus 테스트는 일반적인 JUnit TestRunner 에서 시작한다.
테스트 케이스의 인스턴스가 생성되고 나서 생성자로 전달된 이름에 의해 테스트 메소드가 선택된다.

*beginXXX() Method

테스트 메소드의 이름에 의해 ServletTestCase() 는 TestCase에서 beginXXX() 메서드를 찾아 실행한다.
예를 들어 Cactus가 테스트 케이스에서 testHello() 를 실행하려면 beginHello() 메서드를 실행해야 한다.
beginXXX() 메서드는 테스트에 의해 요구되는 요청 파라미터를 셋업하는데 사용된다.

*Redirector 서블릿 호출

beginXXX() 호출후에 ServletTestCase 는 redirector 서블릿에 대해 HTTP커넥션을 오픈한다.
beginXXX() 에서 설정된 임의 request 파라미터를 보내는 것과 아울러, Cactus는 내부 파라미터를 전달해 서버에서 실행될 테스트를 지정한다.

*서버측 셋업

redirector 서블릿이 요청을 받으면 내부 파라미터를 검사하여 일치하는 테스트 케이스의 사본 인스턴스를 생성한다.
이 클래스의 인스턴스가 작성되면 redirector 서블릿은 리플렉션 기법을 사용하여 표준 서블릿 변수(request, response등) 를
새 테스트 케이스 인스턴스로 복사한다.
이들 변수는 redirector 서블릿이 사용하는 변수로 표준 서블릿 변수의 wrapped(랩퍼) 버전이다.

*서버측 실행

서버측 테스트 케이스가 완전히 초기화 되면, 서버측 실행이 시작된다.
setUp(), testXXX(), tearDown() 메서드가 이 시점에서 실행된다.
테스트 결과는 application scope 에 있는 변수에 저장된다.

*결과수집 및 사후 처리

테스트가 실행을 마치면, 클라이언트에 있는 테스트 사본은 결과를 가져오기 위해 redirector 서블릿에 요청을 하게 된다.
redirector 서블릿은 애플리케이션 스코프의 변수에 저장된 내용을 클라이언트에게 보낸다.
예외 상황및 실패 사항이 결과에 저장되어 있는 경우에는 재전달(rethrown) 되어 JUnit 테스트 실행기에 이ㅡ해 로그가 저장된다.
결과가 성공한 경우에는 클라이언트에서 endXXX()를 실행한다.
endXXX() 는 WebResponse 파라미터를 사용한다. WebResponse 오브젝트는 클라이언트에게 필요한 응답 덴이터를 가지고 있을 수 있다.
endXXX() 메서드는 WebResponse오브젝트의 메서드를 사용하여 응답 내용에 대한 확인작업을 하게 된다.
endXXX() 메서드가 리턴되면 모든 테스트 실행이 끝나게 된다.