Kotest
업데이트:
코틀린에서 가장 많이 사용되는 테스트 프레임워크이다. 코틀린 DSL을 활용해 테스트 코드를 작성할 수 있다.
왜 Kotest?
racing-car 미션을 하는 도중 테스트 코드를 작성할 때였다. 자바에서 하던 대로 Junit
, Assertion
을 이용했다.
class CarTest {
@DisplayName("자동차를 생성한다.")
@Test
fun `create car`() {
//given - when
val car = Car(CarName("jason"))
//then
assertThat(car.getName()).isEqualTo("jason")
assertThat(car.position).isEqualTo(0)
}
}
이렇게 테스트를 채워나가다 kotlin에 특화된 테스트 코드가 있지 않을까 라는 생각이 들어 찾아보다 kotest
를 찾게 되었다. 코틀린이 제공하는 DSL(Domain Specific Language) 스타일의
중괄호를 활용한 코드 스타일을 테스트에도 사용할 수 있게 된다.
Kotest 사용하기
- 먼저 gradle에 의존성을 추가한다.
dependencies {
...
testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion") // $kotestVersion버전에 오류가 나면 원하는 버전 명시
testImplementation("io.kotest:kotest-assertions-core:$kotestVersion")
}
- 인텔리제이 plugin에서 kotest를 찾아 설치한다.
Testing Styles
kotest에는 다양한 레이아웃이 있다. 이 중에 원하는 하나를 상속받아 진행한다. 코틀린만을 위해 만들어진 것도 있고, 기존 테스트 프레임워크에서 영향을 받아 만들어진 것도 있다.
공식 문서는 Testing Styles
- Annotation Spec
나는 Junit 방식과 유사한 Annotation Spec을 사용했다.
internal class CarSpec : AnnotationSpec() { // 상속
@Test
fun `car를 생성한다`() {
//given - when
val car = Car(CarName("jason"))
//then
car.getName() shouldBe "jason"
car.position shouldBe 0 // or car.position.shouldBe(0)
}
}
- Behavior Spec
Given, When, Then을 명시적으로 간결하게 정의할 수 있다.
class CarSpec : BehaviorSpec({
given("create") {
val carName = CarName("jason")
`when`("5자 이하의 이름으로 생성하면") {
val result = Car(carName)
then("Car 생성된다.") {
result.getName() shouldBe "jason"
result.position shouldBe 0
}
}
}
})
이 외에도 다양한 테스트 Spec이 있으니 공식문서를 참고하여 원하는 방식을 선택하면 된다.
Kotest Assertions
Kotest에서 지원해주는 여러 Assertion들을 이용해 테스트를 작성할 수 있다. 몇 가지 표현식들을 살펴보자.
- Multitude of Matchers
- should
- shouldBe
- shouldHave
- shouldNot
- shouldNotBe
- shouldNotHave
이러한 matcher들이 매우 많이 존재한다.
matcher는 두 가지 스타일로 사용 가능하다.
-
중위 함수 스타일
car.getName() shouldBe "jason"
-
확장 함수 스타일
car.getName().shouldBe("jason")
- Inspectors
- forExactly(k) : Collection에서 조건에 해당하는 element의 수가 k개인지
mylist.forExactly(3) { it.city shouldBe "Chicago" }
- forAtLeast(k) : Collection에서 적어도 k개 이상의 element가 조건을 만족
val mylist= listOf("sam", "gareth", "timothy", "muhammad") mylist.forAtLeast(2) { it.shouldHaveMinLength(7) }
- Exceptions
- shouldThrow : [Exception]에 원하는 예외를 넣는다
shouldThrow<[Exception]> { // code in here that you expect to throw an IllegalAccessException }
- shouldThrowAny
val exception = shouldThrowAny { // test here can throw any type of Throwable! }
이러한 것들 말고도 많은 것들이 있으니 필요할 때마다 공식 문서를 참고하면서 작성하면 될 거 같다.
정리
자바 식 테스트 코드 작성법에만 익숙해져 있다 kotest를 이용해서 여러가지 테스트 Spec을 사용해보니 좀 더 직관적이고 다양한 스타일이 있어서 다채롭게 쓸 수 있었다. 현재 미션이 간단해서 unit test만
진행했지만 @SpringBootTest와 Mockk
을 이용해서 통합 테스트도 추후 진행해보려고 한다.
댓글남기기