JUnit을 활용하면 테스트 코드를 원활하게 작성할 수 있다. JUnit의 기초를 학습해보면서 테스트 코드를 작성할 수 있는 기반을 다지도록 하겠다.
JUnit 5 모듈 구성
JUnit 5는 크게 세 가지 모듈로 구성되어 있다.
- JUnit 플랫폼: 테스팅 프레임워크를 구동하기 위한 런처와 테스트 엔진을 위한 API를 제공한다.
- JUnit 주피터(Jupiter): JUnit 5를 위한 테스트 API와 실행 엔진을 제공한다.
- JUnit 빈티지(Vintage): JUnit 3과 4로 작성된 테스트를 JUnit 5 플랫폼에서 실행하기 위한 모듈을 제공한다.
@Test 애노테이션과 테스트 메서드
JUnit 코드의 기본 구조는 간단하다. 테스트로 사용할 클래스를 만들고 @Test 애노테이션을 메서드에 붙이기만 하면 된다. 이때 @Test 애노테이션을 붙인 메서드는 private이면 안 된다는 점을 주의해야 한다. 예시는 다음과 같다.
public class CalculatorTest {
@Test
void plus(){
int result = Calculator.plus(1, 2);
assertEquals(3, result);
assertEquals(5, Calculator.plus(1, 4));
}
}
JUnit 5 버전과 JUnit 4 버전은 패키지 구조나 일부 제약 조건 등이 다르다. 같은 기능이라도 버전에 따라 다른 패키지 구조를 가질 수 있다는 점을 주의해야 한다.
주요 단언 메서드
메서드 | 설명 |
assertEquals(expected, actual) | 실제 값이 기대하는 값과 같은지 검사한다. |
assertNotEquals(expected, actual) | 실제 값이 기대하는 값과 같지 않은지 검사한다. |
assertSame(Object expected, Object actual) | 두 객체가 동일한 객체인지 검사한다. |
assertNotSame(Object expected, Object actual) | 두 객체가 동일하지 않은 객체인지 검사한다. |
assertTrue(boolean condition) | 값이 true인지 검사한다. |
assertFalse(boolean condition)) | 값이 false인지 검사한다. |
assertNull(Object actual) | 값이 null인지 검사한다. |
assertNotNull(Object actual) | 값이 null이 아닌지 검사한다. |
fail() | 테스트를 실패 처리한다. |
테스트 라이프사이클
@BeforeEach 와 @AfterEach
JUnit은 각 테스트 메서드마다 다음 순서대로 코드를 실행한다.
- 테스트 메서드를 포함한 객체 생성
- @BeforeEach 애노테이션이 붙은 메서드 실행
- @Test 애노테이션이 붙은 메서드 실행
- @AfterEach 애노테이션이 붙은 메서드 실행
동작 방식을 이해하기 위해 작성한 간단한 코드이다.
public class LifecycleTest {
public LifecycleTest(){
System.out.println("new Lifecycle Test");
}
@BeforeEach
void setUp(){
System.out.println("setUp");
}
@Test
void first() {
System.out.println("first");
}
@Test
void second() {
System.out.println("second");
}
@AfterEach
void tearDown() {
System.out.println("tearDown");
}
}
위 테스트 클래스의 실행 결과는 다음과 같다.
결과를 보면 @Test 애노테이션이 붙은 메서드가 실행될 때마다 객체를 새로 생성하고 테스트 메서드가 실행되기 전후로 @BeforeEach와 @AfterEach이 붙은 메서드가 실행되는 것을 확인할 수 있다.
@BeforeEach는 테스트를 실행하는데 필요한 준비 작업을 할 때 사용한다. 테스트에서 사용할 객체나 임시 파일을 생성하는 작업 등을 이곳에서 수행한다.
@AfterEach는 테스트를 실행한 후에 정리할 것이 있을 때 사용한다. 테스트에서 사용한 임시 파일을 삭제하거나 테스트를 수행하기 이전의 상태로 돌려놓기 위한 작업을 이곳에서 수행한다.
@BeforeAll 와 @AfterAll
@BeforeAll은 클래스의 모든 테스트 메서드를 실행하기 전에 한 번 실행된다. 한 클래스의 모든 테스트 메서드가 실행되기 전에 특정 작업을 수행해야 할 때 사용한다.
@AfterAll은 클래스의 모든 테스트 메서드가 끝난 뒤에 한 번 실행된다. 한 클래스의 모든 테스트 메서드가 실행된 후 특정 작업을 수행해야 할 때 사용한다.
테스트 메서드 간 실행 순서 의존과 필드 공유 문제
테스트 메서드가 특정 순서에 의해 실행된다는 가정하에 테스트 메서드를 작성하면 안 된다. JUnit이 테스트 순서를 결정하긴 하지만 그 순서는 버전에 따라 달라질 수 있다. 순서 달라지면 테스트도 실패한다.
각 테스트 메서드는 독립적으로 동작해야 한다. 테스트 메서드가 서로 필드를 공유하는 행위를 하지 말아야 한다. 한 테스트 메서드의 결과에 따라 다른 테스트의 메서드의 실행 결과가 달라지기 때문이다.
테스트 코드도 유지보수가 중요하다는 것을 잊지 말아야 한다. 테스트 메서드 간 의존이 생기면 유지보수를 어렵게 만든다.
|References
테스트 주도 개발 시작하기, 최범균
'TDD' 카테고리의 다른 글
[테스트 코드의 구성] (0) | 2023.02.04 |
---|---|
[TDD 기능 명세 ∙ 설계] (0) | 2023.01.31 |
[TDD 테스트 코드 작성 순서] (0) | 2023.01.15 |