Junit Test-Driven Development by JUnit

황제낙엽 2006.02.21 09:35 조회 수 : 91 추천:83

sitelink1  
sitelink2  
sitelink3  
extra_vars4  
extra_vars5  
extra_vars6  
http://www.ngic.re.kr/forum/thread.jspa?threadID=1137&tstart=90링크1 : 원본 출처

1. JUnit의 소개

JUnit 에 대하여 설명을 드리기 전에, JUnit 을 사용하게된 배경에 대해 간단히 요약하면 다음과 같습니다.

모든 프로그래머는 자신의 코드가 실제 사용되기 전에, 여러가지 방법에 의하여 테스트 되어야 하며, 발생할 수 있는 에러에 대한 디버깅이 있어햐 한다는 생각을 하고 있습니다.
실제로 프로그램의 개발기간중 상당한 부분을 디버깅 기간에 두고 있음에도 불구하고, 자신이 작성한 코드를 효율적으로 테스트하고 관리하지 못하고 있는것이 사실입니다.

JUnit 은 자신의 코드를 릴리스하기 전에 단위 테스트에 사용할 수 있는 단위 테스팅 프레임워크입니다. 따라서 우리는 JUnit 을 사용하여 자신의 코드에 숨어있는 버그의 수를 대폭 감소 시킬 수 있으며, 보다 효율적인 코드의 작성을 할 수 있습니다.

자바 코드의 테스트를 위해서 가장쉽고 많이 사용되는 방법은 main() 메소드를 통한 테스트의 구현입니다.

이 테스트 방법은 다음과 같은 이유로 인해 단위 테스트 수식자(qualifier)로서의 인정을 받지 못하고 있습니다.

- 클래스에서 테스트 최소 단위는 메소드이며, 어떤 것이 유효한지를 찾으려면 각각의 메소드를 하나씩 테스트해 봐야 합니다.

- 이전 테스트를 실패했다 하더라도 각각의 메소드를 테스트해야 합니다. 이러한 테스트 구현하는 과정에서 한 번의 단일 테스트가 실패할 경우, 후속 테스트가 전혀 수행되지 않기 때문입니다. 그럴 경우, 손상된 코드가 몇 퍼센트나 되는지 알 수가 없게 됩니다.

- 테스팅 코드는 생성된 클래스에 존재하게 됩니다. 그럴 경우, 코드의 크기로 인해 발생되는 문제는 없겠지만 보안상 문제가 발생할 수 있습니다. 가령, 테스트에 데이타베이스 접속을 위한 암호가 포함될 경우 이 정보는 릴리스된 클래스에서 쉽게 사용될 수 있습니다.

- 이 테스트를 자동으로 시작해주는 프레임워크는 없습니다. 따라서 각 테스트를 시작하기 위해서는 스크립트를 작성해야 합니다.

- 리포트 작성시, 자신의 구현 과정을 기록해야 하며 오류 보고를 위한 규칙을 나름대로의 방법으로 정의해야 합니다.

JUnit 은 위와같은 문제를 해결하기 위해서 만들어 졌으며, 이 프레임워크는 주로 모든 테스트 케이스(TestCase)를 위해 만들어진 부모 클래스(parent class)이고, 작성된 테스트 수행, 리포트 생성, 테스트 모음을 정의하기 위한 툴을 제공합니다.


2. JUnit의 설치와 실행

JUnit의 최신 버전은
http://www.junit.org/index.htm
에서 다운로드 받으실 수 있습니다.

제가 이 글을 작성할 당시의 안정된 버전은 3.8.1 이었으며, 저는 이 버전에서 예제들을 테스트하였습니다.

리눅스 또는 윈도우의 Command 창에서 실행을 원하시는 분들은 아래와 같이 CLASSPATH를 설정하셔야 합니다.

export CLASSPATH=.:./junit.jar
javac *.java

Or, if you're using Windows:

set CLASSPATH=.;junit.jar
javac *.java

JUnit 을 실행하기 위한 명령은 아래와 같으며, 3가지의 인터페이스가 있습니다.
java junit.textui.TestRunner 테스트할클래스이름
java junit.awtui.TestRunner 테스트할클래스이름
java junit.swingui.TestRunner 테스트할클래스이름

text, awt, swing 중 원하는 인터페이스를 선택하여 위의 명령라인을 실행하면 됩니다.

아래의 주소에 가시면 샘플 소스의 실행 예제를 보실 수 있습니다.

http://junit.sourceforge.net/doc/testinfected/testing.htm


3. Eclipse 에서의 JUnit 설치

Eclipse 에서는 기본적으로 JUnit을 내장하고 있습니다. (참고로 저는 Eclipse 3.0 M9 버전을 사용하였습니다.)

따라서 별도의 다운로드 및 인스톨 과정없이 보다 편하게 JUnit을 사용할 수 있는 강점이 있으며, 실제로 마우스의 클릭 몇번으로 대부분의 클래스 및 메서드를 생성해 주는 강력한 기능을 지원합니다.

O'REILLY 사의 Eclipse(저자 Steve Holzner) 를 구입하시거나 제본하신 분들께서는 CHAPTER 3. Testing and Debugging 을 보시면 Sample 예제와 함께 자세한 설명이 있음을 알려드립니다.

먼저 Eclipse 에서 JUnit 을 사용하기 위한 세팅법입니다.

Eclipse 플랫폼을 실행하시고, Window->Preference 메뉴를 선택하시면 Preferences 대화창이 열립니다. 왼쪽의 트리구조를 보시면 Java 라는 노드가 있고, 하위 노드로 Build Path 에 보시면 Classpath Varialbles 가 있습니다.
요기서 New 누르시고..
Name : 은 JUNIT 으로..
Path : 는 이클립스가 설치된 폴더내에서 아래와 같은 파일을 찾아 클릭하면 됩니다.

clipse/plugins/org.junit_3.8.1/junit.jar

이것으로 Junit을 사용하기 위한 준비는 끝입니다.

샘플 예제를 만들어 테스트를 해보도록 하겠습니다.

Example 3-1. The Ch03_01.java

·미리보기 | 소스복사·
  1. package org.eclipsebook.ch03;   
  2.   
  3. public class Ch03_01 {   
  4.     private int[] array;   
  5.   
  6.     public int[] allocate() {   
  7.       array[0] = 0;   
  8.       array[1] = 1;   
  9.       array[2] = 2;   
  10.       return array;   
  11.     }   
  12.   
  13.     public int get(int index) {   
  14.       return array[index];   
  15.     }   
  16.   
  17.     public boolean set(int index, int value) {   
  18.       if (index < array.length && index >= 0) {   
  19.         array[index] = value;   
  20.         return true;   
  21.       } else {   
  22.         return false;   
  23.       }   
  24.     }   
  25. }  

위의 샘플 클래스를 JUnit을 통하여 테스트 해보도록 하겠습니다.

이클립스의 Workspace 중 Pakage Expolorer 를 보시면 Ch03_01.java 파일이 있습니다. 여기서 마우스 오른쪽 버튼을 클릭 -> NEW -> JUnit Test Case 를 선택합니다.

New 대화창이 뜨면 아래쪽의 setUP()과 tearDown()을 체크하고 Next를 누릅니다.

다음으로 자신이 테스트를 하고 싶은 메서드에 체크를 하고 Finish 하면 TestCase를 상속받는 새 클래스를 자동으로 생성하여 줍니다.
여기서는 샘플소스의 메소드 3개( allocate(), get(int), set(int,int) )를 모두 체크합니다.


아래와 같은 새 클래스가 생성되었습니다.

·미리보기 | 소스복사·
  1. public class Ch03_01Test extends TestCase {   
  2.   
  3. /*  
  4.   * @see TestCase#setUp()  
  5.   */  
  6.   protected void setUp() throws Exception {   
  7.     super.setUp();   
  8.   }   
  9.   
  10. /*  
  11.   * @see TestCase#tearDown()  
  12.   */  
  13.   protected void tearDown() throws Exception {   
  14.     super.tearDown();   
  15.   }   
  16.   
  17.   public void testAllocate() {   
  18.   
  19.   }   
  20.   
  21.   public void testGet() {   
  22.   
  23.   }   
  24.   
  25.   public void testSet() {   
  26.   
  27.   }   
  28. }  

이제 자신이 테스트를 하고싶은 메서드에 원하는 코드를 추가하면 됩니다.

테스트를 하기위해 사용되는 메서드의 리스트는 아래와 같습니다.

1. assertEquals(a,b)
2. assertFalse(a)
3. assertNotNull(a)
4. assertNotSame(a,b)
5. assertNull(a)
6. assertSame(a,b)
7. assertTrue(a)

Java Beans 형식으로 되어있으므로 메서드에 대한 설명은 하지 않습니다.

이제 아래와 같이 코드를 수정합니다.

·미리보기 | 소스복사·
  1. public class Ch03_01Test extends TestCase {   
  2.   
  3. Ch03_01 testObject;   
  4.   
  5. /*  
  6. * @see TestCase#setUp()  
  7. */  
  8. protected void setUp() throws Exception {   
  9.   super.setUp();   
  10.   testObject = new Ch03_01();   
  11. }   
  12.   
  13. /*  
  14. * @see TestCase#tearDown()  
  15. */  
  16. protected void tearDown() throws Exception {   
  17.     super.tearDown();    
  18.   }   
  19.   
  20.   public void testAllocate() {   
  21.     assertNotNull(testObject.allocate());   
  22.   }   
  23.   
  24.   public void testGet() {    
  25.     assertEquals(testObject.get(1),1);   
  26.   }   
  27.   
  28.   public void testSet() {   
  29.     assertTrue(testObject.set(2,3));   
  30.   }   
  31. }  


테스팅을 원하는 코드를 추가했으므로, Urs As -> JUnit Test 메뉴를 클릭하여 실행합니다.

왼쪽의 Workspace 에 붉은색 상태바가 나타나며 3개의 Error가 발생합니다.
Error 의 발생합니다.

첫번째 에러를 수정하기 위해서

Ch03_01 클래스의 allocate() 메서드를 다음과 같이 수정합니다.

·미리보기 | 소스복사·
  1. public int[] allocate() {   
  2.   array = new int[3];   
  3.   array[0] = 0;   
  4.   array[1] = 1;   
  5.   array[2] = 2;   
  6.   return array;    
  7. }  

다시 Run을 하면 Error가 두개로 줄었음을 알 수 있습니다.

나머지 두개의 Error는 JUnit이 모든 테스트를 독립적으로 실행하기 때문에 발생하는 것 입니다.

결국 메서드 단위로 독립적이라고 생각하시면 되겠습니다.
따라서, 아래와 같이 테스트 코드를 수정하시고,

·미리보기 | 소스복사·
  1. public void testGet() {   
  2.   testObject.allocate();   
  3.   assertEquals(testObject.get(1),1);   
  4. }   
  5.   
  6. public void testSet() {   
  7.   testObject.allocate();   
  8.   assertTrue(testObject.set(2,3));   
  9. }  

다시 실행을 하시면, 왼쪽의 상태바가 녹색으로 나타나는 것을 확인 할 수 있습니다.

각각의 메서드를 독립적으로 테스트하기 때문에 일어나는 에러를 확인할 수 있는 부분이 되겠지요.

간단히 JUnit의 사용법을 테스트 해보았습니다.

이와같은 방법으로 자신의 코드를 디자인 하기전에 메소드에 대한 Rules을 잘 디자인 한다면, 프로그램의 개발에 있어 디버깅 시간을 줄이고, 생각나는 대로 코딩을 했다가 수정하는 오류를 범하지 않을 수 있다고 합니다.

좋은 프로그래밍 습관으로 효율적인 코딩을 하는데 도움이 되었으면 하는 바람입니다.

이상 시스템개발실 홍태희 입니다.