JAVA/Unit Test

Junit -03-

B정상 2009. 2. 16. 11:38

JUnit4.X 이후 변화

비교대상 JUnit3.8이전 JUnit4.0이후
Jdk5.0 Pradigm 도입 - Annotation 사용
Assertion Method를 static import 사용
Test Class junit.framework.TestCase상속 TestCase 상속받지 않음
Set up, teat Down setUp(), tearDown() @Before, @After
(다수의 메서드 지정가능)
Test Method testXXX()로 정의 @Test
@Test(expected=Error.class)
Junit4.4이후 - assertThat(value,matcher statement);
assumeThat()추가

TestCase에 Main() 메서드를 추가하기.

테스트를 실행시킬때 여러가지 방법이 있습니다만 전체 클래스에 메인메서드를 추가해서 사용해도 편리하겠죠.
메인메서드는 org.junit.runner.JUnutCore#main()을 호출합니다.

package testJunit;

import static org.junit.Assert.*;

import org.junit.*;
import org.junit.runner.JUnitCore;

public class SampleTest01 {

    @Test
    public void getStringOne() {
    	String str ="JUnit4.5";
    	assertEquals(str.charAt(0),'b');
    }
    public static void main(String[] args){
	JUnitCore.main(SampleTest01.class.getName());
    }
}

실행결과


콘솔창에서 실행한 결과입니다.

assertEquals(str.charAt(0),'J');

올바른 내용이 나오도록 수정하고 확인하면


올바른 테스트를 축하 드립니다. 위의 내용을 Run As > Java Application 으로 실행한 결과 입니다.


setUp(), tearDown()에 대해 정정


우선 제대로 알지 못하고 짐작으로 퉁~ 친점 죄송합니다. 앞서 스터디상에서 설명드릴때 setUp()메서드와 tearDowm()메서드 대신
어노테이션 사용하는데 @BeforeClass @AfterClass를 쓴다고 말했습니다.
정정 : @Before 와 @After 입니다.

import junit.framework.*;
import java.util.*;

public class Tester extends TestCase {
      public Tester(String name) {super(name);}
      private List list = new ArrayList();
      public void testFirst() {
            list.add("one");
            assertEquals(1, list.size());
      }
      public void testSecond() {
            assertEquals(0, list.size());
      }
}

위에 간단한 소스를 적어 놓았습니다.
testFirst() 메서드에선 list에 "one" 을 추가하고 list의 사이즈가 1과 같은지 를 묻고 있습니다.
testSecond() 메서드에도 list의 사이즈를 0과 같은지 묻고있습니다.
결과는 직접실행해 보시기 바랍니다.(추측후 실행해보시면 더욱 재미있으실 겁니다.)

JUnit 관련 검색중 재미있는 글을 읽었습니다.
원문 :
http://martinfowler.com/bliki/JunitNewInstance.html

JUnit에서는 테스트메서드 호출시마다 인스턴스를 새로 만든다는 내용의 글입니다. JUnit에서는 분리를 중요하게 여겨서
테스트시 자신의 테스트가 정작 다른테스트의 오류 때문에 방해를 받아선 안된다. 그래서 분리의 원칙에 따라 테스트
메서드 호출마다 새로운 인스턴스를 만든다는게 글의 요지입니다.

이미 알고 계신 내용이라면 김이 빠지실지도 모르겠습니다만 처음 알게된 저로선 작은 테스트를 해보기로 하겠습니다.
초심으로 돌아가서 static 초기화와 인스턴스초기화, 생성자 main()메서드 등등의 호출순서
처음으로 Java라는 것을 접하고 나열한 위의 ~ 호출순서때문에 고민했던 기억을 되살려 보시기 바랍니다.
(고민안하셨다면 천재일지도...;;; )

package testJunit;

public class testClass01 {

	static{
		System.out.println("static 초기화 제일먼저 호출");
	}
	{System.out.println("인스턴스 초기화 호출");}

	public void testMethod01() {
		System.out.println("testMethod01 호출");
	}
	public void testMethod02() {
		System.out.println("testMethod02 호출");
	}
	public static void main(String[] args) {

		System.out.println("main 호출");
		System.out.println("인스턴스 생성전");
		testClass01 tc01 = new testClass01();
		System.out.println("인스턴스 생성후");
		tc01.testMethod01();
		tc01.testMethod02();

	}

}

결과값

static 초기화 제일먼저 호출
main 호출
인스턴스 생성전
인스턴스 초기화 호출
인스턴스 생성후
testMethod01 호출
testMethod02 호출


네 알고계신 내용을 복습차원에서 써 놓았습니다.
JUnit에서의 호출수순도 이러한지 살펴볼 시간입니다.

package testJunit;

import static org.junit.Assert.assertEquals;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.JUnitCore;

public class SampleTest02 {

    static {
        System.out.println("static 초기화 출력");
    }
    {
        System.out.println("인스턴스 초기화 출력");
    }
    public SampleTest02() {
        System.out.println("생성자 출력");
    }
    @BeforeClass
    public static void doBeforeClass() {
        System.out.println("@BeforeClass 출력");
    }
    @Before
    public void doBefore() {
        System.out.println("@Before 출력");
    }
    @Test
    public void testOne() {
        System.out.println("@Test1 출력");
    }
    @Test
    public void testTwo() {
        System.out.println("@Test2 출력");
    }
    @After
    public void doAfter() {
        System.out.println("@After 출력");
    }
    @AfterClass
    public static void doAfterClass() {
        System.out.println("@AfterClass 출력");
    }
    public static void main(String[] args) {
	System.out.println("main 호출");
	System.out.println("인스턴스 생성전");
        JUnitCore.main(SampleTest02.class.getName());
	System.out.println("인스턴스 생성후");
    }
}

결과값

static 초기화 출력
main 호출
인스턴스 생성전
JUnit version 4.5
@BeforeClass 출력
.인스턴스 초기화 출력
생성자 출력
@Before 출력
@Test1 출력
@After 출력
.인스턴스 초기화 출력
생성자 출력
@Before 출력
@Test2 출력
@After 출력
@AfterClass 출력

Time: 0

OK (2 tests)





  • SampleTest02 클래스가 로드되면서 static초기화 호출
  • main()메서드 호출
  • @BeforeClass메서드 호출
  • 이하의 내용이 테스트메서드 호출마다 반복됩니다.
    • 인스턴스 초기화 호출
    • @Before메서드 호출
    • @Test메서드 호출
    • @After메서드 호출
  • @AfterClass메서드 호출

@BeforeClass, @Before, @After, @AfterClass의 차이점도 아실 수 있었습니다.

assertThat의 사용법

JUnit4.4버젼에서 추가된 assertThat()은 다른 단정메서드보다 더 범용적으로 활용이 가능할 것 같습니다.

assertThat
public static <T> void assertThat(T actual, org.hamcrest.Matcher<T> matcher)
public static <T> void assertThat(java.lang.String reason, T actual, org.hamcrest.Matcher<T> matcher)

assertThat()메서드에 인수로 지정되어 있는 org.hamcrest.Matcher 클래스는 비교처리를 위해 추가된 클래스입니다.
비교 처리를 위해 import static 해두시면 편하실 겁니다.
(ex : AllOf, AnyOf, DescribedAs, Is, IsAnything, IsEqual, IsInstanceOf, IsNot, IsNull, IsSame)

assertThat의 사용예

assertThat(x, is(3));
assertThat(x, is(not(4)));
assertThat(responseString, either(containsString("color")).or(containsString("colour")));
assertThat(myList, hasItem("3"));
  • 기존의 단정메서드를 사용하는 것보다 assertThat을 사용할때 가독성이 높고 무엇을 비교하는지 쉽게 알 수있다.
  • 기존의 단정메서드를 사용해 실패했을때 보다 이해하기가 쉽다. (실패메세지의 변화)
  • 비교처리를 스스로 추가해 사용 할 수 있다.

assertTrue failure Message

assertTrue(responseString.contains("color") || responseString.contains("colour"));
// ==> failure message:
// java.lang.AssertionError:

assertThat failure Message

assertThat(responseString, anyOf(containsString("color"), containsString("colour")));
// ==> failure message:
// java.lang.AssertionError:
// Expected: (a string containing "color" or a string containing "colour")
//      got: "Please choose a font"

assumeThat의 사용법

JUnit4.4에서는, org.junit.Assume 클래스가 추가되었습니다. Assume는 테스트하기 전에
전제조건을 밝히기 위한 클래스입니다. 동작은 앞서 설명한 AssertThat()메서드와 거의 동등합니다.

assertThat()의 차이점은 assumeThat()메서드로 검증을 실패하더라도 JUInit프레임워크의 테스트가
성공한 것으로 처리합니다. Assume은 테스트를 하기위한 전제조건을 테스트하는 기능입니다.

package Junit4_X;

import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.hamcrest.CoreMatchers.*;
import org.junit.Test;

public class TestSample01 {

	@Test
	public void testMethod01() {
		assumeThat(0 ,is(0));
		assertThat(0, is(0));
		assertThat(0 ,is(1));
	}
}

만약 전제조건에서 에러가 발생하더라도, 후의 계속되는 테스트에는 무의미하다고 판단해 테스트 전체에 대해서
영향을 미치지 않게 하여 테스트를 성공하게 합니다. 다양한 환경에서 테스트할 필요가 있는 경우,
환경의존테스트 (OS종류에 따른 테스트등)를 만들고 싶을때가 있을것이라고 생각합니다.
그럴때 이용하시면 편리할 듯 합니다.

package Junit4_X;

import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.hamcrest.CoreMatchers.*;
import org.junit.Test;

public class TestSample01 {

	@Test
	public void testMethod01() {
		assumeThat(0 ,is(0));
		assertThat(0, is(0));
                assumeThat(0 ,is(1));
		assertThat(0 ,is(1));
	}
}