Kotest プロパティベーステスト(Property-based Testing)
プロパティベーステスト
Kotest は、独立して使用できる複数のサブプロジェクトに分かれている。そのうちの 1 つがプロパティテストフレームワーク(Property-based Testing)である。当然だが、プロパティテストサポートの利点を得るために Kotest をテストフレームワークとして使用する必要はない。
プロパティテストとは何か
開発者は一般的に例ベースのテストを書く。これは、よく知られているさまざまな単体テストである。いくつかの入力値と期待結果を与えると、Kotest や JUnit のようなテストフレームワークが、実際の結果が期待に合っているかを確認する。
このアプローチの問題の 1 つは、開発者が思いつかなかったエッジケースや、選んだ入力のカバレッジ不足によって、エラーを見逃しやすいことである。代わりにプロパティテストを使うと、同じテストに数百または数千の値が入力され、その値は通常プロパティテストフレームワークによってランダムに生成される。
たとえば、優れたプロパティテストフレームワークには、負の無限大、空のリスト、非 ASCII 文字を含む文字列などの値が含まれる。これらは例ベースのテストを書くときに忘れがちなものである。
プロパティテストはもともと QuickCheck のようなフレームワークで、あるオブジェクトのプロパティ、つまりすべての入力に対して真でなければならないプロパティをテストする概念として考案された。言い換えると不変条件である。不変条件の例として、2 つの文字列 a と b がある場合、length(a + b) は常に length(a) + length(b) と同じでなければならない。
ここから property testing という用語が生まれた。
ただし、モナド則や基本的な数値関数のようなものだけをテストするためにプロパティテストを使う必要はない。さまざまな入力値を活用できるテストは、すべて良い候補である。たとえば、ユーザー名を検証する関数があり、有効なメールアドレスが受け入れられることをテストしたい場合、プロパティテストは検証ロジックを強化する数千の組み合わせを生成するのに役立つ。
はじめに
プロパティテストフレームワークはすべてのターゲットでサポートされる。
JVM/Gradle
ビルドに次の依存関係を追加する。
dependencies {
testImplementation("io.kotest:kotest-property:$version")
}
JVM/Maven
ビルドに次の依存関係を追加する。
<dependency>
<groupId>io.kotest</groupId>
<artifactId>kotest-property-jvm</artifactId>
<version>${version}</version>
<scope>test</scope>
</dependency>
Multiplatform
commonTest ソースセットに次の依存関係を追加する。
kotlin {
sourceSets {
val commonTest by getting {
dependencies {
implementation("io.kotest:kotest-property:$version")
}
}
}
}
または、特定のターゲットに依存関係を追加することもできる。たとえば JavaScript ターゲットに対して、jsTest ソースセットだけで使用する依存関係を追加できる。
kotlin {
targets {
js {
browser()
nodejs()
}
}
sourceSets {
val jsTest by getting {
dependencies {
implementation("io.kotest:kotest-property:$version")
}
}
}
}
次のステップ
テストの入力値を生成するために、Kotest はジェネレーター(generator)という用語を使用する。入力引数ごとに 1 つのジェネレーターがテスト関数に渡され、テストは設定された反復回数だけ実行される。
詳しく見る内容:
- テスト関数の使い方。
- さまざまな種類のジェネレーターとその操作。
- カスタムジェネレーターの書き方。
- シードを含むテスト設定の指定方法。