하나의 클래스에 대한 여러 테스트 만들기
테스트를 작성하게 되면 하나의 클래스에 여러 테스트가 작성된다. 예를 들어 다음과 같이 가변 인자로 받는 모든 정수에 대해 곱하기를 실행하는 SimpleMultiplier 객체가 있다고 해보자.
class SimpleMultiplier() {
fun multiplyAll(vararg numbers: Int): Int {
return numbers.fold(1) { acc, number ->
acc * number
}
}
}
이 객체에 대한 간단한 테스트 케이스와 테스트를 작성하면 다음과 같다.
1. 일반적인 곱하기가 제대로 실행되는지 살펴야 한다.
@Test
fun `check_2_multiply_3_is_6`() {
// Given
val simpleMultiplier = SimpleMultiplier()
// When
val result = simpleMultiplier.multiplyAll(2, 3)
// Then
assertEquals(6, result)
}
2. 마이너스에 대한 곱하기가 제대로 동작하는지 살펴야 한다.
@Test
fun `check_-2_multiply_3_is_-6`() {
// Given
val simpleMultiplier = SimpleMultiplier()
// When
val result = simpleMultiplier.multiplyAll(-2, 3)
// Then
assertEquals(-6, result)
}
3. 인자에 0이 들어가면 어떤 값이 들어가던지 0이 나와야 한다.
@Test
fun `check_multiplier_returns_0_if_it_contains_0`() {
// Given
val simpleMultiplier = SimpleMultiplier()
// When
val result = simpleMultiplier.multiplyAll(2, 0, 3)
// Then
assertEquals(0, result)
}
이렇게 하면 SimpleMultiplier에 대한 테스트는 엣지 케이스까지 모두 잘 작성되어 완성도 높은 테스트가 만들어진다. 하지만, 이 테스트 들에는 공통되고 반복되는 부분이 나타난다. 바로 SimpleMultiplier을 초기화 하는 부분이다. 이러한 테스트 환경 설정의 반복을 없애기 위해 @BeforeEach가 등장한다.
@BeforeEach 사용해 테스트 환경 설정하기
JUnit5에서는 @BeforeEach가 붙은 함수는 모든 테스트 실행 전에 공통적으로 실행되는 함수이다. 즉, @BeforeEach를 사용하면 테스트 환경을 설정하기 위해 매번 반복하는 부분들을 한곳에서 관리할 수 있도록 일원화 할 수 있다. 예를 들어 위의 SimpleMultiplier을 초기화 하는 부분은 다음과 같이 일원화 할 수 있다.
class SimpleMultiplierTest {
lateinit var simpleMultiplier : SimpleMultiplier
@BeforeEach
fun setUp() {
simpleMultiplier = SimpleMultiplier()
}
@Test
fun `check_2_multiply_3_is_6`() {
// When
val result = simpleMultiplier.multiplyAll(2, 3)
// Then
assertEquals(6, result)
}
@Test
fun `check_-2_multiply_3_is_-6`() {
// When
val result = simpleMultiplier.multiplyAll(-2, 3)
// Then
assertEquals(-6, result)
}
@Test
fun `check_multiplier_returns_0_if_it_contains_0`() {
// When
val result = simpleMultiplier.multiplyAll(2, 0, 3)
// Then
assertEquals(0, result)
}
}
이렇게 코드를 만들면, 각 테스트 실행 시, @BeforeEach 어노테이션이 붙은 setUp 함수가 실행되어 simpleMultiplier에 새로운 SimpleMultiplier 인스턴스가 생성되어 할당되며, 이를 통해 반복된 코드를 제거할 수 있다.
정리
좋은 테스트를 만들기 위해서 이전 테스트에 다른 테스트가 영향을 받아서는 안된다. 즉, 테스트는 독립적이어야 하며, 테스트가 독립적이기 위해서는 테스트 대상 클래스의 인스턴스가 테스트 간에 공유되어서는 안된다. 이런 경우 @BeforeEach 블록에서 공유되어서는 안되는 클래스의 인스턴스를 초기화 함으로써 테스트의 완성도를 높일 수 있다.