KotestをFreeSpecで書いていて「No tests found for given includes: [XXXXX](–tests filter)」という謎のエラーが発生し原因が分からず悩んだ事があったのでメモ。
原因はFreeSpecの書き方でした。
環境
- IntelliJ IDEA 2022.1.3 (Community Edition)
- Kotest(intellij IDEA Plugin) 1.2.60-IC-2022.1
- kotlin 1.6.21
- kotest 4.6.0
IntelliJ IDEAの設定
[IntelliJ] JUnit4 + Gradle – update broke all tests with error: no tests found for given includes
https://linked2ev.github.io/devsub/2019/09/30/Intellij-junit4-gradle-issue/
こんな記事を見てIntellij IDEAの設定をまず見直しました。
FreeSpecの書き方が原因
FreeSpecはネストの階層をユーザ好みで書けることがメリットです。
OKバージョン
class MyTests : FreeSpec({ "文字列のテスト" - { "ねこのlengthは2であること" { "ねこ".length shouldBe 2 } } })
NGバージョン
こちらがNGバージョンになります。これで実行すると「No tests found for given includes ~」 となりました。
class MyTests : FreeSpec({ "文字列のテスト" - { "ねこのlengthは2であること" - { // 一番内側のブロックに最後に - を付けるとエラーになる "ねこ".length shouldBe 2 } } })
これは公式ドキュメントにも書いてありますが、FreeSpecのルールだそうです。
一番内側のブロックには – を使わない とのこと。
The innermost test must not use the
-
(minus) keyword after the test name.
https://kotest.io/docs/framework/testing-styles.html#free-spec
大量にテストケースが並んでると見落としやすい
FreeSpecの一番のメリットはユーザが好きにテストコードの構造をいくらでもネスト出来ることです。
ただ、その使いやすさと裏腹に一瞬見落としやすい作りになっています。
class MyTests : FreeSpec({ "文字列のテスト" - { "ねこのlengthは2であること" { "ねこ".length shouldBe 2 } } "文字列のテスト2" - { "ねこ2に関して" - { "ねこのlengthは3であること" - { // ここだけ記述ミス。だが気付きにくい。 "ねこ3".length shouldBe 3 } } } "文字列のテスト3" - { "ねこ3のlengthは3であること" { "ねこ3".length shouldBe 3 } } })
番外編
他にもうっかりミスしてしまうFreeSpecの書き方。
一瞬戸惑うOKパターン
ちなみにこれだと何故かテスト自体は検知されます。
どうやらハイフンなしのブロック内のブロックは無視される模様。
"文字列のテスト2" - { "ねこ2に関して" { "ねこ2のlengthは3であること" - { "ねこ3".length shouldBe 3 } } }
試しにテストケースを失敗させるとこういう結果になります。テストケース名は結果に表示されません。
コンパイル出来ないNGパターン
これはエラーが出ます。ハイフン付きのブロック内にハイフン付きのブロックです。
「Using ‘invoke(suspend TestContext.() -> Unit): Unit’ is an error. Cannot nest lead test inside another leaf test ‘」
"文字列のテスト2" - { "ねこ2に関して" { "ねこのlengthは3であること" { "ねこ3".length shouldBe 3 } } }
FreeSpec ではなく、DescribeSpec とかを使っていきたい
ということでネストの自由さがウリのFreeSpecだが、実際に書くときは構造を瞬時に理解できる別のSpecと使いたい。
例えばDescribeSpec とかだとこんな風に書ける。不要なミスがなくなる。
class MyTests : DescribeSpec({ describe("ねこのテスト") { it("ねこのlengthは3であること") { "ねこ3".length shouldBe 3 } describe("ねずみのlength") { it("ねずみのlengthは3であること") { "ねこ3".length shouldBe 3 } it("ねずみ2のlengthは4であること") { "ねこ3".length shouldBe 3 } } } })
おしまい
コメント