Kotest 統計(Statistics)
統計(Statistics)
ジェネレーターが望んだ方法で構成されているかを確認するために、Kotest で生成される値の種類を知りたい場合がある。プロパティテスト統計は、このような要求を満たすために設計されている。
collect 関数は統計の開始点であり、値のカテゴリを数えるために使用される。この関数は、プロパティテスト内で増やしたいカテゴリを指定して呼び出す。
たとえば、BigDecimal が使用する RoundingMode 値の統計を収集したいとする。通常どおり checkAll を呼び出し、丸めモードを collect 関数に渡す。
checkAll(Arb.enum<RoundingMode>(), Arb.bigDecimal()) { mode, decimal ->
collect(mode)
// test here
}
テストが完了すると、Kotest はテスト名と各カテゴリの件数/割合を出力する。
Statistics: [collecting stats] (1000 iterations, 1 args)
HALF_DOWN 142 (14%)
HALF_UP 141 (14%)
CEILING 132 (13%)
FLOOR 122 (12%)
UP 119 (12%)
UNNECESSARY 119 (12%)
HALF_EVEN 118 (12%)
DOWN 107 (11%)
使用するカテゴリは enum である必要はない。任意のオブジェクトにでき、より細かく制御したい場合は条件付きでラップできる。
checkAll(Arb.int()) { k ->
when {
k % 2 == 0 -> collect("EVEN")
else -> collect("ODD")
}
// test here
}
ラベル(Labels)
直交する統計セットが必要になることがある。たとえば簡単な数値テストでは、特定の割合が偶数であり、特定の割合が負数であることを確認したい場合がある。1 つの方法は EVEN_POS、EVEN_NEG、ODD_POS、ODD_NEG を使うことである。
checkAll(Arb.int()) { k ->
when {
k > 0 && k % 2 == 0 -> collect("EVEN_POS")
k % 2 == 0 -> collect("EVEN_NEG")
k > 0 -> collect("ODD_POS")
else -> collect("ODD_NEG")
}
// test here
}
これにより、1 つの出力セットが得られる。
EVEN_POS 142 (27%)
EVEN_NEG 141 (23%)
ODD_POS 132 (24%)
ODD_NEG 122 (26%)
しかし、組み合わせが増えると扱いにくくなるため、Kotest はラベル付き統計をサポートする。これは別々の統計セットと考えられる。ラベルを使用するには、collect メソッドの最初の引数にラベル名を渡すだけでよい。
checkAll(Arb.int()) { k ->
when {
k % 2 == 0 -> collect("even_odd", "EVEN")
else -> collect("even_odd", "ODD")
}
when {
k > 0 -> collect("pos_neg", "POS")
else -> collect("pos_neg", "NEG")
}
// test here
}
これで Kotest は、タイトルにラベル名を含む複数の統計セットを出力する。
Statistics: [collecting labelled stats] (1000 iterations, 1 args) [even_odd]
ODD 520 (52%)
EVEN 480 (48%)
Statistics: [collecting labelled stats] (1000 iterations, 1 args) [pos_neg]
NEG 527 (53%)
POS 473 (47%)
レポートモード
デフォルトでは、すべてのプロパティテストの統計が出力される。グローバル構成オブジェクト PropertyTesting で構成できる 4 つのモードがある。
可能なオプションは次のとおりである。
| Mode | Function |
|---|---|
PropertyTesting.statisticsReportMode = StatisticsReportMode.OFF |
すべての統計レポートを無効にする。 |
PropertyTesting.statisticsReportMode = StatisticsReportMode.ALL |
すべての統計レポートを有効にする。 |
PropertyTesting.statisticsReportMode = StatisticsReportMode.SUCCESS |
成功したテストでのみ統計を出力する。 |
PropertyTesting.statisticsReportMode = StatisticsReportMode.FAILED |
失敗したテストでのみ統計を出力する。 |
統計のカバレッジ確認
特定の値が生成されていることをプログラムで主張するには、満たす必要がある制約を指定できる。
たとえば、前の丸めの例で withCoveragePercentages を使用し、少なくとも 10% の入力が HALF_DOWN をカバーし、10% が FLOOR をカバーすることを確認できる。
withCoveragePercentages(mapOf(RoundingMode.HALF_DOWN to 10.0, RoundingMode.FLOOR to 10.0)) {
checkAll(Arb.enum<RoundingMode>(), Arb.bigDecimal()) { mode, decimal ->
collect(mode)
// use the mode / decimal
}
}
割合ではなく絶対数で確認するには、withCoverageCounts を使用する。
withCoverageCounts(mapOf(RoundingMode.HALF_DOWN to 75, RoundingMode.FLOOR to 75)) {
checkAll(Arb.enum<RoundingMode>(), Arb.bigDecimal()) { mode, decimal ->
collect(mode)
// use the mode / decimal
}
}
カスタムレポート
統計レポーターの独自インスタンスを使用して、レポート形式をカスタマイズしたり、生データからレポートを生成したりできる。これはグローバル構成オブジェクト PropertyTesting を通じて構成される。
例:
object MyStatisticsReporter : object : StatisticsReporter { ... }
PropertyTesting.statisticsReporter = MyStatisticsReporter