IT_Programming/Dev Tools

예제를 통한 JUnit 4 살펴보기

JJun ™ 2011. 3. 30. 16:45

------------------------------------------------------------------------------------------------

출처: http://www.java2go.net/blog/62

------------------------------------------------------------------------------------------------

 

JUnit 4는 JDK 5의 어노테이션 도입을 비롯해 예외 처리 테스트, 타임 아웃 등 TestNG 로 부터

많은 컨셉을 가져왔고, 거의 4년만에 이루어진 Major 릴리즈를 내놓았다.

 

JUnit 3 패키지(junit.framework.*)를 그대로 포함하면서, 새로운 패키지(org.junit.*)를 추가한 구조를

가지고 있다. JUnit 3에서 한층 업그레이드 된 JUnit 4의 새로운 기능을 예제를 통해 알아본다.

 

 

1. 기본 테스트 예제

import! org.junit.Assert;
import! org.junit.Test;
public class SimpleTest {	
	private int x = 3;
	private int y = 2;
	@Test
	public void testAddition() {
		int z = x + y;
		Assert.assertEquals(5, z);
	}
}

- 기존 방식의 junit.framework.TestCase 를 상속할 필요가 없다.
- @Test를 사용하여 테스트 메소드를 정의하며, 메소드명의 test* 로 시작할 필요가 없다.
- 더이상 TestCase를 상속하지 않으므로, 별도 Assert 클래스로 제공하는 assert 메소드로 검증한다. 기존과 같은 형태의 코드 스타일을 원하면 Java 5에서부터 지원하는static 임포트를 사용하면 된다.

import! static org.junit.Assert.*;
...
assertEquals(5, z);
...


2. 테스트 메소드 시작 전과 후에 처리 메소드 정의하기

import! static org.junit.Assert.*;
import! org.junit.After;
import! org.junit.Before;
import! org.junit.Test;
public class BeforeTest {
	private int x;
	private int y;
	@Before
	public void doBeforeTest() {
		x = 3;
		y = 2;
		System.out.println("@Before");		
	}
	@Test
	public void testAddition() {
		int z = x + y;
		assertEquals(5, z);
	}
	@Test
	public void testSubtraction() {
		int z = x - y;
		assertEquals(1, z);
	}
	@After
	public void doAfterTest() {
		System.out.println("@After");		
	}	
}

- 각 테스트 메소드가 실행되기 전 또는 후에 매번 실행된다.

3. 테스트 클래스 시작 전과 후에 처리 메소드 정의하기

import! static org.junit.Assert.*;
import! org.junit.AfterClass;
import! org.junit.BeforeClass;
import! org.junit.Test;
public class BeforeClassTest {
	private static int x;
	private static int y;
	@BeforeClass
	public static void doBeforeClass() {
		x = 3;
		y = 2;
		System.out.println("@BeforeClass");				
	}
	@Test
	public void testAddition() {
		int z = x + y;
		assertEquals(5, z);
	}
	@Test
	public void testSubtraction() {
		int z = x - y;
		assertEquals(1, z);
	}
	@AfterClass
	public static void doAfterClass() {
		System.out.println("@AfterClass");		
	}	
}

- 모든 테스트 메소드가 실행되기 전 또는 후에 한번만 실행된다.

4. 주석을 이용해 Test Suite을 작성하여 테스트 실행하기

import! org.junit.runner.RunWith;
import! org.junit.runners.Suite;
import! org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@SuiteClasses( { SimpleTest.class, BeforeTest.class, BeforeClassTest.class } )
public class AllTests {
}

- @RunWith 주석을 통해 Suite 라는 러너를 지정하고, @SuiteClasses 주석을 통해 테스트할 클래스 목록을 지정한다.

5. 예외처리 테스트하기

import! org.junit.Test;
public class ExceptionTest {
	@Test(expected = ArithmeticException.class)
	public void divisionByZero() {
		int n = 2 / 0;
		System.out.println(n);
	}
	@Test(expected = NumberFormatException.class)
	public void parseInteger() {
		int n = Integer.parseInt("two");
		System.out.println(n);
	}
}

- 기대되어지는 예외 클래스와 동일한 예외가 발생되면 성공으로 간주한다.

6. 타임아웃 테스트하기

import! org.junit.Test;
public class TimeoutTest {
	@Test(timeout = 2000)
	public void testTimeout() throws Exception {
		Thread.sleep(1000);	// success
		//Thread.sleep(3000);	// failure
	}
}

- 지정된 시간안에 정상적으로 처리되면 성공이고, 그렇지 않으면 실패로 간주된다.

7. 파라미터를 이용하여 테스트하기

import! java.util.Arrays;
import! java.util.Collection;
import! org.junit.Assert;
import! org.junit.Test;
import! org.junit.runner.RunWith;
import! org.junit.runners.Parameterized;
import! org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class ParameterTest {
	private int x;
	private int y;
	private int z;
	public ParameterTest(int x, int y, int z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}
	@Parameters
	public static Collection numValues() {
		return Arrays.asList(new Object[][] { { 1, 2, 3 }, { 2, 5, 7 },
				{ 3, 6, 9 }, { 10, 20, 30 } });
	}
	@Test
	public void testAddition() {
		System.out.println("x=" + x + ", y=" + y + ", z=" + z);
		int n = x + y;
		Assert.assertEquals(z, n);
	}
}

- JUnit에서는 테스트 메소드에 직접 파라미터를 넘길 수 없으므로, 매개변수 없는 테스트 메소드를 작성한다.
- Collection 유형을 반환하는 static 메소드를 작성하고, @Parameter로 파라미터 제공 메소드로 정의한다.
- 제공되는 파라미터를 받어 처리하는 생성자를 작성한다.
- 클래스 수준에서 테스트가 Parameterized 클래스와 함께 실행되도록 @RunWith 주석을 지정한다.

8. 특정 테스트 무시하기

import! org.junit.Assert;
import! org.junit.Ignore;
import! org.junit.Test;
public class IgnoreTest {
	private int x = 3;
	private int y = 2;
	@Test
	public void testAddition() {
		int z = x + y;
		Assert.assertEquals(5, z);
	}
	@Ignore("This metod isn't working yet.")
	@Test
	public void testSubtraction() {
		//
	}	
}

- @Ignore 주석을 통해 테스트 되지 말아야할 테스트 메소드를 지정한다.

9. 배열 내용을 비교하는 assert 사용하기 

import! org.junit.Assert;
import! org.junit.Test;
public class ArrayTest {
	@Test
	public void verifyArrayContents() throws Exception {
		String[] expected = new String[] { "JUnit 3.8.2", "JUnit 4.4",
				"TestNG 5.7" };
		String[] actual = new String[] { "JUnit 3.8.2", "JUnit 4.4",
				"TestNG 5.7" };
		Assert.assertArrayEquals("the two arrays should not be equal",
				expected, actual);
	}
}

 

 

 

더보기

  [ JUnit4 Test Annotation ]

 

@Test annotation

Test Case 를 만들어 줍니다. (선언)
 

@Test

public void blahMethod() {
    String result = "blah";

    assertEquals("blah", result);

}


@Before & @After annotation

각각 setup 과 tearDown method 를 위한 annotation

@Before

public void blahBeforeTest() {
    blah = new Blah();

}

@After

public void blahAfterTest() {
    blah = null;

}


@BeforeClass & @AfterClass

@BeforeClass : test case 수행 이전에 한번 실행, @AfterClass : test case 수행 후 한번 실행

@BeforeClass

public void blahBeforeTest() {
}

@AfterClass

public void blahAfterTest() {

}


@Ignore

Test Case 수행을 무시



@기타

@Ignore("무시이유작성")
@Test(timeout = 1000) : 시정한 시간이 경과 하면 test fail. (miiseconds)



사용하면 편한 mock 객체
- easymock
- mockito

 


 

 

JUnit 4

http://www.ibm.com/developerworks/kr/library/tutorial/j-junit4/section3.html

JUnit 4에서는 자바(Java™) 5 주석(annotation)의 효율적인 유연성을 위해 기존의 엄격한 명명 규칙 및 상속 계층 구조를 없앴다.이전의 엄격한 명명 규칙과 상속 계층 구조가 사라졌다. 다음은 JUnit 4의 새로운 기능을 간략히 설명해 놓은 목록이다.

  • 매개변수 테스트
  • 예외 테스트
  • 제한 시간 테스트 @Test(timeout=1)
  • 유연한 픽스쳐
  • 테스트를 쉽게 무시하는 방법 -> @ignore()
  • 테스트를 논리적으로 그룹화하는 방법

 

기존 버전의 문제

 

첫 번째는 모든 메서드는 test라는 단어로 반드시 시작해야 한다.

두 번째 클래스 자체가 JUnit의 TestCase에서 확장되어야 한다는 점이다(또는 일부 파생).

이러한 두 가지 규칙을 위반하는 테스트는 실행할 수 없었다.

 

테스트 Annotations
          @Test
          
          @Test(expected=IndexOutOfBoundsException.class): Exception을 테스트한다.
          
          @Test(timeout=1): 테스트가 실행하는 데 걸리는 최대 시간을 나타낸다. 시간이 초과되면 테스트가 실패한다.
          
          @Ignore("message"): 바로 다음 @Test 주석은 무시된다.
          

테스트 픽스쳐

픽스쳐는 특정 로직이 테스트 전후에 실행되도록 보장하는 하나의 약정이므로 손쉽게 재활용할 수 있다. 하지만 JUnit 4에서 픽스쳐는 주석을 통해 명시적으로 변경되므로 사용자가 픽스쳐를 사용하도록 결정한 경우에만 약정이 적용된다.

이전 버전의 픽스쳐 구현

여기에서는 setUp()tearDown() 메서드를 사용하여 모든 테스트 메서드를 래핑해야 했다

이전 버전의 JUnit에서 이 약정은 픽스쳐를 구현했는지 여부에 관계없이 적용되었다.

JUnit4의 픽스쳐

@BeforeClass@AfterClass : 클래스 수준, 1회용 픽스쳐 - @BeforeClass 픽스쳐 주석 사용.

@Before@After : 메서드(또는 테스트) 수준의 경우

이전의 tearDown() 기능은 새로운 픽스쳐 모델에서 사라지지 않았다. tearDown()메서드를 실행하려면 새 메서드를 생성하고 필요에 따라 @After 또는 @AfterClass를 사용하면 된다.

  1. @After
    public static void cleanUp() {
    // tear down logic..
    }

테스트 그룹화 ; @RunWith

이전 버전의 TestSuite 는 몇 개의 논리적 테스트 클래스를 그룹화하고 이를 단일 유닛으로 실행하는 역할을 수행했다.

 

 

JUnit 4는 @RunWith는 프레임워크에 내장된 러너(runner)가 아닌 다른 러너를 통해 특정 테스트 클래스를 손쉽게 실행할 수 있게 해준다.

  • @RunWith(Suite.class) 스위트 러너를 번들로 포함한다.
  • 테스트 스위트를 나타내기 위한 클래스 목록을 매개변수로 취하는 @SuiteClasses라는 주석을 제공해야 한다.

 

 

ANT와 JUnit 4

1.7 이전의 앤트 버전을 실행 중인 경우 JUnit 4 테스트를 즉시 실행할 수 없다. 하지만 그렇더라도 테스트 자체를 실행할 수 없는 것은 아니며 단지 즉시 실행할 수 없을 뿐이다.

해결 방법

1.7 이전의 앤트 버전에서 JUnit 4 테스트를 실행하려면 Listing 16에서와 같이 JUnit4TestAdapter의 인스턴스를 반환하는 suite() 메서드를 사용하여 테스트 케이스를 수정해야 한다.

  1.           public static junit.framework.Test suite(){
              
               return new JUnit4TestAdapter(RegularexpressionTest.class);
              }
              

문서