2008년 9월 7일 일요일

Junit 사용법[스크랩]

JUnit이란 한마디로 테스트 툴이다. 프로그램 테스트할때 사용한다.



class 화일을 테스트를 할때.. 반드시 main() 를 만들어 겉으로만 테스트 하는것은

테스트라 보기 어렵다고 한다.

대형 프로젝트의 경우 시나리오가 나오고 로직이 나오면

로직의 문제를 테스트하는것을 테스트라 말 할 수 있다고 한다.

JUnit는 이렇게 보이지 않고 숨겨진 단위 테스트를 좀더 수면 위로 끌어올리고

정형화시켜주는 단위 테스트 프레임워크의 자바 구현물이며

1.4버젼에서 추가된 assertXXX를 사용하여 Test 한다.



-- Eclipse에서 사용법

저도 잘 모르지만... 다른것보단 간단하더라구요..

Eclipse 2.1 버전 이상에서는 Junit을 기본으로 사용하고 있어서...

밑에 읽어보시면 알겠지만. .. classpath를 따로 잡아주지 않아도.

Eclipse 에서는 default 여서 그냥 사용하시면 됩니다.

확인법 : Window->Preferences->Jave->JUnit 모든것을 체크 해주면 됨..



File->NEW->project에서 TestCase, TestSuite가 없으신 분은

Window ->Customize Perspective->File>New에서 찾아서 체크만 해주면 ok



실행은 Run->JUnit

실행하면 왼쪽에 JUnit 창이 뜰것인데.

그쪽에 아무것도 안뜨고 초록 막대가 보이면 Test 성공

에러나면 빨간 막대.. Junit 창에 에러가 쫙~~ 뜹니다.



위 방법을 모르겠거나 잘 되지 않으면,

=====================================================

Sample 프로젝트에 마우스를 대고 오른쪽을 클릭하여 컨텍스트 메뉴 맨 밑에 있는 Properties 를 선택한다.
Java Build Path를 선택한다.
Libraries 탭을 선택한다.
Add Variable 버튼을 클릭한다.
New 버튼을 클릭하고 변수 이름에 JUNIT_LIB을 입력한다.
그 변수를 편집하고 C:\eclipse\plugins\org.junit_3.8.1 (JUnit은 Eclipse plug-in이다)에 지정한다.
Sample 프로젝트에 src 폴더를 선택한다.
구현 경로에 JUnit을 넣었다. 외부 JAR를 이 경로에 직접 추가할 수 있었지만 다른 머신의 작업공간을 설정할 때에는 변수를 사용하는 것이 더 쉽다. 다음은 테스트 클래스를 작성하는 과정이다:


툴바의 Create a Java Class 버튼 오른편에 드롭다운 화살표를 클릭하고 Test Case를 선택한다.
테스트 이름으로 TC_Account를 선택한다.
setUp()과 tearDown() 체크 박스를 선택한다.
Finish를 클릭한다.
====================================================







밑에 다른 사이트에 퍼온건데 정리가 잘 되어 있더라구요.. 도움이 되실꺼예요.





JUnit개요


test case는 일련의 테스트를 실행하기 위한 장치

(fixture, 기능, 원시코드경로, 멤버 함수간의 상호작용)을 정의하는 것이다.


전형적으로 작성한 모든 클래스는 테스트 케이스를 가지고 있어야 한다.

테스트 Fixture는 테스트 수행에 필요한 자원

즉, 프리미티브 변수와 오브젝트를 제공하는 것


동일하거나 유사한 오브젝트에 대한 테스트가 두개 이상 있을 경우

테스트 환경을 셋업하기 위한 코드를 각 테스트에서 꺼내서 하나의 메소드에 넣어둔다.





동일하거나 유사한 환경에서 실행되는 테스트를 위한 설정을 테스트 Fixture라고 한다.

테스트 스위트(test suite) 는 관련된 테스트 케이스를 모아 놓은 것을 말한다.


=====================================================








<<출처 : http://wiki.tdd.or.kr >>



Unit Test


JUnit의 사용법을 말하기 전에 도대체 테스팅이란 무엇인지

그 의미에 대해서 짚고 넘어가자.

테스트는 말 그대로 우리가 만든 프로그램이 원하는 대로 동작하는지

알아보는 것에 불과하다. 그렇다면 우리가 원하는 대로 동작하는지

알 수 있는 방법은 무엇이 있을까?

그것은 단 한가지이다.

기대값과 결과값을 비교한다.



우리가 기대하던 결과를 프로그램이 출력하는지를 살펴 보는것이

테스팅의 기본이고 끝이다.

유닛 테스트는 이러한 기대값과 결과값을 비교한다.

TDD는 이러한 유닛 테스트를 기본으로 한다.

다만 테스트의 범위가 매우 작은것이 그 특징이라 할 수 있다.



비행기를 만들고 비행기가 날아가는 것을 보는것도 테스팅이지만

비행기의 부속하나하나 역시 테스트 하지 않던가?


TDD는 비행기를 테스트 하는것이 아니라 비행기의 부속 하나하나를

꼼꼼하게 테스트한다. 그리고 100% 그 테스트를 통과해야 한다.





JUnit 사용법
http://www.junit.org 에서 junit.jar파일을 구하고

자바 클래스 패쓰에 다운 받은 jar파일을 설정한다.



그리고 에디터로 다음의 코드를 작성해 보자.



package tddbook;

import junit.framework.*;
import junit.textui.*;


public class JUnitTutorialTest extends TestCase {

public JUnitTutorialTest( String arg0 ) {
super( arg0 );
}

public void testNumber() {
int expected = 10;
assertEquals( expected, 2*5 );
}

public static void main( String[] args ) {
TestRunner.run( JUnitTutorialTest.class );
}
}





이것이 바로 JUnit을 이용한 테스트 코드이다.

TestCase를 extends해서 testXXX메써드들을 테스트하고 있다.



위와 같은 모습의 코드가 전형적인 Junit을 이용한 코드의 틀이라고 할 수 있겠다.

위의 testNumber가 실제적인 테스트를 행하는 메써드이며,
이렇게 메써드명이 test로 시작하는 메써드들은 원하는 만큼 많이 만들어서 쓸 수가 있다.



그렇다면 testNumber메써드를 보자. assertEquals라는 TestCase를 통해서

extend받은 메써드를 이용하여 2*5의 결과값이 기대한 값 (expected)와

일치하는지를 비교한다.

위의 코드를 실행하면 다음과 같은 결과를 보게 된다.

.
Time: 0.01

OK (1 test)



자세히 보면 제일 윗줄에 점(.)이 하나 보이는데 이것은 test로 시작하는

메써드들의 갯수 즉, 테스트의 갯수를 의미한다.
다음의 Time은 테스트하는데 소요된 시간을 말하며 OK는 1개의 테스트가

성공했음을 알린다.



이렇듯 text로 그 결과를 보여주는 까닭은 우리가 main메써드에서

junit.textui.TestRunner을 사용했기 때문이며

이 외에도 awt나 swing을 이용한 visual한 결과를 볼 수도 있다.



see also : JunitGui - awt, swing을 이용한 유닛 테스팅

이번에는 테스트가 실패할 경우 어떻게 보여지는지 살펴보도록 하자.

다음과 같이 위의 코드를 수정해 보자.



package tddbook;

import junit.framework.TestCase;

public class JUnitTutorialTest extends TestCase {
public JUnitTutorialTest(String arg0) {
super(arg0);
}

public void testNumber() {
int expected = 10;
assertEquals(expected, 2 * 5);
}

public void testFailMessage() {
int expected = 10;
assertEquals(expected, 3*5);
}

public static void main(String args[]) {
junit.textui.TestRunner.run(JUnitTutorialTest.class);
}
}



testFailMessage라는 메써드를 추가했다.

코드를 보면 expected는 10이지만 3*5의 값은 10일리 없다.

위의 테스트 코드를 실행하면 다음과 같은 결과를 보게 된다.



..F
Time: 0.01
There was 1 failure:
1) testFailMessage(tddbook.JUnitTutorialTest)junit.framework.AssertionFailedError: expected:<10> but was:<15>
at tddbook.JUnitTutorialTest.testFailMessage(JUnitTutorialTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at tddbook.JUnitTutorialTest.main(JUnitTutorialTest.java:21)

FAILURES!!!
Tests run: 2, Failures: 1, Errors: 0


점 두개는 역시 테스트의 갯수를 말하며

그 옆의 F는 테스트가 실패(Fail)되었음을 말한다.

There was 1 failure: 밑에는 실패한 이유와 trace가 보인다.



우리의 짐작처럼 기대값은 10인데 결과값이 15라서

AssertionFailedError가 발생했음을 알려준다.



마지막 줄은 총 2개의 테스트 중 1개의 Fail이 있고 Error는 0개임을 말한다.

테스트 코드에서 Fail과 Error는 다르다.
Fail은 우리가 테스트한 기대값과 결과값이 다를때 발생하지만

Error는 코드상의 오류나 NullPointerException같은

예측못한 Exception이 발생할 때 생긴다.



setUp & tearDown
setUp - JUnit 테스트 코드의 setUp 메써드는 특별한 의미이다.

주로 코드내에서 사용할 리소스를 초기화 시킬때 setUp을 이용한다.
즉, 각각의 테스트 코드가 항상 new Person()이라는 statement를 실행한다면

이것은 setUp에 선언해서 테스트 매써드가 실행될 때마다 수행하게 할 수 있는 것이다.
다시 말해 setUp은 각각의 testXXX메써드들이 수행되기 바로 직전에

매번 실행되는 것이다.


tearDown - setUp과 반대의 경우라고 생각하면 된다.

testXXX매써드가 종료될 때마다 수행되는 매써드이다.

사용한 리소스를 클리어할때 주로 사용된다.



Examples.

package tddbook;

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

public class TestSetupTearDown extends TestCase {

public TestSetupTearDown(String arg0) {
super(arg0);
}

public static void main(String[] args) {
junit.textui.TestRunner.run(TestSetupTearDown.class);
}

Vector employee;

protected void setUp() throws Exception {
employee = new Vector();
}

protected void tearDown() throws Exception {
employee.clear();
}

public void testAdd() {
employee.add("Pey");
assertEquals(1, employee.size());
}

public void testCleared() {
assertEquals(0, employee.size());
}

}


JUnit Useful Methods
JUnit에서 가장 많이 사용되는 메써드는 assertEquals이지만 이 외에도 여러 유용한 메써드들이 있는데 그것에 대해서 알아보기로 하자.



assertTrue(X)
X가 참인지를 테스트한다.



assertFalse(X)
X가 거짓인지를 테스트한다.



assertNull(X)
X가 NULL인지를 테스트한다.



assertNotNull(X)
X가 NULL이 아닌지를 테스트한다.



fail(MSG)
무조건 실패시킨다 (MSG를 출력한다. ) 주로 Exception테스트를 할때 사용된다.




<< 출처 : http://www.yeonsh.com >>

JUnit Cookbook
A cookbook for implementing tests with JUnit.


간단한 Test Case
뭔가를 테스트하고 싶을 때 순서:

1. TestCase 클래스의 인스턴스를 만든다.
2. runTest() 메소드를 override한다.
3. 값을 검사하고 싶으면, assert()를 호출해서 테스트가 성공일 때

참이 되는 boolean을 전달한다.


public void testSimpleAdd() {
Money m12CHF= new Money(12, "CHF");
Money m14CHF= new Money(14, "CHF");
Money expected= new Money(26, "CHF");
Money result= m12CHF.add(m14CHF);
assert(expected.equals(result));
}



이미 작성한 테스트와 유사한 테스트를 다시 작성해야 한다면 대신 Fixture를 만든다.

만일 하나 이상의 테스트를 실행해야 한다면 Suite를 만든다.


Fixture
동일하거나 유사한 오브젝트에 대한 테스트가 두개 이상 있을 경우

테스트 환경을 셋업하기 위한 코드를 각 테스트에서 꺼내서 하나의 메소드에 넣어 둔다.
동일한 환경에서 실행되는 테스트를 위한 설정을 Fixture라고 한다.

처음 테스트를 작성할 때는 테스트 자체를 위한 코드보다는 테스트를 위한 환경 설정에

더 많은 시간이 들 것이다. Fixture를 작성해놓으면 다음에 테스트를 작성할 때

시간이 절약될 것이다.





공통 Fixture가 있을 경우 할 일:



1. TestCase 클래스의 서브 클래스를 만든다.
2. Fixture의 각 파트를 위한 인스턴스 변수를 추가한다.
3. setUp()을 override해서 변수를 초기화한다.
4. tearDown()을 override해서 setUp()에서 할당한 자원들을 해제한다.


public class MoneyTest extends TestCase {
private Money f12CHF;
private Money f14CHF;
private Money f28USD;

protected void setUp() {
f12CHF= new Money(12, "CHF");
f14CHF= new Money(14, "CHF");
f28USD= new Money(28, "USD");
}
}


Test Case

Suite
TestSuite는 많은 테스트 케이스들을 함께 실행할 수있다.

하나의 테스트 케이스를 실행하는 방법은 아래와 같다.

TestResult result= (new MoneyTest("testMoneyMoneyBag")).run();

두개의 테스트 케이스를 한번에 실행할 때는 아래와 같이 한다.

TestSuite suite= new TestSuite();
suite.addTest(new MoneyTest("testMoneyEquals"));
suite.addTest(new MoneyTest("testSimpleAdd"));
TestResult result= suite.run();



다른 방법은 JUnit으로 하여금 TestCase에서 suite를 추출하도록 하는 것이다.

그렇게 하기 위해서는 TestSuite의 생성자에 테스트 케이스의 클래스를 전달한다.

TestSuite suite= new TestSuite(MoneyTest.class);
TestResult result= suite.run();

테스트 케이스의 일부만 테스트할 때는 수작업으로 하나씩 지정하는 방법을 사용한다.

그 외의 경우에는 위와 같이 자동 추출되도록 하면 테스트 케이스를 추가할 때마다

지정하지 않아도 되므로 좋다.



TestSuite는 Test Interface를 implement하는 모든 오브젝트를 포함할 수 있다.

TestSuite suite= new TestSuite();
suite.addTest(Kent.suite());
suite.addTest(Erich.suite());
TestResult result= suite.run();


TestRunner
어떻게 테스트를 실행하고 결과를 수집할 것인가?

JUnit은 실행할 suite를 정의하고 결과를 표시하기 위한 도구(TestRunner)를 제공한다.

test suite를 넘겨주는 static method suite()를 사용하면 TestRunner가

suite에 접근할 수 있다.



예를 들어, TestRunner가 MoneyTest suite를 사용할 수 있게 하려면,

아래와 같은 코드를 MoneyTest에 추가한다



public static Test suite() {
TestSuite suite= new TestSuite();
suite.addTest(new MoneyTest("testMoneyEquals"));
suite.addTest(new MoneyTest("testSimpleAdd"));
return suite;
}

만일 TestCase가 suite 메소드를 정의하지 않는다면

TestRunner는 'test'로 시작하는 모든 메소드들을 추출해서 suite를 만들 것이다.



JUnit은 TestRunner 툴의 텍스트 버전과 그래픽 버전을 제공한다.

junit.textui.TestRunner는 텍스트 버전이고 junit.ui.TestRunner와

junit.swingui.TestRunner는 그래픽 버전이다.





TestCase 클래스에 main()을 정의해놓으면 직접 TestRunner를 호출할 수도 있다.



public static void main(String args[]) {
junit.textui.TestRunner.run(suite());
}

위의 모든 방법으로 테스트가 정상실행되도록 하기 위해서는

CLASSPATH에 junit.jar 파일이 들어 있어야 한다

댓글 없음:

댓글 쓰기