2011년 6월 9일 목요일

Sampling & Testing JUnit

테스트는 지루함 속의 절대적인 공포라는 이름의 프로그램의 묘비이다.
이장에서 우리는 case-study 코드에 관하여 소개하고, 코드를 테스트 하기 위해서 식별화 하고, 그것을 어떻게 테스트 하는지에 관하여 논의할 것입니다.
우리는 코드가 우리가 기대하는 대로 잘 동작하고 코드가 잘못될 때에도 잘 행동 할거라는 걸 확신하기 위해서 테스트를 실행 할 것 입니다.

PLT 1.1 Introducing the controller component
Controller는 일반적으로 다음과 같은 특징을 같는다.
  • 요청(Request)의 수용
  • 그 요청에 대하여 어떠한 공통의 계산도 수행한다.
  • 적절한 요청 Handler를 선택합니다.
  • 그 Handler가 관련된 비즈니스 로직을 실행할수 있도록 요청을 전달 합니다.
  • Error와 Exception을 위한 Top-Level의 Handler을 제공할 수 있다.


PLT 1.1.1 Designing the Interfaces
다음은 controller구성을 위한 4개의 인터페이스 구성에 대하여 보여주고있다.
Request, Response, RequestHandler, Controller(Controller는 Request을 요청받고, RequestHandler에의해 디스페치 시키며, Response객체을 리턴한다.)
Request, Response, RequestHandler, and Controller interfaces
public interface Request {
String getName();
}
 
public interface Response {
}

public interface RequestHandler {
Response process(Request request) throws Exception;
}

public interface Controller {
Response processRequest(Request request);
void addHandler(Request request, RequestHandler requestHandler);
}


- Request 인터페이스는 요청의 유니크 네임을 리턴하는 getName() 메서드 하나만이 정의 되어있다.

PLT 1.1.2 Implementing the base classes
The generic controller
package junitbook.sampling;
import java.util.HashMap;
import java.util.Map;
public class DefaultController implements Controller {
private Map requestHandlers = new HashMap();
protected RequestHandler getHandler(Request request){

if (!this.requestHandlers.containsKey(request.getName())){
String message = "Cannot find handler for request name "
  + "[" + request.getName() + "]";
throw new RuntimeException(message);
}
return (RequestHandler) this.requestHandlers.get(
request.getName());
}

public Response processRequest(Request request){
Response response;

try{
response = getHandler(request).process(request);
}catch (Exception exception){
response = new ErrorResponse(request, exception);
}
return response;
}

public void addHandler(Request request,RequestHandler requestHandler){
if (this.requestHandlers.containsKey(request.getName())){
throw new RuntimeException("A request handler has "
+ "already been registered for request name "
+ "[" + request.getName() + "]");
}else{
this.requestHandlers.put(request.getName(),requestHandler);
}
}
}


- HashMap은 requestHandler 등록에 사용된다.
- getHandler을 호출했는데 등록된 requestHander가 없으면 RuntimeException을 발생한다.
- Controller 클래스의 processRequest 메서드에서 발생하는 Exception은 다음의 ErrorResponse클래스로 전달된다.
Special response class signaling an error
package junitbook.sampling;
public class ErrorResponse implements Response{
private Request originalRequest;
private Exception originalException;
public ErrorResponse(Request request, Exception exception){
this.originalRequest = request;
this.originalException = exception;
}
public Request getOriginalRequest(){
return this.originalRequest;
}
public Exception getOriginalException(){
return this.originalException;
}
}


PLT 1.1.3 Testing the DefaultController
TestDefaultController – a bootstrap iteration
package junitbook.sampling;
import junit.framework.TestCase;
public class TestDefaultController extends TestCase {
private DefaultController controller;
protected void setUp() throws Exception{
controller = new DefaultController();
}
public void testMethod(){
throw new RuntimeException("implement me");
}
}


- JUnit TestCase을 만들 때 테스트대상은 다음과 같은 형태에 있어야 좋다.
    • public class은 같은 페키지에 만든다.
    • test case class의 내부 클래스로 만든다.

- setup 메서드는 TestCase에서 실행 초기에 자동으로 호출되는 콜백 메서드이다.
TestDefaultController – 최종 버전
package junitbook.sampling;
import junit.framework.TestCase;
public class TestDefaultController extends TestCase {
private DefaultController controller;
private Request request;
private RequestHandler handler;
protected void setUp() throws Exception{
controller = new DefaultController();
request = new TestRequest();
handler = new TestHandler();
controller.addHandler(request, handler);
}
private class TestRequest implements Request{
public String getName(){
return "Test";
}
}
private class TestHandler implements RequestHandler{
public Response process(Request request) throws Exception {
return new TestResponse();
}
}
private class TestResponse implements Response{
}
public void testAddHandler() {
RequestHandler handler2 = controller.getHandler(request);
assertSame(handler2, handler);
}
public void testProcessRequest() {
Response response = controller.processRequest(request);
assertNotNull("Must not return a null response", response);
assertEquals(TestResponse.class, response.getClass());
}
}



Chapter 2 Testing JUnit
이장에서 우리는 JUnit를 이용한 테스트 프로그램 작성 및 Test Case, Test Suite을 만들어 본다.
테스트 대상이 되는 ezframeserviceLocator는 호출자에게 보내는 사람 메일주소, 받는 사람 메일주소, 메일폼, 첨부파일등의 정보을 받아 메일 발송 프로그램을 호출하여 메일 발송 로직을 처리하는 프로그램이다. 여기서는 메일 발송 프로그램의 소스는 정의 하지 않고 넘어간다.

getMailTemplate 메서드는 유닉 테스트 대상이 되는 메서드 이다.
ezFrameServiceLocator – 테스트 대상 프로그램
package org.ezF.servlets;
import java.io.*;
import java.io.File;
import java.util.HashMap;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.*;
import org.ezF.config.*;
import org.ezF.log.*;
import org.ezF.mvc.*;
import org.ezF.tools.*;
import org.ezF.config.ezFConfig;
/**
* ezFrame 내부에서 사용되는 ServiceLocator
* 본 파일은 ezFame 라이블러리 파일에 포함하지 않고 별도의 파일로 배포 될수 있다.
*
* @version ezFrame 1.03
* Copyright 2002-2004 by Lee Yun Chang
* All rights reserved.
* 작성일 : 2004/02/26
* @author 이윤창, craftlee@nate.com
*/
public class ezFrameServiceLocator {
private static HashMap mailTemplateCache = new HashMap();
static {
try {
File Home = new File(ezFConfig.getInstance().get("mail.template.dir"));
File[] fileList = Home.listFiles(new includeNameFileFilter(".html"));
FileReader freader = null;
BufferedReader bufferReader = null;
StringBuffer buffer = null;
String readString = "";
for(int i=0; i < fileList.length; i++) {
freader = new FileReader(fileList[i]);
bufferReader = new BufferedReader(freader);
buffer = new StringBuffer();
while((readString = bufferReader.readLine()) != null) {
buffer.append(readString+"\n");
}
mailTemplateCache.put(fileList[i].getName(),buffer.toString());
}
} catch (Exception exception) {
LogWriter.log(0, "MailTemplate Exception : "+exception.toString());
}
}
public ezFrameServiceLocator() {
}
/**
* 메일링 템플릿 가져오는 메서드
* @param templateName 사용할 메일 템플릿 파일 명
* @param args 템플릿에서 변경할 값들
* @return 메일 폼
*/
public static String getMailTemplate(String templateName, HashMap args) {
return text.replace((String)mailTemplateCache.get(templateName), args);
}
/**
* 에러 발생에 대한 디스패처 작성
* @param requestParser
* @return 에서 발생시 이동할 디스패처
*/
public static RequestDispatcher setErrorDisPatcher(RequestParser requestParser) {
}
/**
* 일반 디스페처 생성
* @param request
* @param URI
* @return 정상 처리된 상태일때 이동할 디스패처
*/
public static RequestDispatcher setDisPatcher(HttpServletRequest request, String URI) {
return request.getRequestDispatcher(URI);
}
}

TestCase - ezFrameServiceLocatorTester
package org.ezF.servlets.test;
import java.util.*;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.ezF.servlets.ezFrameServiceLocator;
public class ezFrameServiceLocatorTester extends TestCase {
public ezFrameServiceLocatorTester(String sTestName) {
super(sTestName);
}
/**
* String getMailTemplate(String)
*/
public void testgetMailTemplate() {
HashMap map = new HashMap();
map.put("name", "이윤창");
map.put("address", "서울 특별시 광진구 구의동");
map.put("phone", "011-9954-0000");
map.put("email", "inter999@xxxx.net");
System.out.println(ezFrameServiceLocator.getMailTemplate("sample.html", map));
}
}


- 테스트을 희망하는 메서드의 testxxxx 메서드을 구현한다.
- TestCase는 개발자의 희망에 따라 여러 개를 만들수 있다.
TestSuite – ezFrameServiceLocatorSuite
package org.ezF.servlets.test;
import junit.framework.Test;
import junit.framework.TestSuite;
public class ezFrameServiceLocatorSuite {
public static Test suite() {
TestSuite suite;
suite = new TestSuite("ezFrameServiceLocatorSuite");
suite.addTestSuite(org.ezF.servlets.test.ezFrameServiceLocatorTester.class);
return suite;
}
public static void main(String args[]) {
String args2[] = {"-noloading", "org.ezF.servlets.test.ezFrameServiceLocatorSuite"};
junit.swingui.TestRunner.main(args2);
}
}


- 만들어진 TestCase을 TestSuit에 등록하여 단위테스트을 실행할 수 있게 한다.
단위 테스트 실행 화면

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...