Unit Testing의 1~3장을 읽고 정리한 글입니다.
테스트를 작성하는 일은 아주 아주 중요하다.
사실 근거에 대해 명확히 이해하지 않더라도, 느낌 만으로도 테스트는 중요하다.
(핫픽스를 몇 번 내보면 느낄 수 있다)
다만 "좋은 테스트"를 작성하기 위해서는, 왜 테스트를 해야 하는지 고민해보는 과정이 필요하다고 생각한다. 필자의 생각을 한 번 정리해보았다.
실수를 줄이기 위해
중요하다.테스트는 코드의 문서화
를 돕는다.
테스트 코드를 통해 업무를 더 효율적으로 처리할 수도 있다.
Testable 한 코드를 만드는 것은 코드의 품질을 향상시킨다.
Successful Test Suite
?테스트를 왜 짜야 할 지 고민해보았다.
그렇다면 좋은 테스트란 뭘까?
책 Unit Testing의 저자께서는 아래와 같은 조건들을 제시한다.
💡 SW 개발자는, (심지어 훌륭한 개발자라도) 그 결정이 내려진 이유를 정확히 설명할 수 없다면, 설계 결정에 대해 완전히 인정받지 못한다.
(갑자기 정곡을 찌르는 멋진 문장이 책에 적혀 있길래 인용)
앞선 좋은 테스트의 기준을 다시 정리해보면, 결국 테스트가 필요한 코드와 그렇지 않은 코드를 분리하고, 작성할 수 있어야 한다.
또 그럴 수 있으려면, 코드를 적당한 단위로 격리해서 테스트를 작성해야 한다.
따라서 좋은 테스트에 대한 논의 뒤에 단위 테스트에 대한 논의가 뒤따른다.
단위 테스트란 무엇인가?
책에서의 단위 테스트 정의는 아래와 같다.
고전파
vs 런던파
코드를 어디까지
분리해야 하는가? 에 대한 생각이 다르다.
런던파는 고전파보다 테스트 단위가 좁다.
무조건 한 클래스 (객체)에 대해 테스트를 하고, 모든 의존성은 테스트 대역을 써서 처리하는 것을 지향한다.
격리 주체 | 단위의 크기 | 테스트 더블 사용 대상 | |
---|---|---|---|
런던파 | 단위 | 단일 클래스 | 불변 의존성 외 모든 의존성 |
고전파 | 단위 테스트 | 단일 클래스 또는 클래스 세트 | 공유 의존성 |
Classical school (고전파)
// classical school test
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
internal class MarketTest {
@Test
fun `Purchase Succeeds when enough Inventory`() {
// given
val store = Store()
val customer = Customer()
store.addInventory(Product.Shampoo, 10)
// when
val result = customer.purchase(store, Product.Shampoo, 5)
// then
assertTrue(result)
assertEquals(5, store.getCount(Product.Shampoo))
}
@Test
fun `Purchase Fails when not enough Inventory`() {
// given
val store = Store()
val customer = Customer()
store.addInventory(Product.Shampoo, 10)
// when
val result = customer.purchase(store, Product.Shampoo, 15)
// then
assertFalse(result)
assertEquals(10, store.getCount(Product.Shampoo))
}
}
}
London school (런던파)
@Test
fun `London School Mocks Collaborators`() {
// given
val customer = Customer()
val mockStore = mock<IStore>()
// when
`when`(mockStore.hasEnoughInventory(any(), any())).thenReturn(false)
val result = customer.purchase(mockStore, Product.Shampoo, 5)
// then
assertFalse(result)
verify(mockStore, never()).minus(any(), any())
}
작가는 고전파의 관점에서 단위 테스트를 바라본다.
작가의 견해에는 나름의 이유가 있다. 다음 4, 5장에서 이를 다룬다.