- 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 |
FunSpec
ํ
์คํธ๋ test๋ฅผ ์ค๋ช
ํ๊ธฐ์ํด ๋ฌธ์์ด์ธ์๋ก ํธ์ถ๋ ํจ์๋ฅผ ํธ์ถํ๋ค์
ํ
์คํธ ์์ฒด๋ฅผ ๋๋ค๋ก ํธ์ถํ์ฌ ํ
์คํธ๋ฅผ ์์ฑํ ์ ์๋ค.
class MyTests : FunSpec({
test("String length should return the length of the string") {
"sammy".length shouldBe 5
"".length shouldBe 0
}
})
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
}
})
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
}
}
})
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
}
}
})
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
}
}
}
})
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"
}
}
}
})
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
}
}
}
}
})
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
}
}
})
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
}
}
})
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
๋งค๊ฐ๋ณ์์ 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
}
์ต์์ ๋ ๋ฒจ ํ
์คํธ ์ด๋ฆ ์์์ผ๋ก f:
๋ฅผ ๋ถ์ฌ์ฃผ๋ฉด ํด๋น ํ
์คํธ ๋ฐ ํด๋น๋ฒ์๋ด์ ์ ์๋ ๋ชจ๋ ํ์ ํ
์คํธ๋ค๋ง ์คํ๋๊ณ
๋๋จธ์ง๋ ํ
์คํธ๋ค์ ๊ฑด๋๋จ๋ค.
class FocusExample : StringSpec({
"test 1" {
// this will be skipped
}
"f:test 2" {
// this will be executed
}
"test 3" {
// this will be skipped
}
})
์ค์ฒฉ ํ ์คํธ๋ ์์ ํ ์คํธ๊ฐ ์คํ๋ ํ์๋ง ๊ฒ์๋๊ธฐ ๋๋ฌธ์ ํฌ์ปค์ค๋ชจ๋๋ ์ค์ฒฉ ํ ์คํธ์ ๋ํด์๋ ์๋ ํ์ง ์์.
Focus์ ๋ฐ๋๊ธฐ๋ฅ์ผ๋ก ํ
์คํธ์ด๋ฆ์ ์ ๋์ด !
๋ฅผ ๋ถํ ํ
์คํธ๋ง ๊ฑด๋๋ด๋ค.
class BangExample : StringSpec({
"!test 1" {
// this will be ignored
}
"test 2" {
// this will run
}
"test 3" {
// this will run too
}
})
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
์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ ์ ์๋ค.
Spec์ ๊ฑด๋๋ฐ๊ณ ์ธ์คํด์คํํ์ง๋ ์๋๋ค.
@Ignored
class IgnoredSpec : FunSpec() {
init {
error("boom") // spec will not be created so this error will not happen
}
}
@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์ ํตํด 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)๋ฅผ ์ฌ์ฉํ๋ฉด ํ
์คํธ ์์ง์ด ํ
์คํธ ์ผ์ด์ค์ ๋ํ ์ฌ์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ ์ดํ ์ ์๋ค.
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
์ผ๋ก Specํด๋์ค์ ํ๋์ ์ธ์คํด์ค๊ฐ ์์ฑ๋ ๋ค์
๋ชจ๋ ํ
์คํธ๊ฐ ์๋ฃ๋ ๋๊น์ง ๊ฐ ํ
์คํธ ์ผ์ด์ค๊ฐ ์ฐจ๋ก๋ก ์คํ๋๋ ๋ฐฉ์์ด๋ค.
// ๋ชจ๋ ํ
์คํธ์ ๋์ผํ ์ธ์คํด์ค๊ฐ ์ฌ์ฉ๋๋ฏ๋ก ๋์ผํ ID๊ฐ ์ธ ๋ฒ ์ธ์๋๋ค.
class SingleInstanceExample : WordSpec({
val id = UUID.randomUUID()
"a" should {
println(id)
"b" {
println(id)
}
"c" {
println(id)
}
}
})
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
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
์์คํ ์์ฑ์ ํตํด ์ ์ญ์ ์ผ๋ก ๊ฒฉ๋ฆฌ๋ชจ๋๋ฅผ ์ค์ ํ ์๋ ์๋ค.
class ProjectConfig: AbstractProjectConfig() {
override val isolationMode = IsolationMode.InstancePerLeaf
}
Kotest๋ ํ์ฌ ์ฌ๋ฌ๋ชจ๋์ ๊ฑธ์ณ ์ฝ 325๊ฐ์ matcher๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
Kotest matcher๋ฅผ๋ ํ๋ ์์ํฌ์ ๊ตฌ์ ๋ฐ์ง์๊ณ Kotest ํ๋ ์์ํฌ ๋๋ ๋ค๋ฅธ ํ๋ ์์ํฌ์ ํจ๊ป ์ฌ์ฉํ ์ ์๋ค.
matcher๋ ๋ ๊ฐ์ง ์คํ์ผ์ ์ ๊ณตํ๋ค.
ํ์ฅํจ์ ์คํ์ผ
a.shouldStartWith("foo")
์ค์ํจ์ ์คํ์ผ
a should startWith("foo")
kotest-assertions-core
๋ชจ๋์์ ์ ๊ณตํ๋ Matcher
obj.shouldBe(other)
: ์ฃผ์ด์ง obj์ other๊ฐ ๋ชจ๋ ๊ฐ๋ค๋ ๋ฒ์ฉ assertionexpr.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.shouldBeEmpty()
: iterator์ ๋ค์๊ฐ์ด ์๋์ง ๊ฒ์ฆiterator.shouldHaveNext()
: iterator์ ๋ค์๊ฐ์ด ์๋์ง ๊ฒ์ฆ
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์ด ๋น์ด์๋์ง ํ์ธ
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)
: ๋ฌธ์์ด์ด ๋์๋ฌธ์๋ฅผ ๋ฌด์ํ๊ณ ๋ค๋ฅธ ๋ฌธ์์ด๊ณผ ๊ฐ์์ง ํ์ธ
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.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.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์ด๋ฉด ๋ธ๋ญ์ ์คํํ์ฌ ํ์ธ
channel.shouldReceiveWithin(duration)
: ์ฑ๋์ด ๊ธฐ๊ฐ๋ด์ ์์ ์์ ํ๋์ง ํ์ธchannel.shouldReceiveNoElementsWithin(duration)
: ์ฑ๋์ด ๊ธฐ๊ฐ ๋ด์ ์ด๋ค ์์๋ ์์ ํ์ง ์๋์ง ํ์ธchannel.shouldHaveSize(n)
: ๋ซ๊ธฐ ์ ์ ์ฑ๋์ด ์ ํํ n๊ฐ์ ์์๋ฅผ ์์ ํ๋์ง ํ์ธchannel.shouldReceiveAtLeast(n)
: ์ฑ๋์ด >= n๊ฐ์ ์์๋ฅผ ์์ ํ๋์ง ํ์ธchannel.shouldReceiveAtMost(n)
: ์ฑ๋์ด ๋ซ๊ธฐ ์ ์ <=n ์์๋ฅผ ์์ ํ๋์ง ํ์ธchannel.shouldBeClosed()
: ์ฑ๋์ด ๋ซํ ์๋์ง ํ์ธchannel.shouldBeOpen()
: ์ฑ๋์ด ์ด๋ ค ์๋์ง ํ์ธchannel.shouldBeEmpty() :
์ฑ๋์ด ๋น์ด ์์์ ํ์ธ
๋๋๋ก ํ ์คํธ์์ ์ฌ๋ฌ ์ด์ค์ ์ ์ํํ๊ณ ์คํจํ ๋ชจ๋ ์ด์ค์ ์ ๋ณด๊ณ ์ถ์ ์ ์๋ค. Kotest๋ ์ด๋ฅผ ์ํ assertSoftly๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
assertSoftly {
foo shouldBe bar
foo should contain(baz)
}
๋ธ๋ก ๋ด์ ์ด์ค์ ์ด ์คํจํ๋ฉด ํ ์คํธ๊ฐ ๊ณ์ ์คํ๋๋ฉฐ. ๋ชจ๋ ์คํจ๋ ๋ธ๋ก ๋์์ ๋ณด๊ณ ๋๋ค.