プロパティベーステスト
関数の持つ一般的な性質(プロパティ)を定義し、ランダムに生成した多数の入力に対してチェックするテスト手法 開発者が、プログラムへの入力値と期待される出力値(Example)ペアを定義する
問題点
テストケースを作成するのは開発者なので、無意識にテストがパスするものになりやすい
また、テストに対する責任を開発者が負うと、テストの管理や修正に注力することになる
https://scrapbox.io/files/67d37509d885178b8fe2e1a6.png
https://scrapbox.io/files/67d3751c7381b419d5131306.png
PBT による解決
開発者が、いかなる入力値を与えても常に成り立つべき(不変条件 を満たす)ルール(プロパティ)を定義 する EBT ではこの不変条件を 間接的に 示そうとするが限界がある
warning.icon EBT と PBT は相反するものではない
補完し合う関係性
EBT: Known known → Known known
「コードが自分たちの想定した通りに実行されるかチェックする」ための助けになる
PBT: Known unknown → Known known
「プログラムがどのように振る舞うかを探索し、何ができて何ができないのか、自分たちの想定が正しいかをチェックする」ための助けになる
そのため、PBT が失敗した場合はテストが失敗する理由が明確ではないので、「本当にバグなのか?」または「そもそもそのプロパティが正しいのか?」を判断することをよく求められる
これにより「本当に満たすべき仕様は何か?」を考え直す機会が増える
https://scrapbox.io/files/67d375bcc6907206b68028a1.png
このフレームワークの多くでは、以下のような機能を持つ
収縮(Shrinking): テストが失敗する入力値の中で、最小限(最も単純な形)のものを探し出す機能 通常 ゼロ値(数値だと 0(0.0)、リストだと空リスト)に向かって収縮するが、カスタマイズすることも可能 e.g. Proper: ?SHRINK / ?LETSHIRINK
ジェネレータ(Generator): テストの入力データをランダムに生成する機能 自身で独自のジェネレータを作成することも可能
通常のプロパティは各テストケースのデータ生成処理は独立している
一方、標的型プロパティは後続のデータ生成処理に対して影響を与えることができる
これにより、ジェネレータをチューニングすることなく、単純なジェネレータで狙ったデータを生成することが可能になる
具体的なフレームワーク
FP 以外
プロパティには大きく 2 つの種類がある
ステートレスプロパティ(状態を持たない)
ステートフルプロパティ(状態を持つ)
プロパティを見つける方法
参考