JUnit

|
이글은 Java Extreme Programming Cookboook에서 유용한 내용만 발췌해서 정리한 것입니다.
재방송(원문 작성 일시:2004/11/25 (목) 21:22)

JUnit 개념적으로 이해하기

less..


JUnit에 대한 큰 그림을 머리속에 넣는 걸 돕기 위해 그린 그림이다. 실제 실행은 직접적으로 TestRunner가 TestCase 객체를 호출한다기 보다, Test라는 인터페이스로 접근한다.

less..


단위 테스트는 어떻게 나눌 것인가?

more..


테스트 메소드가 수행되는 절차

more..


다수의 단위 테스트에 대해 setUp과 tearDown 메소드 한번만 수행하게 하기

less..

일종의 부가 클래스(Decorator)인 TestSetup 클래스를 이용한다.

  • 예제 코드
 ...  
public class TestAFunction extends TestCase{
public void testXXX( ){ ... }
public void testYYY( ){ ... }

public static Test suite( ){
TestSetup setup = new TestSetup(new TestSuite(TestAFunction.class)){
protected void setup() throws Excepton{
// 한번만 수행될 테스트 설정 코드
}

protected void teardown() throws Exception{
// 한번만 수행될 테스트 마무리 코드
}
};


return setup;
}
}


JUnit에서는 TestDecorator라는 클래스를 두어 부가적인 기능(테스트에 관련된 기능)을 수행할 수 있게 했다. TestSetup은 TestDecorator의 한가지 활용 사례로 볼 수도 있다. JUnitPerf의 각종 테스트 기능들도 이러한 Decoration 패턴을 통해 TestCase에 부가된다. 새로운 기능을 추가하고자 할 때 상속하여 기능을 확장하는 방법과 Decoration을 고려할 수 있는데, 상속을 이용하게 되면 모든 객체가 확장된 기능을 갖아야 하는 반면, Decoration을 이용하는 경우는 필요한 객체만 동적으로 해당 기능을 부가할 수 있다. 아래의 클래스 다이어그램은 TestCase와 TestSetup 클래스의 관계 및 연관된 클래스 및 인터페이스를 나타낸 것이다.

less..


TestSuite 구성하기

less..

테스트 실행시 JUnit은 가장 먼저 아래의 메소드를 찾는다.

public static Test suite() { ... } 

메소드가 없는 경우는 리플렉션을 이용하여 자동으로 모든 testXXX() 메소드를 TestSuite에 추가시켜서 한번에 수행하게 된다. 아래와 같이 해도 기본적인 suite() 메소드의 동작과 동일한 효과를 얻을 수 있다.

public class TestGame extends TestCase{
  ...
  public static Test suite(){
  return new TestSuite(TestGame.class);
  }
}

모든 테스트를 전부 수행하는 것이 아니라, 특정한 것만 골라서 하거나 순서를 설정하고 싶은 경우에는 다음과 같이 할 수 있다.

public static Test suite(){
  TestSuite suite = new TestSuite();
  suite.addTest(new TestGame("testCreateFighter");
  suite.addTest(new TestGame("testSameFighters");
  return suite;
}

JUnit의 테스트는 Composite 패턴을 고려한 것으로 볼 수 있다. 즉, 아래와 같이 TestSuite를 다시 다른 TestSuite에 추가시킬 수도 있다.

public static Test suite(){
  TestSuite suite = new TestSuite(TestGame.class);
  suite.addTest(new TestSuite(TestPerson.class);
  return suite;
}

less..


테스트 반복 수행

less..

junit.extensions.RepeatedTest 클래스를 이용하면 특정 테스트를 반복 수행할 수 있다.

public static Test suite(){
  return new RepeatedTest(new TestSuite(TestGame.class), 100);
}

less..


예외 상황 테스트

less..

try/catch 블럭으로 예외가 예상되는 부분을 묶은 후에 예외가 발생하지 않으면 fail() 메소드를 호출한다.

public void testPassNullsToConstructor(){
  try{
  Person p = new Person(null, null);
  fail(" ... "):
  catch(IllegalArgumentException expected){
  // test passed!
  }
}

less..


테스트 병렬 수행

less..

junit.extensions.ActiveTestSuite를 이용하여 쓰레드를 활용하여 테스트를 병렬 수행할 수 있다.

public static Test suite(){
  TestSuite suite = new ActiveTestSuite();
  suite.addTest(new TestGame("testCreateFighter"));
  suite.addTest(new TestGame("testGameInitialState")):
}

위의 예제의 경우, 두 개의 테스트 혹은 테스트 그룹은 별도의 쓰레드에서 수행된다.

less..


비동기식 테스트 수행

less..

비동기 메소드를 테스트하는 경우 아래와 같은 테스트 메소드는 문제가 생긴다.

public void testSomething(){
  someAsynchronousMethod();
  assertXXX(...):
}

someAsynchronousMethod 메소드 호출로 시작되는 쓰레드가 작업을 시작하기도 전에 assertXXX 메소드가 불려질 것이기 때문이다


이러한 테스트를 가능하기 위해 Mock Listener를 사용할 수 있다.

public void testAsynchronousSearch() throws InterruptedException{
  MockSearchModelListener mockListener = new MockSearchModelListener();
  SearchModel sm = new PersonSearchModel();

  // 1. 검색 수행
  sm.search("younghoe", mockListener);

  // 2. 검색 종료까지 대기
  synchronized (mockListener) {
  mockListener.wait(2000);
  }

  // 3. 결과를 얻음
  SearchModelEvent evt = mockListener.getSearchModelEvent();

  // 3.1 시간 초과시 Fail
  assertNotNull("Search Time out", evt);

  // 3.2 시간내 결과를 얻으면 결과 확인
  ...
}

이 경우 Timeout 시간을 적절하게 선택해야 의미있는 결과를 얻을 수 있다.

실제 Listener가 개발되어 있는 상태가 아니라면, 테스트를 위해 Mock Listener가 있어야 하는데 아래 예제 코드가 있다.


class MockSearchModelListener implements SearchModelListener{
  private SearchModelEvent evt;

  public void searchFinished(SearchModelEvent evt){
  this.evt = evt;
  synchronized(this){ notifyAll(); }
  }

  public SearchModelEvent getSearchModelEvent(){
  return this.evt;
  }
}

less..

'Document' 카테고리의 다른 글

executeUpdate/executeQuery/execute 차이점  (0) 2008.11.12
html 기초  (0) 2008.10.28
SWT 실행파일 배포  (0) 2008.07.25
jmf 강좌..  (0) 2008.07.25
Web Editor  (0) 2008.07.25
And