Skip to content

Latest commit

ย 

History

History
828 lines (741 loc) ยท 30.1 KB

kotest.md

File metadata and controls

828 lines (741 loc) ยท 30.1 KB

Kotest

Index

KoTest๋ž€

  • Kotest DSL์„ ์‚ฌ์šฉ
  • ์—ฌ๋Ÿฌ TestStyle์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ณ  ์•„๋ฆ„๋‹ค์šด ํ…Œ์ŠคํŠธ ์ž‘์„ฑ
  • ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋กœ ๋งŽ์€ ์–‘์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ
  • ๋ชจ๋“  ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ํ˜ธ์ถœ์ˆ˜, ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ, ์‹œ๊ฐ„์ œํ•œ, ํ…Œ์ŠคํŠธ๊ทธ๋ฃนํ™”, ์กฐ๊ฑด๋ถ€๋น„ํ™œ์„ฑ๋“ฑ์˜ ๋ฏธ์„ธ ์กฐ์ • ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ
  • ์ค‘์ฒฉ ํ…Œ์ŠคํŠธ๊ธฐ๋Šฅ ์ œ๊ณต
  • ๋™์ ํ…Œ์ŠคํŠธ ์ œ๊ณต (๋Ÿฐํƒ€์ž„์— ์กฐ๊ฑด๋ถ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ)
  • ํ…Œ์ŠคํŠธ์ˆ˜๋ช…์ฃผ๊ธฐ์— ๋งž๋Š” ๋‹ค์–‘ํ•œ ์ฝœ๋ฐฑ์„ ์ œ๊ณต

ํ…Œ์ŠคํŠธ ์Šคํƒ€์ผ

ํ…Œ์ŠคํŠธ ์Šคํƒ€์ผ ์˜๊ฐ๋ฐ›์€๊ฒƒ
Fun Spec ScalaTest
Describe Spec Javascript frameworks a nd RSpec
Should Spec A Kotest original
String Spec A Kotest original
Behavior Spec BDD frameworks
Free Spec ScalaTest
Word Spec ScalaTest
Feature Spec Cucumber
Expect Spec A Kotest original
Annotation Spec JUnit

Fun Spec

FunSpec ํ…Œ์ŠคํŠธ๋Š” test๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ์œ„ํ•ด ๋ฌธ์ž์—ด์ธ์ˆ˜๋กœ ํ˜ธ์ถœ๋œ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค์Œ
ํ…Œ์ŠคํŠธ ์ž์ฒด๋ฅผ ๋žŒ๋‹ค๋กœ ํ˜ธ์ถœํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : FunSpec({
    test("String length should return the length of the string") {
        "sammy".length shouldBe 5
        "".length shouldBe 0
    }
})

String Spec

StringSpec ํ…Œ์ŠคํŠธ๋Š” ๊ตฌ๋ฌธ์„ ์ ˆ๋Œ€ ์ตœ์†Œ๊ฐ’์œผ๋กœ ์ค„์ธ๋‹ค.
ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ๋ฌธ์ž์—ด ๋‹ค์Œ์— ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์ž‘์„ฑํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

class MyTests : StringSpec({
    "strings.length should return size of string" {
        "hello".length shouldBe 5
    }
})

Config ์ถ”๊ฐ€

class MyTests : StringSpec({
    "strings.length should return size of string".config(enabled = false, invocations = 3) {
        "hello".length shouldBe 5
    }
})

Should Spec

ShouldSpec์€ FunSpec๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ testํ‚ค์›Œ๋“œ ๋Œ€์‹  should ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

class MyTests : ShouldSpec({
    should("return the length of the string") {
        "sammy".length shouldBe 5
        "".length shouldBe 0
    }
})

context ๋ธ”๋ก๊ณผ๋„ ์ค‘์ฒฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

class MyTests : ShouldSpec({
    context("String.length") {
        should("return the length of the string") {
            "sammy".length shouldBe 5
            "".length shouldBe 0
        }
    }
})

xshould, xcontext ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : ShouldSpec({
    context("this outer block is enabled") {
        xshould("this test is disabled") {
            // test here
        }
    }
    xcontext("this block is disabled") {
        should("disabled by inheritance from the parent") {
            // test here
        }
    }
})

Describe Spec

DescribeSpec์˜ ํ…Œ์ŠคํŠธ ์Šคํƒ€์ผ์€ describe / it ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. (Ruby, JS ์Šคํƒ€์ผ)
ํ…Œ์ŠคํŠธ๋Š” ํ•˜๋‚˜ ์ด์ƒ์˜ describe ๋ธ”๋ก์— ์ค‘์ฒฉ๋˜์–ด์•ผํ•œ๋‹ค.

class MyTests : DescribeSpec({
    describe("score") {
        it("start as zero") {
            // test here
        }
        describe("with a strike") {
            it("adds ten") {
                // test here
            }
            it("carries strike to the next frame") {
                // test here
            }
        }

        describe("for the opposite team") {
            it("Should negate one score") {
                // test here
            }
        }
    }
})

xdescribe, xit์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : DescribeSpec({
    describe("this outer block is enabled") {
        xit("this test is disabled") {
            // test here
        }
    }
    xdescribe("this block is disabled") {
        it("disabled by inheritance from the parent") {
            // test here
        }
    }
})

Behavior Spec

BDDBehavior Driven Development ์Šคํƒ€์ผ์˜ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ๋ฐฉ๋ฒ•์œผ๋กœ
given, when, then์„ ์‚ฌ์šฉ

when์ด ์ฝ”ํ‹€๋ฆฐ ์˜ˆ์•ฝ์–ด์™€ ๊ฒน์น˜๋ฏ€๋กœ ์—ญ๋”ฐ์˜ดํ‘œ๋กœ ๋ฌถ์–ด์•ผ ํ•œ๋‹ค.
์—ญ๋”ฐ์˜ดํ‘œ ์‚ฌ์šฉ์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” Given, When, Then ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

class MyTests : BehaviorSpec({
    given("a broomstick") {
        `when`("I sit on it") {
            then("I should be able to fly") {
                // test code
            }
        }
        `when`("I throw it away") {
            then("it should come back") {
                // test code
            }
        }
    }
})

and๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ given๊ณผ when์— depth๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : BehaviorSpec({
    given("a broomstick") {
        and("a witch") {
            `when`("The witch sits on it") {
                and("she laughs hysterically") {
                    then("She should be able to fly") {
                        // test code
                    }
                }
            }
        }
    }
})

xgiven, xwhen, xthen์„ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : DescribeSpec({
    xgiven("this is disabled") {
        When("disabled by inheritance from the parent") {
            then("disabled by inheritance from its grandparent") {
                // disabled test
            }
        }
    }
    given("this is active") {
        When("this is active too") {
            xthen("this is disabled") {
               // disabled test
            }
        }
    }
})

Word Spec

WordSpec์€ context ๋ฌธ์ž์—ด๋’ค์— ํ…Œ์ŠคํŠธ๋ฅผ ํ‚ค์›Œ๋“œ should๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

class MyTests : WordSpec({
    "String.length" should {
        "return the length of the string" {
            "sammy".length shouldBe 5
            "".length shouldBe 0
        }
    }
})

๋˜ํ•œ ๋‹ค๋ฅธ ์ˆ˜์ค€์˜ ์ค‘์ฒฉ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” When ํ‚ค์›Œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค. when๋Š” Kotlin์˜ ํ‚ค์›Œ๋“œ ์ด๋ฏ€๋กœ ์—ญ๋”ฐ์˜ดํ‘œ ๋˜๋Š” ๋Œ€๋ฌธ์ž ๋ณ€ํ˜•์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

class MyTests : WordSpec({
    "Hello" When {
        "asked for length" should {
            "return 5" {
                "Hello".length shouldBe 5
            }
        }
        "appended to Bob" should {
            "return Hello Bob" {
                "Hello " + "Bob" shouldBe "Hello Bob"
            }
        }
    }
})

Free Spec

FreeSpec ํ‚ค์›Œ๋“œ -(๋นผ๊ธฐ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž„์˜์˜ ๊นŠ์ด ์ˆ˜์ค€์„ ์ค‘์ฒฉํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : FreeSpec({
    "String.length" - {
        "should return the length of the string" {
            "sammy".length shouldBe 5
            "".length shouldBe 0
        }
    }
    "containers can be nested as deep as you want" - {
        "and so we nest another container" - {
            "yet another container" - {
                "finally a real test" {
                    1 + 1 shouldBe 2
                }
            }
        }
    }
})

Feature Spec

FeatureSpec์€ feature, scenario๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. (cucumber์™€ ๋น„์Šทํ•˜๋‹ค)

class MyTests : FeatureSpec({
    feature("the can of coke") {
        scenario("should be fizzy when I shake it") {
            // test here
        }
        scenario("and should be tasty") {
            // test here
        }
    }
})

xsceanario, xfeature๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : FeatureSpec({
    feature("this outer block is enabled") {
        xscenario("this test is disabled") {
            // test here
        }
    }
    xfeature("this block is disabled") {
        scenario("disabled by inheritance from the parent") {
            // test here
        }
    }
})

Expect Spec

ExpectSpec์€ FunSpec, ``ShouldSpec๊ณผ ๋น„์Šทํ•˜๋ฉฐ, expect` ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

class MyTests : ExpectSpec({
    expect("my test") {
        // test here
    }
})

context ๋ธ”๋Ÿญ์— ํ•˜๋‚˜ ์ด์ƒ ์ค‘์ฒฉํ•˜์—ฌ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : ExpectSpec({
    context("a calculator") {
        expect("simple addition") {
            // test here
        }
        expect("integer overflow") {
            // test here
        }
    }
})

xexpect, xcontext๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTests : DescribeSpec({
    context("this outer block is enabled") {
        xexpect("this test is disabled") {
            // test here
        }
    }
    xcontext("this block is disabled") {
        expect("disabled by inheritance from the parent") {
            // test here
        }
    }
})

Annotation Spec

JUnit์—์„œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๊ฒฝ์šฐ AnnotationSpecJUnit์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.(Junit 4/5์™€ ๋™์ผํ•œ ์ฃผ์„์„ ์‚ฌ์šฉ)
์ •์˜ํ•œ ํ•จ์ˆ˜์— @Test ์ฃผ์„์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

JUnit๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ํ…Œ์ŠคํŠธ ์ด์ „๊ณผ ํ…Œ์ŠคํŠธ ์ดํ›„๋“ฑ์— ๋ฌด์–ธ๊ฐ€๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด Annotation์„ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

@BeforeAll / @BeforeClass
@BeforeEach / @Before
@AfterAll / @AfterClass
@AfterEach / @After

JUnit ์ž์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์ด์ ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ธฐ์กด ํ˜•์‹์„ ๊ทธ๋Œ€๋กœ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด ๋” ๋น ๋ฅด๊ฒŒ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

class  AnnotationSpecExample : AnnotationSpec () { 

    @BeforeEach fun beforeTest () {
         println ( " ๊ฐ ํ…Œ์ŠคํŠธ ์ „ " ) 
    } 
    @Test fun test1 () {
         1 shouldBe 1 
    } 
    @Test fun test2 () {
         3 shouldBe 3 
    } 
}

ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™” ํ•˜๋ ค๋ฉด @Ignore๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

์กฐ๊ฑด๋ถ€๋กœ ํ…Œ์ŠคํŠธ ์‹คํ–‰ํ•˜๊ธฐ

ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ํ…Œ์ŠคํŠธ์—์„œ ํ•˜๋“œ์ฝ”๋”ฉํ•˜๊ฑฐ๋‚˜, ๋Ÿฐํƒ€์ž„์— ์กฐ๊ฑด๋ถ€๋กœ ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

Config

config ๋งค๊ฐœ๋ณ€์ˆ˜์˜ enabled๋ฅผ false๋กœ ์„ค์ •ํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

"should do something".config(enabled = false) {
  ...
}

SystemUtils.IS_OS_LINUX๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฆฌ๋ˆ…์Šคํ™˜๊ฒฝ์—์„œ๋งŒ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š”๋“ฑ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

"should do something".config(enabled = IS_OS_LINUX) {
  ...
}

๊ฐ’์ด ์•„๋‹Œ ํ…Œ์ŠคํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋น„ํ™œ์„ฑํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด enabledIf๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜๋Š” ๋ฆฌ๋ˆ…์Šคํ™˜๊ฒฝ์ด๊ฑฐ๋‚˜, ํ…Œ์ŠคํŠธ์ด๋ฆ„์— "danger"๊ฐ€ ๋“ค์–ด๊ฐ€์ง€์•Š๋Š” ํ…Œ์ŠคํŠธ๋งŒ ์‹คํ–‰ํ•œ๋‹ค. ใ„ด

val disableDangerOnWindows: EnabledIf = { !it.name.startsWith("danger") || IS_OS_LINUX }

"danger will robinson".config(enabledIf = disableDangerOnWindows) {
  // test here
}

"very safe will".config(enabledIf = disableDangerOnWindows) {
 // test here
}

Focus

์ตœ์ƒ์œ„ ๋ ˆ๋ฒจ ํ…Œ์ŠคํŠธ ์ด๋ฆ„ ์•ž์—์œผ๋กœ f:๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด ํ•ด๋‹น ํ…Œ์ŠคํŠธ ๋ฐ ํ•ด๋‹น๋ฒ”์œ„๋‚ด์— ์ •์˜๋œ ๋ชจ๋“  ํ•˜์œ„ ํ…Œ์ŠคํŠธ๋“ค๋งŒ ์‹คํ–‰๋˜๊ณ 
๋‚˜๋จธ์ง€๋Š” ํ…Œ์ŠคํŠธ๋“ค์€ ๊ฑด๋„ˆ๋’จ๋‹ค.

class FocusExample : StringSpec({
    "test 1" {
     // this will be skipped
    }

    "f:test 2" {
     // this will be executed
    }

    "test 3" {
     // this will be skipped
    }
})

์ค‘์ฒฉ ํ…Œ์ŠคํŠธ๋Š” ์ƒ์œ„ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋œ ํ›„์—๋งŒ ๊ฒ€์ƒ‰๋˜๊ธฐ ๋•Œ๋ฌธ์— ํฌ์ปค์Šค๋ชจ๋“œ๋Š” ์ค‘์ฒฉ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด์„œ๋Š” ์ž‘๋™ ํ•˜์ง€ ์•Š์Œ.

Bang

Focus์˜ ๋ฐ˜๋Œ€๊ธฐ๋Šฅ์œผ๋กœ ํ…Œ์ŠคํŠธ์ด๋ฆ„์— ์ ‘๋‘์–ด !๋ฅผ ๋ถ™ํžŒ ํ…Œ์ŠคํŠธ๋งŒ ๊ฑด๋„ˆ๋›ด๋‹ค.

class BangExample : StringSpec({

  "!test 1" {
    // this will be ignored
  }

  "test 2" {
    // this will run
  }

  "test 3" {
    // this will run too
  }
})

X-Method

kotest์˜ spec๋“ค์€ ํ…Œ์ŠคํŠธํ•จ์ˆ˜๊ฐ€ x๋กœ ์‹œ์ž‘ํ•˜๊ฒŒ๋˜๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•œ๋‹ค.(JS Style์ž„)

class XMethodsExample : DescribeSpec({

  xdescribe("this block and it's children are now disabled") {
    it("will not run") {
      // disabled test
    }
  }

})

@Ignored

๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด @Ignored ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
Spec์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ์ธ์Šคํ„ด์Šคํ™”ํ•˜์ง€๋„ ์•Š๋Š”๋‹ค.

@Ignored
class IgnoredSpec : FunSpec() {
  init {
    error("boom") // spec will not be created so this error will not happen
  }
}

@EnabledIf

@Ignored์™€ ์œ ์‚ฌํ•˜๊ฒŒ Spec์„ ์ธ์Šคํ„ด์Šคํ™”ํ•ด์•ผ ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

class LinuxOnlyCondition : EnabledCondition() {
   override fun enabled(specKlass: KClass<out Spec>): Boolean =
      if (specKlass.simpleName?.contains("Linux") == true) IS_OS_LINUX else true
}

์ ์šฉ

@EnabledIf(LinuxOnlyCondition::class)
class MyLinuxTest1 : FunSpec() {
  ..
}

@EnabledIf(LinuxOnlyCondition::class)
class MyLinuxTest2 : DescribeSpec() {
  ..
}

Gradle์—์„œ ํ•„ํ„ฐ๋งํ•˜๊ธฐ

gradle์„ ํ†ตํ•ด JUnit ํ”Œ๋žซํผ ๋Ÿฌ๋„ˆ๋ฅผ ํ†ตํ•ด Kotest๋ฅผ ์‹คํ–‰ํ•  ๋•Œ Kotest๋Š” ํ…Œ์ŠคํŠธ ํ•„ํ„ฐ๋ง์„ ์œ„ํ•œ ํ‘œ์ค€ gradle ๊ตฌ๋ฌธ์„ ์ง€์›ํ•œ๋‹ค.
๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋˜๋Š” --tests ๋ช…๋ น์ค„ ์˜ต์…˜์„ ํ†ตํ•ด ํ•„ํ„ฐ๋ง์„ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

tasks.test {
    filter {
        //include all tests from package
        includeTestsMatching("com.sksamuel.somepackage.*")
    }
}
$ ./gradlew test --tests 'com.sksamuel.somepackage*'

ํด๋ž˜์Šค ์ˆ˜์ค€๋งŒ ํ•„ํ„ฐ๋ง ๊ฐ€๋Šฅํ•˜๋‹ค(๊ฐœ๋ณ„ ๋ฉ”์†Œ๋“œ XX)

Isolation Modes

๊ฒฉ๋ฆฌ๋ชจ๋“œ(Isolation Modes)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ŠคํŠธ ์—”์ง„์ด ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์— ๋Œ€ํ•œ ์‚ฌ์–‘ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค. IsolationMode๋ผ๋Š” enum์œผ๋กœ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ SingleInstance, InstancePerLeaf, InstancePerTest๊ฐ’์ด ์žˆ๋‹ค.

isolationMode์— ๊ฐ’์„ ํ• ๋‹นํ•˜๊ฑฐ๋‚˜, fun isolationMode()์„ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜์—ฌ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

class MyTestClass : WordSpec({
 isolationMode = IsolationMode.SingleInstance
 // tests here
})
class MyTestClass : WordSpec() {
  override fun isolationMode() = IsolationMode.SingleInstance
  init {
    // tests here
  }
}

SingleInstance

๊ธฐ๋ณธ ๊ฒฉ๋ฆฌ๋ชจ๋“œ๋Š” SingleInstance์œผ๋กœ Specํด๋ž˜์Šค์˜ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋œ ๋‹ค์Œ
๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ฐ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ์ฐจ๋ก€๋กœ ์‹คํ–‰๋˜๋Š” ๋ฐฉ์‹์ด๋‹ค.

// ๋ชจ๋“  ํ…Œ์ŠคํŠธ์— ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ๋™์ผํ•œ ID๊ฐ€ ์„ธ ๋ฒˆ ์ธ์‡„๋œ๋‹ค.
class SingleInstanceExample : WordSpec({
   val id = UUID.randomUUID()
   "a" should {
      println(id)
      "b" {
         println(id)
      }
      "c" {
         println(id)
      }
   }
})

InstancePerTest

IsolationMode.InstancePerTest๋ชจ๋“œ๋Š” ๋‚ด๋ถ€ ์ปจํ…์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜์—ฌ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์— ๋Œ€ํ•ด ์ƒˆ Spec์ด ์ƒ์„ฑ๋œ๋‹ค.
์ฆ‰, ์™ธ๋ถ€ ์ปจํ…์ŠคํŠธ๋Š” Spec์˜ ์ž์ฒด ์ธ์Šคํ„ด์Šค์—์„œ "๋…๋ฆฝ ์‹คํ–‰ํ˜•" ํ…Œ์ŠคํŠธ๋กœ ์‹คํ–‰๋œ๋‹ค.

class InstancePerTestExample : WordSpec() {

  override fun isolationMode(): IsolationMode = IsolationMode.InstancePerTest

  init {
    "a" should {
      println("Hello")
      "b" {
        println("From")
      }
      "c" {
        println("Sam")
      }
    }
  }
}

์ถœ๋ ฅ๊ฐ’์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค

Hello
Hello
From
Hello
Sam

์™ธ๋ถ€ ์ปจํ…์ŠคํŠธ(ํ…Œ์ŠคํŠธ "a")๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๊ณ , ๊ทธ ๋‹ค์Œ (ํ…Œ์ŠคํŠธ "b")์— ๋Œ€ํ•ด ๋‹ค์‹œ ์‹คํ–‰๋˜๊ณ , (ํ…Œ์ŠคํŠธ "c")์— ๋Œ€ํ•ด ๋‹ค์‹œ ์‹คํ–‰๋œ๋‹ค.
Spec ํด๋ž˜์Šค์˜ ๊นจ๋—ํ•œ ์ธ์Šคํ„ด์Šค์—์„œ ๋งค๋ฒˆ, ๋ณ€์ˆ˜๋ฅผ ์žฌ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•˜๋‹ค.

๋˜ ๋‹ค๋ฅธ ์˜ˆ์‹œ

class InstancePerTestExample : WordSpec() {

  override fun isolationMode(): IsolationMode = IsolationMode.InstancePerTest

  val counter = AtomicInteger(0)

  init {
    "a" should {
      println("a=" + counter.getAndIncrement())
      "b" {
        println("b=" + counter.getAndIncrement())
      }
      "c" {
        println("c=" + counter.getAndIncrement())
      }
    }
  }
}

์ถœ๋ ฅ๊ฐ’

a=0 a=0 b=1 a=0 c=1

InstancePerLeaf

IsolationMode.InstancePerLeaf๋Š” ํ•˜์œ„ ํ…Œ์ŠคํŠธ๋งŒ ์ƒˆ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

class InstancePerLeafExample : WordSpec() {

  override fun isolationMode(): IsolationMode = IsolationMode.InstancePerLeaf

  init {
    "a" should {
      println("Hello")
      "b" {
        println("From")
      }
      "c" {
        println("Sam")
      }
    }
  }
}

"a" ํ…Œ์ŠคํŠธ๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๊ณ  ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค์—์„œ "b" ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
๊ทธ๋Ÿฐ ๋‹ค์Œ ์ƒˆ ์‚ฌ์–‘์ด ์ƒ์„ฑ๋˜๊ณ  ํ…Œ์ŠคํŠธ "a"๊ฐ€ ๋‹ค์‹œ ์‹คํ–‰๋œ ๋‹ค์Œ ํ…Œ์ŠคํŠธ "c"๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

Hello
From
Hello
Sam

Global Isolation Mode

์‹œ์Šคํ…œ ์†์„ฑ์„ ํ†ตํ•ด ์ „์—ญ์ ์œผ๋กœ ๊ฒฉ๋ฆฌ๋ชจ๋“œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

class ProjectConfig: AbstractProjectConfig() {
   override val isolationMode = IsolationMode.InstancePerLeaf
}

Assertions

Kotest๋Š” ํ˜„์žฌ ์—ฌ๋Ÿฌ๋ชจ๋“ˆ์— ๊ฑธ์ณ ์•ฝ 325๊ฐœ์˜ matcher๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.
Kotest matcher๋ฅผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์— ๊ตฌ์• ๋ฐ›์ง€์•Š๊ณ  Kotest ํ”„๋ ˆ์ž„์›Œํฌ ๋˜๋Š” ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Style

matcher๋Š” ๋‘ ๊ฐ€์ง€ ์Šคํƒ€์ผ์„ ์ œ๊ณตํ•œ๋‹ค.

ํ™•์žฅํ•จ์ˆ˜ ์Šคํƒ€์ผ

a.shouldStartWith("foo")

์ค‘์œ„ํ•จ์ˆ˜ ์Šคํƒ€์ผ

a should startWith("foo")

Core Matchers

kotest-assertions-core๋ชจ๋“ˆ์—์„œ ์ œ๊ณตํ•˜๋Š” Matcher

๋ฒ”์šฉ

  • obj.shouldBe(other) : ์ฃผ์–ด์ง„ obj์™€ other๊ฐ€ ๋ชจ๋‘ ๊ฐ™๋‹ค๋Š” ๋ฒ”์šฉ assertion
  • expr.shouldBeTrue() : ํ‘œํ˜„์‹์ด true์ธ์ง€ ํ™•์ธ
  • expr.shouldBeFalse() : ํ‘œํ˜„์‹์ด false์ธ์ง€ ํ™•์ธ
  • shouldThrow<T> { block } : ๋ธ”๋ก์ด T Throwable ๋˜๋Š” ํ•˜์œ„ ์œ ํ˜•์„ throwํ•˜๋Š”์ง€ ํ™•์ธ
  • shouldThrowExactly<T> { block } : ๋ธ”๋ก์ด ์ •ํ™•ํžˆ ์˜ˆ์™ธ๋ฅผ throwํ•˜๋Š”์ง€ ํ™•์ธ
  • shouldThrowAny { block } : ๋ธ”๋ก์ด ๋ชจ๋“  ์œ ํ˜•์˜ throwable์„ throwํ•˜๋Š”์ง€ ํ™•์ธ
  • shouldThrowMessage(message) { block } : ์ฝ”๋“œ ๋ธ”๋ก์ด ์ฃผ์–ด์ง„ ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ ๋ชจ๋“  throwable์„ throwํ•˜๋Š”์ง€ ํ™•์ธ

ํƒ€์ž…

  • obj.shouldBeSameInstanceAs(other) : ๊ฐœ์ฒด๋ฅผ ID๋กœ ๋น„๊ตํ•˜์—ฌ ์ •ํ™•ํžˆ ๋™์ผํ•œ ์ฐธ์กฐ์ธ์ง€ ํ™•์ธ
  • obj.shouldBeTypeOf<T>() : ์ฃผ์–ด์ง„ Type์ด ์ •ํ™•ํžˆ T ์œ ํ˜•์ด๋ผ๊ณ  ํ™•์ธ, ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์‹คํŒจํ•œ๋‹ค
  • obj.shouldBeInstanceOf<T> : ์ฃผ์–ด์ง„ ์ฐธ์กฐ๊ฐ€ T ์œ ํ˜• ๋˜๋Š” T์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ž„์„ ํ™•์ธ
  • obj.shouldHaveAnnotation(annotationClass) : ์ฃผ์–ด์ง„ ์ธ์Šคํ„ด์Šค์—์— ์ง€์ •๋œ ์œ ํ˜•์˜ Annotation์ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • obj.shouldBeNull() : ์ง€์ •๋œ ์ฐธ์กฐ๊ฐ€ null์ž„์„ ํ™•์ธ

๋น„๊ต

  • comp.shouldBeLessThan(other) : compareTo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ comp๊ฐ€ other๋ณด๋‹ค ๋ฏธ๋งŒ์ธ์ง€ ํ™•์ธ
  • comp.shouldBeLessThanOrEqualTo(other) : compareTo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ comp๊ฐ€ other๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ™•์ธ
  • comp.shouldBeEqualComparingTo(other) : compareTo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ comp๊ฐ€ other๋ณด๋‹ค ๊ฐ™์€์ง€ ํ™•์ธ
  • comp.shouldBeEqualComparingTo(other, comparator) : comparator.compare๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ comp์™€ other์ด ๊ฐ™์€์ง€ ํ™•์ธ
  • comp.shouldBeGreaterThan(other) : compareTo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ comp๊ฐ€ other๋ณด๋‹ค ํฐ์ง€ ํ™•์ธ
  • comp.shouldBeGreaterThanOrEqualTo(other) : compareTo๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ comp๊ฐ€ other๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ™•์ธ

Iterator

  • iterator.shouldBeEmpty() : iterator์— ๋‹ค์Œ๊ฐ’์ด ์—†๋Š”์ง€ ๊ฒ€์ฆ
  • iterator.shouldHaveNext() : iterator์— ๋‹ค์Œ๊ฐ’์ด ์žˆ๋Š”์ง€ ๊ฒ€์ฆ

Map

  • map.shouldContain("key", "value") : map์— "key"์— ๋Œ€ํ•ด ๋งคํ•‘๋˜๋Š” "value"๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
  • map.shouldContainAll(other) : map๊ณผ other์ด ๋™์ผํ•œ ์Œ์„ ํฌํ•จํ•˜๋Š”์ง€ ํ™•์ธ
  • map.shouldContainExactly(other) : map๊ณผ other์ด ์ •ํ™•ํ•˜๊ฒŒ ๋™์ผํ•œ ์Œ์„ ํฌํ•จํ•˜๋Š”์ง€(๋‹ค๋ฅธ ์Œ์€ ์—†์–ด์•ผํ•จ) ํ™•์ธ
  • map.shouldContainKey(key) : map์— "key"์˜ ๊ฐ’์ด ํฌํ•จ๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธ
  • map.shouldContainKeys(keys) : map์— ์ฃผ์–ด์ง„ "keys"์— ๋ชจ๋“  ๊ฐ’์ด ๋งคํ•‘๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธ
  • map.shouldContainValue(value) : map์— ์ฃผ์–ด์ง„ "value"๊ฐ€ ํ•˜๋‚˜์ด์ƒ ๋งคํ•‘๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธ
  • map.shouldContainValues(values) : map์— ์ฃผ์–ด์ง„ "values"๊ฐ€ ๋ชจ๋‘ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธ
  • map.shouldBeEmpty() : map์ด ๋น„์–ด์žˆ๋Š”์ง€ ํ™•์ธ

String

  • str.shouldBeBlank() : ๋ฌธ์ž์—ด์ด nullOrEmpty์ธ์ง€ ํ™•์ธ
  • str.shouldBeEmpty() : ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ 0์ž„์„ ํ™•์ธ
  • str.shouldBeLowerCase() : ๋ฌธ์ž์—ด์ด ๋ชจ๋‘ ์†Œ๋ฌธ์ž์ธ์ง€ ํ™•์ธ
  • str.shouldBeUpperCase() : ๋ฌธ์ž์—ด์ด ๋ชจ๋‘ ๋Œ€๋ฌธ์ž์ž„์„ ํ™•์ธ
  • str.shouldContain("substr") : ๋ฌธ์ž์—ด์— ์ง€์ •๋œ ํ•˜์œ„ ๋ฌธ์ž์—ด์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ. ํ•˜์œ„ ๋ฌธ์ž์—ด์€ ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ๊ณ , ๋Œ€ ์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค
  • str.shouldContain(regex) : ๋ฌธ์ž์—ด์— ์ฃผ์–ด์ง„ ์ •๊ทœ ํ‘œํ˜„์‹์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • str.shouldContainADigit() : ๋ฌธ์ž์—ด์— ์ตœ์†Œํ•œ ํ•˜๋‚˜์˜ ์ˆซ์ž๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • str.shouldContainIgnoringCase(substring) : ๋ฌธ์ž์—ด์— ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ํ•˜์œ„ ๋ฌธ์ž์—ด์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • str.shouldContainOnlyDigits() : ๋ฌธ์ž์—ด์— ์ˆซ์ž๋งŒ ํฌํ•จ๋˜์–ด ์žˆ๊ฑฐ๋‚˜ ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • str.shouldBeInteger([radix]) : ๋ฌธ์ž์—ด์— ์ •์ˆ˜๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ๋ฐ˜ํ™˜
  • str.shouldContainOnlyOnce(substring) : ๋ฌธ์ž์—ด์— ๋ถ€๋ถ„ ๋ฌธ์ž์—ด์ด ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • str.shouldEndWith("suffix") : ๋ฌธ์ž์—ด์ด ์ง€์ •๋œ ์ ‘๋ฏธ์‚ฌ๋กœ ๋๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธ. ์ ‘๋ฏธ์‚ฌ๋Š” ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ๊ณ , ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค
  • str.shouldHaveLength(length) : ๋ฌธ์ž์—ด์ด ์ฃผ์–ด์ง„ ๊ธธ์ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธ str.shouldHaveLineCount(count) : ๋ฌธ์ž์—ด์— ์ฃผ์–ด์ง„ ์ˆ˜์˜ ํ–‰์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ. tr.split("\n").length.shouldBe(n)
  • str.shouldHaveMaxLength(max) : ๋ฌธ์ž์—ด์ด ์ฃผ์–ด์ง„ ์ตœ๋Œ€ ๊ธธ์ด๋ณด๋‹ค ๊ธธ์ง€ ์•Š์€์ง€ ํ™•์ธ
  • str.shouldHaveMinLength(min) : ๋ฌธ์ž์—ด์ด ์ฃผ์–ด์ง„ ์ตœ์†Œ ๊ธธ์ด๋ณด๋‹ค ์งง์ง€ ์•Š์€์ง€ ํ™•์ธ
  • str.shouldHaveSameLengthAs(length) : ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ ๋‹ค๋ฅธ ๋ฌธ์ž์—ด๊ณผ ๋™์ผํ•œ์ง€ ํ™•์ธ
  • str.shouldMatch(regex) : ๋ฌธ์ž์—ด์ด ์ฃผ์–ด์ง„ ์ •๊ทœ์‹๊ณผ ์™„์ „ํžˆ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ
  • str.shouldStartWith("prefix") : ๋ฌธ์ž์—ด์ด ์ฃผ์–ด์ง„ ์ ‘๋‘์‚ฌ๋กœ ์‹œ์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ. ์ ‘๋‘์‚ฌ๋Š” ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์„ ์ˆ˜ ์žˆ๊ณ , ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค
  • str.shouldBeEqualIgnoringCase(other) : ๋ฌธ์ž์—ด์ด ๋Œ€์†Œ๋ฌธ์ž๋ฅผ ๋ฌด์‹œํ•˜๊ณ  ๋‹ค๋ฅธ ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์€์ง€ ํ™•์ธ

Integer, Long

num.shouldBeBetween(x, y) : x์™€ y ์‚ฌ์ด์— ์žˆ๊ณ  x์™€ y๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š”์ง€ ํ™•์ธ num.shouldBeLessThan(n) : num์ด ์ฃผ์–ด์ง„ ๊ฐ’ n๋ณด๋‹ค ์ž‘๋‹ค๊ณ  ์ฃผ์žฅ num.shouldBeLessThanOrEqual(n): num์ด ์ฃผ์–ด์ง„ ๊ฐ’ n๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ™•์ธ num.shouldBeGreaterThan(n) : num์ด ์ฃผ์–ด์ง„ ๊ฐ’ n๋ณด๋‹ค ํฐ์ง€ ํ™•์ธ num.shouldBeGreaterThanOrEqual(n) : num์ด ์ฃผ์–ด์ง„ ๊ฐ’ n๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ™•์ธ num.shouldBeEven() : num์ด ์ง์ˆ˜์ž„์ธ์ง€ ํ™•์ธ num.shouldBeOdd() : num์ด ํ™€์ˆ˜์ž„์„ ํ™•์ธ num.shouldBeInRange(range) : num์ด ์ง€์ •๋œ ๋ฒ”์œ„์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ num.shouldBeZero() : num์ด 0์ž„์„ ํ™•์ธ

Collection

  • collection.shouldBeEmpty() : ์ปฌ๋ ‰์…˜์— element๊ฐ€ ์—†์Œ์„ ํ™•์ธ
  • collection.shouldBeUnique() : ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  element๊ฐ€ ์ค‘๋ณต์ด ์—†๋Š”์ง€ ํ™•์ธ
  • collection.shouldContain(element) : ์ปฌ๋ ‰์…˜์— ์ง€์ •๋œ element๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldContainAll(e1, e2, ..., en) : ์ปฌ๋ ‰์…˜์— ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๋‚˜์—ด๋œ ๋ชจ๋“  element๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldContainDuplicates() : ์ปฌ๋ ‰์…˜์— ํ•˜๋‚˜์ด์ƒ์˜ ์ค‘๋ณต element๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldContainExactly(e1, e2, ..., en) : ์ปฌ๋ ‰์…˜์ด ์ •ํ™•ํžˆ ์ฃผ์–ด์ง„ ๊ฐ’์„ ํฌํ•จํ•˜๊ณ  ๋‹ค๋ฅธ๊ฒƒ์€ ์ˆœ์„œ๋Œ€๋กœ ํฌํ•จํ•˜์ง€ ์•Š์Œ์„ ํ™•์ธ
  • collection.shouldContainExactlyInAnyOrder(e1, e2, ..., en) : ์ปฌ๋ ‰์…˜์ด ์ˆœ์„œ์— ์ƒ๊ด€์—†์ด ์ •ํ™•ํžˆ ์ฃผ์–ด์ง„ ๊ฐ’์„ ํฌํ•จํ•˜๊ณ  ๋‹ค๋ฅธ ๊ฒƒ์€ ํฌํ•จํ•˜์ง€ ์•Š์Œ์„ ํ™•์ธ
  • collection.shouldContainNull() : ์ปฌ๋ ‰์…˜์— ํ•˜๋‚˜ ์ด์ƒ์˜ null element๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldContainOnlyNulls() : ์ปฌ๋ ‰์…˜์ด null elements๋งŒ ํฌํ•จํ•˜๊ฑฐ๋‚˜ ๋น„์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldHaveSingleElement(element) : ์ปฌ๋ ‰์…˜์ด ํ•˜๋‚˜์˜ element๋งŒ ํฌํ•จํ•˜๋Š”์ง€ ํ™•์ธ
  • collection.shouldHaveSingleElement { block } : ์ปฌ๋ ‰์…˜์ด ์ฃผ์–ด์ง„ ์ˆ ์–ด์—์˜ํ•ด ํ•˜๋‚˜์˜ element๋ฅผ ํฌํ•จํ•˜๋Š”์ง€ ํ™•์ธ
  • collection.shouldHaveSize(length) : ์ปฌ๋ ‰์…˜์ด ์ •ํ™•ํžˆ ์ฃผ์–ด์ง„ ๊ธธ์ด์ธ์ง€ ํ™•์ธ
  • collection.shouldBeSingleton() : ์ปฌ๋ ‰์…˜์— element๊ฐ€ ํ•˜๋‚˜๋งŒ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldBeSingleton { block } : ์ปฌ๋ ‰์…˜์ด ๋‹จ ํ•˜๋‚˜์˜ element์ธ์ง€ ํ™•์ธํ•œ ํ›„ ์ด element๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ block์‹คํ–‰
  • collection.shouldHaveLowerBound(element) : ์ฃผ์–ด์ง„ element๊ฐ€ ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  element๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ™•์ธ. (Comparable์„ ๊ตฌํ˜„ํ•˜๋Š” element์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘๋™)
  • collection.shouldHaveUpperBound(element) : ์ฃผ์–ด์ง„ element๊ฐ€ ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  element๋ณด๋‹ค ํฌ๊ฑฐ๋‚˜ ๊ฐ™์€์ง€ ํ™•์ธ. (Comparable์„ ๊ตฌํ˜„ํ•˜๋Š” ์š”์†Œ์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘๋™)
  • collection.shouldBeSmallerThan(col) : ์ปฌ๋ ‰์…˜์ด ๋‹ค๋ฅธ ์ปฌ๋ ‰์…˜๋ณด๋‹ค ์ž‘์€์ง€ ํ™•์ธ
  • collection.shouldBeLargerThan(col) : ์ปฌ๋ ‰์…˜์ด ๋‹ค๋ฅธ ์ปฌ๋ ‰์…˜๋ณด๋‹ค ํฐ์ง€ ํ™•์ธ
  • collection.shouldBeSameSizeAs(col) : ์ปฌ๋ ‰์…˜์˜ ํฌ๊ธฐ๊ฐ€ ๋‹ค๋ฅธ ์ปฌ๋ ‰์…˜๊ณผ ๋™์ผํ•œ์ง€ ํ™•์ธ
  • collection.shouldHaveAtLeastSize(n) : ์ปฌ๋ ‰์…˜์˜ ํฌ๊ธฐ๊ฐ€ n ์ด์ƒ์ธ์ง€ ํ™•์ธ
  • collection.shouldHaveAtMostSize(n) : ์ปฌ๋ ‰์…˜์˜ ํฌ๊ธฐ๊ฐ€ ์ตœ๋Œ€ n์ธ์ง€ ํ™•์ธ
  • list.shouldBeSorted() : ๋ชฉ๋ก์ด ์ •๋ ฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
  • list.shouldContainInOrder(other) : ์ด ๋ชฉ๋ก์— ์ฃผ์–ด์ง„ ๋ชฉ๋ก์ด ์ˆœ์„œ๋Œ€๋กœ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • list.shouldExistInOrder({ element }, ...) : ์ด ๋ชฉ๋ก์— ์ˆ ์–ด์™€ ์ˆœ์„œ๋Œ€๋กœ ์ผ์น˜ํ•˜๋Š” element๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ. ๋‹ค๋ฅธ element๋Š” ์ˆ ์–ด์™€ ์ผ์น˜ํ•˜๋Š” element ์ฃผ๋ณ€์ด๋‚˜, element ์‚ฌ์ด์— ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Œ
  • list.shouldHaveElementAt(index, element) : ์ด ๋ชฉ๋ก์ด ์ฃผ์–ด์ง„ index์— ์ฃผ์–ด์ง„ element๋ฅผ ํฌํ•จํ•˜๋Š”์ง€ ํ™•์ธ
  • list.shouldStartWith(lst) : ์ด ๋ชฉ๋ก์ด ์ฃผ์–ด์ง„ ๋ชฉ๋ก์˜ element๋กœ ์ˆœ์„œ๋Œ€๋กœ ์‹œ์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ
  • list.shouldEndWith(lst) : ์ด ๋ชฉ๋ก์ด ์ฃผ์–ด์ง„ ๋ชฉ๋ก์˜ element๋กœ ์ˆœ์„œ๋Œ€๋กœ ๋๋‚˜๋Š” ๊ฒƒ์„ ํ™•์ธ
  • value.shouldBeOneOf(collection) :ํŠน์ • ์ธ์Šคํ„ด์Šค๊ฐ€ ์ปฌ๋ ‰์…˜์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ
  • collection.shouldContainAnyOf(collection) : ์ปฌ๋ ‰์…˜์— ์žˆ๋Š” element ์ค‘ ์ ์–ด๋„ ํ•˜๋‚˜๊ฐ€ ์žˆ์Œ์„ ํ™•์ธ
  • value.shouldBeIn(collection) : object๊ฐ€ ์ปฌ๋ ‰์…˜์— ํฌํ•จ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ. (์ฐธ์กฐ๊ฐ€ ์•„๋‹Œ ๊ฐ’์œผ๋กœ ํ™•์ธํ•จ)

Result

  • result.shouldBeSuccess() : Result๊ฐ€ Success์ธ์ง€ ํ™•์ธ
  • result.shouldBeSuccess(value) : Result๊ฐ€ Success์ด๊ณ  value์™€ ๋™์ผํ•œ์ง€ ํ™•์ธ
  • result.shouldBeSuccess(block) : Result๊ฐ€ Success์ด๋ฉด ๋ธ”๋Ÿญ์„ ์‹คํ–‰ํ•˜์—ฌ ํ™•์ธ
  • result.shouldBeFailure() : Result๊ฐ€ Failure์ธ์ง€ ํ™•์ธ
  • result.shouldBeFailureOfType<Type : Throwable>() : Result์˜ Failure์˜ ํƒ€์ž…์ด ๋™์ผํ•œ์ง€ ํ™•์ธ
  • result.shouldBeFailure(block) : Result๊ฐ€ Failure์ด๋ฉด ๋ธ”๋Ÿญ์„ ์‹คํ–‰ํ•˜์—ฌ ํ™•์ธ

Coroutine Channel

  • channel.shouldReceiveWithin(duration) : ์ฑ„๋„์ด ๊ธฐ๊ฐ„๋‚ด์— ์ˆ˜์‹ ์ˆ˜์‹ ํ•˜๋Š”์ง€ ํ™•์ธ
  • channel.shouldReceiveNoElementsWithin(duration) : ์ฑ„๋„์ด ๊ธฐ๊ฐ„ ๋‚ด์— ์–ด๋–ค ์š”์†Œ๋„ ์ˆ˜์‹ ํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธ
  • channel.shouldHaveSize(n) : ๋‹ซ๊ธฐ ์ „์— ์ฑ„๋„์ด ์ •ํ™•ํžˆ n๊ฐœ์˜ ์š”์†Œ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š”์ง€ ํ™•์ธ
  • channel.shouldReceiveAtLeast(n) : ์ฑ„๋„์ด >= n๊ฐœ์˜ ์š”์†Œ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š”์ง€ ํ™•์ธ
  • channel.shouldReceiveAtMost(n) : ์ฑ„๋„์ด ๋‹ซ๊ธฐ ์ „์— <=n ์š”์†Œ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š”์ง€ ํ™•์ธ
  • channel.shouldBeClosed() : ์ฑ„๋„์ด ๋‹ซํ˜€ ์žˆ๋Š”์ง€ ํ™•์ธ
  • channel.shouldBeOpen() : ์ฑ„๋„์ด ์—ด๋ ค ์žˆ๋Š”์ง€ ํ™•์ธ
  • channel.shouldBeEmpty() : ์ฑ„๋„์ด ๋น„์–ด ์žˆ์Œ์„ ํ™•์ธ

Soft Assertions

๋•Œ๋•Œ๋กœ ํ…Œ์ŠคํŠธ์—์„œ ์—ฌ๋Ÿฌ ์–ด์„ค์…˜์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์‹คํŒจํ•œ ๋ชจ๋“  ์–ด์„ค์…˜์„ ๋ณด๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ๋‹ค. Kotest๋Š” ์ด๋ฅผ ์œ„ํ•œ assertSoftly๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

assertSoftly {
  foo shouldBe bar
  foo should contain(baz)
}

๋ธ”๋ก ๋‚ด์˜ ์–ด์„ค์…˜์ด ์‹คํŒจํ•˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ๊ณ„์† ์‹คํ–‰๋˜๋ฉฐ. ๋ชจ๋“  ์‹คํŒจ๋Š” ๋ธ”๋ก ๋์—์„œ ๋ณด๊ณ ๋œ๋‹ค.