JaeniWorld

[코테스트kotest] 코테스트 기본정리 본문

스터디/TDD

[코테스트kotest] 코테스트 기본정리

jaeni 2023. 6. 14. 23:08
반응형

0. 코테스트 공식 Document 및 특징

 - https://kotest.io/docs/framework/framework.html

 

Introduction | Kotest

introgif

kotest.io

- 코테스트는 java를 이용하여 테스트 하던 개발자들의 편의를 제공하기 위해 탄생 하였고, 기본적으로 테스트 로직을 포함하며 Unit을 반환하는 Function 이다 

- 수동테스트도 지원하며 Kotest DSL(Domain Specific Language: 도메인 특화 언어)로도 작성 가능하다.

- Test Function들은 라벨링 되어있기 때문에 test function/ container/ test case 등을 아무때나 작성할 수 있음 ( test function 작성의 순서는 중요하지 않으며 작성자/ 작성 그룹의 편의대로 작성하면 됨)

 

 

 

 

 

1. 제공하는 테스트 스타일

- 아래와 같이 10가지의 테스트 스타일 제공 

Test Style Inspired By feature
Fun Spec ScalaTest test function에 String argument를 넣어서 사용하며 사용 불가한 기능에 대해
xcontext/xtest function을 사용해 테스트 가능 
Describe Spec JS FrameWorks And Rspec Ruby와 JavaScript에서 사용하는 테스트와 비슷하며 describe와 it을 사용하는 것이 특징
Xcontext는 Xdescribe / Xtest는 Xit으로 대체하여 사용 가능
Should Spec A Kotest Original fun spec과 비슷함 test대신 should function을 사용하여 테스트를 진행할 수 있음
fun spec의 xtest의 역할을 xshould가 동일하게 진행
String Spec A Kotest Original 문자열만 사용하여 테스트 할 때 사용
Behavior Spec BDD frameworks BDD에 뿌리를 두고 있어 given / when / then 키워드 사용하여 테스트 진행
각 function 앞에 사용불가한 기능에 대해 테스트 가능
Free Spec Scala Test  - 를 통해 테스트의 깊이를 구분하여 nest test가능
Word Spec Scala Test should keyword를 사용하여 nest test 가능
Feature Spec CuCumber feature와 senario function을 사용
각 function 앞에 x를 붙여 사용불가한 기능에 대해 테스트 가능
Excpect Spec A Kotest Original funspec과 should spec과 비슷하나 excpect keyword를 사용하는 것이 특징
Annotaion Spec JUnit Junit과 비슷하게 Listener와 테스트 메소드를 Annotaion을 사용하여 라벨링하는 것이 특징

 

 

- 테스트 스타일 코드 예제

  • Fun Spec
init {
        test("문자열 길이 0") {
            "".length shouldBe 0
        }

        context("xtest는 어쩔때 안쓰이는지?") {
            test("테스트가 됩니다") {
                "".length shouldBe 0
            }
            xtest("테스트가 안돼요") {
                println("xtest1")
                "".length shouldBe "xyz"
            }
        }
    }


위의 테스트 코드를 실행하면 두번째 사진과 같이 되는데 xtest는 왼쪽 사진과 같이 금지 표시가 뜸
context단위로 실행해도 xtest 키워드가 쓰인"테스트가 안돼요" 테스트는 테스트 진행이 안되는 것을 알 수 있음

 

 

 

  • String Spec
  init {
        "문자열 길이 0" {
            "".length shouldBe 0
        }

        "xtest는 어쩔때 안쓰이는지?" {
            "테스트가 됩니다" {
                "".length shouldBe 0
            }
            "테스트가 안돼요" {
                println("xtest1")
                "".length shouldBe "xyz"
            }
        }
    }

String Spec은 간단하게 사용하도록 고안된 것이기 때문에 Context / Xtest등의 키워드를 지원하지 않는다

그래서 해당 코드를 돌려보면 "문자열 길이 0"에 대해서는 정상적으로 테스트가 진행되지만
"xtest는 어쩔 때 안쓰이는지?"에 대한 스코프는 테스트가 진행되지 않는다

당연히 해당 스코프 내의 "테스트가 됩니다"와 "테스트가 안돼요"는 진행되지 않음

 

 

 

  • Describe Spec
 init {
        describe("문자열 길이 0") {
            "".length shouldBe 0
        }

        describe("xtest는 어쩔때 안쓰이는지?") {
            it("테스트가 됩니다") {
                "".length shouldBe 0
            }
            xit("테스트가 안돼요") {
                println("xtest1")
                "".length shouldBe "xyz"
            }
        }

        context("얘도 사용 가능?"){
            it("test?"){
                "".length shouldBe 0
            }
        }
    }

FunSpec, Should Spec과 동일하게 동작하나 context와 동일한 역할을 하는 describe가 있는 것이 특징

 

 

 

  • Behavior Spec
init {
        given("a broomstick") {
            and("a witch") {
                `when`("The witch sits on it") {
                    and("she laughs hysterically") {
                        then("She should be able to fly") {
                            println("fly~~")
                        }
                    }
                    and("she can't handle the broomstick"){
                        then("she should be able to work"){
                            println("work~~~")
                        }
                    }
                }
            }
        }
    }

BDD를 기준으로 고안되었기 때문에 given/when/then 키워드가 쓰이는게 특징이며

given과 when context 내에서는 and로 여러 테스트 상황을 만들어 쓸 수 있다.

위의 test들과 비교하자면 given /when 이라는 두개의 라벨링된 context를 사용하는 것이라 볼 수 있다

(아래의  사진)

 

 

 

  • Annotation Spec
@BeforeEach
    fun beforeTest() {
        println("Before each test")
    }

    @Test
    fun test1() {
        1 shouldBe 1
    }

    @Test
    fun test2() {
        3 shouldBe 3
    }

키워드를 사용했던 다른 테스트들과 달리 어노테이션으로 테스트를 표현하고 있다

Context다 따로 없기 때문에 한번에 같은 컨텍스트로 테스트를 진행할 수 없는 것이 String Spec과 비슷함

또한 기존 테스트들은 리스너를 override하여 사용하는 것이 특징이였으나

해당 Spec의 경우는 테스트 범위와 동일하게 어노테이션을 사용하여 리스너 메소드를 정의할 수 있다.

 

 

 

 

2. 테스트 동작 순서

      테스트 전후처리를 위해 제공되는 TestListener는 아래와 같다 

fun Spec.functionOverrideCallbacks() = object : TestListener {
   override suspend fun afterSpec(spec: Spec) {
      this@functionOverrideCallbacks.afterSpec(spec)
   }

   override suspend fun beforeSpec(spec: Spec) {
      this@functionOverrideCallbacks.beforeSpec(spec)
   }

   override suspend fun afterTest(testCase: TestCase, result: TestResult) {
      this@functionOverrideCallbacks.afterTest(testCase, result)
   }

   override suspend fun beforeTest(testCase: TestCase) {
      this@functionOverrideCallbacks.beforeTest(testCase)
   }

   override suspend fun afterContainer(testCase: TestCase, result: TestResult) {
      this@functionOverrideCallbacks.afterContainer(testCase, result)
   }

   override suspend fun beforeContainer(testCase: TestCase) {
      this@functionOverrideCallbacks.beforeContainer(testCase)
   }

   override suspend fun afterEach(testCase: TestCase, result: TestResult) {
      this@functionOverrideCallbacks.afterEach(testCase, result)
   }

   override suspend fun beforeEach(testCase: TestCase) {
      this@functionOverrideCallbacks.beforeEach(testCase)
   }

   override suspend fun afterAny(testCase: TestCase, result: TestResult) {
      this@functionOverrideCallbacks.afterAny(testCase, result)
   }

   override suspend fun beforeAny(testCase: TestCase) {
      this@functionOverrideCallbacks.beforeAny(testCase)
   }
}

 해당 리스너를 모두 override 해서 각각의 리스너들이 실행될때 각 리스너의 이름을 출력하도록 작성해 리스너의 호출 시기를 확인해 보았다.

 

beforeSpec

beforeContainer
beforeAny
beforeTest

beforeEach
beforeAny
beforeTest
테스트1
afterTest
afterAny
afterEach


beforeEach
beforeAny
beforeTest
테스트2
afterTest
afterAny
afterEach

afterTest
afterAny
afterContainer

afterSpec

테스트 2개를 진행하였을때 Spec -> Container -> Any -> Test -> Each 의 순서로 실행되는 것을 확인할 수 있다.

Any와 Tests는 동일한 동작을 진행하며 이 둘은 TestCase 인스턴스를 매개변수로 사용해서 각 테스트가 실행되기 직전에 호출된다.

 

반응형
Comments