먹고 사는 이야기/프로그래밍
[toby의스프링] 2장 - 테스트
Kunner
2011. 9. 18. 17:19
프로그램을 개발할 때 테스트가 얼마나 중요한지에 대해서는 말해봐야 입만 아프다.
하지만 테스트가 얼마나 중요한지 아는 것과, 테스트를 실제로 수행하는 것과는 약간의 차이가 있다.
프로젝트를 진행할 때 당장 코드 써내려가기만도 바빠 죽겠는데 테스트까지 면밀하게 하기가 여간 어렵지 않기 때문이다.
통상적으로 웹프로그램 테스트를 한다고 하면 WEB UI위에 올려 놓고 하는 경우가 많다.
하지만 이는 클래스나 모듈에 대한 단위테스트로는 매우 부적절하다.
프로그램이 오류가 났을 때 이게 지금 개발한 클래스나 모듈의 문제인지, 브라우저의 문제인지, 서버의 문제인지 기타 다른 부분의 문제인지 알기가 쉽지 않기 때문이다.
따라서 작성코드에 대한 단위테스트는 WEB UI가 아닌 실행 가능한 자바 클래스 자체에서 수행해야 한다.
또 기존 코드와 구분하기 위해 별도의 클래스를 만들어서 진행하는 것이 좋다.
DB의 입출력 테스트라면, 개발된 클래스로 입력과 출력을 테스트해 보고 제대로 수행이 됐는지 알아 보는 식이다.
이러한 테스트를 각각 void main() 메소드를 이용해 진행할 수도 있겠지만 프로그램 규모가 커질 수록, 테스트할 대상이 많아질 수록 개별적으로 테스트 하는 것은 매우 어려운 일이다.
따라서 테스트를 할 때는 테스트 자동화 도구를 이용하는 것이 좋다.
대표적인 테스트 자동화 도구에는 JUnit 이 있다.
테스트 자동화 도구 JUnit을 이용할 때의 장점은 아래와 같다.
아래는 JUnit을 이용해 Spring 프레임워크에서 ApplicationContext가 하나만 만들어져서 재사용되는지 확인해보는 테스트이다.
JUnit을 이용한 테스트든, 전통적인 방식의 WEB UI를 이용한 테스트든..
테스트의 중요성은 따로 말할 필요가 없다.
더 나아가 개발이 잘 됐는지 확인하기 위한 테스트로서가 아니라 TDD(Test Driven Development)로서의 테스트로까지 테스트의 역할을 확장할 필요가 있다.
TDD에 대해서는 따로 언급하지 않는다.
하지만 테스트가 얼마나 중요한지 아는 것과, 테스트를 실제로 수행하는 것과는 약간의 차이가 있다.
프로젝트를 진행할 때 당장 코드 써내려가기만도 바빠 죽겠는데 테스트까지 면밀하게 하기가 여간 어렵지 않기 때문이다.
통상적으로 웹프로그램 테스트를 한다고 하면 WEB UI위에 올려 놓고 하는 경우가 많다.
하지만 이는 클래스나 모듈에 대한 단위테스트로는 매우 부적절하다.
프로그램이 오류가 났을 때 이게 지금 개발한 클래스나 모듈의 문제인지, 브라우저의 문제인지, 서버의 문제인지 기타 다른 부분의 문제인지 알기가 쉽지 않기 때문이다.
따라서 작성코드에 대한 단위테스트는 WEB UI가 아닌 실행 가능한 자바 클래스 자체에서 수행해야 한다.
또 기존 코드와 구분하기 위해 별도의 클래스를 만들어서 진행하는 것이 좋다.
DB의 입출력 테스트라면, 개발된 클래스로 입력과 출력을 테스트해 보고 제대로 수행이 됐는지 알아 보는 식이다.
이러한 테스트를 각각 void main() 메소드를 이용해 진행할 수도 있겠지만 프로그램 규모가 커질 수록, 테스트할 대상이 많아질 수록 개별적으로 테스트 하는 것은 매우 어려운 일이다.
따라서 테스트를 할 때는 테스트 자동화 도구를 이용하는 것이 좋다.
대표적인 테스트 자동화 도구에는 JUnit 이 있다.
테스트 자동화 도구 JUnit을 이용할 때의 장점은 아래와 같다.
1. 테스트의 수행과 결과 확인이 용이하다.
2. 테스트를 위한 자원의 할당과 반환이 효율적이다.
3. 다수의 테스트에서 동일한 명령을 수행해야 할 경우, 해당 명령을 매번 복기하지 않고 미리 정의해 둔 것으로 재사용할 수 있다.
2. 테스트를 위한 자원의 할당과 반환이 효율적이다.
3. 다수의 테스트에서 동일한 명령을 수행해야 할 경우, 해당 명령을 매번 복기하지 않고 미리 정의해 둔 것으로 재사용할 수 있다.
아래는 JUnit을 이용해 Spring 프레임워크에서 ApplicationContext가 하나만 만들어져서 재사용되는지 확인해보는 테스트이다.
package springbook.learningtest.junit;
@RunWith(SpringJUnit4ClassRunner.class) //테스트 중 함께 수행할 class 파일이다.
@ContextConfiguration("junit.xml") //ApplicationContext를 지정해 줄 수 있다.
public class JUnitTest {
@Autowired ApplicationContext context; //Autowired 명령을 통해 자동으로 할당한다.
static Set<JUnitTest> testObjects = new HashSet<JUnitTest>();
static ApplicationContext contextObject = null; //위에서 Autowired 된 context 와 비교를 위한 임시 변수
@Test public void test1() { //@Test Annotation을 삽입하면 JUnit에서 해당 메소드를 테스트 단위로 인식한다.
assertThat(testObjects, not(hasItem(this))); //assertThat()의 두 인수가 서로 같지 않으면 false를 반환한다.
testObjects.add(this);
assertThat(contextObject == null || contextObject == this.context, is(true)); //둘 중 어떤 것이라도 성립하면 true
contextObject = this.context;
}
@Test public void test2() {
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
assertTrue(contextObject == null || contextObject == this.context); //해당 조건이 맞으면 true, 아니면 fasle
contextObject = this.context;
}
@Test public void test3() {
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
assertThat(contextObject, either(is(nullValue())).or(is(this.contextObject))); //either(().or())는 둘 중 어떤 것을 만족해도 true
contextObject = this.context;
}
}
@RunWith(SpringJUnit4ClassRunner.class) //테스트 중 함께 수행할 class 파일이다.
@ContextConfiguration("junit.xml") //ApplicationContext를 지정해 줄 수 있다.
public class JUnitTest {
@Autowired ApplicationContext context; //Autowired 명령을 통해 자동으로 할당한다.
static Set<JUnitTest> testObjects = new HashSet<JUnitTest>();
static ApplicationContext contextObject = null; //위에서 Autowired 된 context 와 비교를 위한 임시 변수
@Test public void test1() { //@Test Annotation을 삽입하면 JUnit에서 해당 메소드를 테스트 단위로 인식한다.
assertThat(testObjects, not(hasItem(this))); //assertThat()의 두 인수가 서로 같지 않으면 false를 반환한다.
testObjects.add(this);
assertThat(contextObject == null || contextObject == this.context, is(true)); //둘 중 어떤 것이라도 성립하면 true
contextObject = this.context;
}
@Test public void test2() {
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
assertTrue(contextObject == null || contextObject == this.context); //해당 조건이 맞으면 true, 아니면 fasle
contextObject = this.context;
}
@Test public void test3() {
assertThat(testObjects, not(hasItem(this)));
testObjects.add(this);
assertThat(contextObject, either(is(nullValue())).or(is(this.contextObject))); //either(().or())는 둘 중 어떤 것을 만족해도 true
contextObject = this.context;
}
}
JUnit을 이용한 테스트든, 전통적인 방식의 WEB UI를 이용한 테스트든..
테스트의 중요성은 따로 말할 필요가 없다.
더 나아가 개발이 잘 됐는지 확인하기 위한 테스트로서가 아니라 TDD(Test Driven Development)로서의 테스트로까지 테스트의 역할을 확장할 필요가 있다.
TDD에 대해서는 따로 언급하지 않는다.