Booklog - 実践プロパティベーステスト PropEr と Erlang/Elixir ではじめよう

前から FsCheck を使いたいと考えてたが手探りすぎたのでなんか手引が欲しく、ちょうど良さそうな本が出たので積読してた。 少なくとも和書だと PBT について書いてるのがこの本しかないっぽいし。 はじめ PBT 基礎を習って、その後は演習等実践を通して理解を進めていくみたい。良さそうや。

2024-11-05, read count: 1, page: i ~ xii, 目次, 索引

第 1 章 プロパティベーステストの基礎。 プロパティベーステストは従来のテストと根本的にアプローチが異なる。 従来のテストは事例を並べるが、プロパティベーステストは「どのような入力を与えても常に同じであるような振る舞い」≒プロパティを定義する。 プロパティベーステストが適さないケースもあり、従来のテストより考えることが多くなり技能も必要だが、素晴らしい結果をもたらしてくれるって感じか。 事例ベースのテストは想像の範囲の仕様を記述するが、プロパティベーステストは想像の失敗をあぶり出す。そうそう、それこそ求めてるものよ。

2024-11-06, read count: 1, page: 1 ~ 11

第 1 章 プロパティベーステストの基礎。 従来のテストは単純なツールと多くのコード。 PBT は強力なツールと少しのコード化されたルール。 そのためツールの支援がなければ話にならんということで本で使うツールの紹介。 .NET もテストプロジェクトを分離するし FsCheck も同じ感じでやれそうやな。

2024-11-07, read count: 1, page: 11 ~ 18

第 2 章 プロパティを書く。 コード化されたルール、ジェネレータ、フレームワークが揃ってプロパティが得られる。 PBT には基礎的なステートレスプロパティとより複雑なステートフルプロパティがある。 あとは PropEr の使い方とか。後ほど FsCheck ではというあたりも自習しておく。

2024-11-08, read count: 1, page: 19 ~ 25

第 2 章 プロパティを書く。 備え付けジェネレータとコード化したルールを組み合わせてどテストを書くかってところ。 最初はサクッと書いてその結果からジェネレータを変える等プロパティを調整してく。 結構試行錯誤な印象。あとこの段階では組み込みのジェネレータ知らんことにはどうにもならなそう。 使うツールに習熟する必要あるって話の片鱗かな。

2024-11-09, read count: 1, page: 25 ~ 36

第 3 章 プロパティで考える。 優れたプロパティの実装は標準的なテストよりも難しいが、習熟するためのテクニックはある。 まずモデル化。単純で正しいと信用できる代替の実装。実行速度に問題があったとしても初手としては意味がある。 複数の実装パターンがない場合には従来のテストケースの汎化をする。どこまでを信頼するかは開発者の判断。 次に小さく分解した部分で常に真となるはずの不変条件を使う。単一の不変条件だと役に立たなくても他の部分の不変条件と組み合わせで信用を高められる。 テクニックがあるとはいえこの辺は実装しつつ習熟するしかないやろな。

2024-11-10, read count: 1, page: 36 ~ 46

第 3 章 プロパティで考える。 正順の処理に対して逆順の処理を書ける場合はそれが対称プロパティとなる。 対称プロパティそれだけでは整合性を保証するのみだが、不変条件を組み合わせることで強固なプロパティが得られる。 コツとして、複雑な処理をプロパティ 1 つだけで信頼性を高めようとせず、複数のプロパティに分けて段階的に検証していくのが望ましい。 この辺は従来のテストと同じかな。

2024-11-11, read count: 1, page: 46 ~ 53

第 4 章 カスタムジェネレーター。 まんべんなくランダムなデータでは発見できると限らない。 限られたエッジケースに焦点を絞るようなテストに最適なデータを、カスタムジェネレータで生成する。 まず統計情報をとりデフォルトジェネレータで生成された値がテストに十分か見極め、不十分ならカスタムジェネレータを利用する。 カスタムのデータ生成はそら欲しくなるよなという印象。

2024-11-12, read count: 1, page: 54 ~ 64

第 4 章 カスタムジェネレーター。 リサイズジェネレーター。生成される値の範囲を狭める。ただし狭めた分ばらつきが得られなくなる点に注意する。 変換ジェネレーター。データの生成と変換がジェネレーターとプロパティに分かれてしまうようなケースをジェネレーターにまとめられる。 またフィルタとして働く制約条件を設けるジェネレータもある。ただし除外されるデータの量が大量だと変換で賄う方が速いケースもあるので注意する。 生成・変換のいずれにしても効率的に欲しいデータを生成するには十分でなく、その場合確率を調整して狙いのデータに近づけることもできる。 ただし CSV や XML のような構造化データの生成には十分でないため更にテクニックがいる。 ここまできたら実際にテスト対象に必要なデータを試行錯誤するのが実践的で良さそうやな。勘所は練習しないとつかめなさげ。

2024-11-13, read count: 1, page: 65 ~ 76

第 4 章 カスタムジェネレーター。 再帰ジェネレーター。 繰り返しで作れるデータは概ね可能。 ただし正格評価で呼び出し階層が深くなりすぎる場合があり、そのときは遅延評価することで回避する。 確率的に再帰の終了条件を設定する場合、確率が固定されたり異常なサイズのデータが生成されることもある。 その場合繰り返し回数だけランダムに生成して、データの生成を通常の関数で記述することで軽くできる。 Erlang 力低くてピンとこんが正確評価は FsCheck も同じだし、他のエッセンスも似たようなもんだろうと推測する。

2024-11-14, read count: 1, page: 76 ~ 84

第 4 章 カスタムジェネレーター。 シンボリックコール。失敗したプロパティの出力が解読不能なバイト列などのデータ形式の場合に使える。 関数呼び出しやその引数をシンボルとして記録し、失敗時にその履歴が追跡できる感じ。 FsCheck にはシンボリックコールそのものはないみたい。それっぽいものを代替手段で実装することはできそうなので参考にはなるか。

2024-11-15, read count: 1, page: 84 ~ 92

第 5 章 信頼できるテスト。 これまで学んだ内容を実践する。 モデル化、事例テストの汎用化、不変条件、対象プロパティと事例テストによる固定化(anchor 錨)。 ここでは CSV のプロパティを書くためにまずジェネレータからかいてるが、仕様のコード化という点で TDD に通じる。 プロパティを定義するとその仕様の曖昧さが生み出すというのもいいな。 避けられない既知のバグを正解ケースとして、またプロパティの実装上避けられない暗黙の仕様のテストも事例テストが向いてる。 こういう事例テストの用途はリグレッションテストも該当する。

2024-11-16, read count: 1, page: 93 ~ 111

第 5 章 信頼できるテスト。 PBT のアイデアを使った事例テスト。 総当たりの範囲が狭く実行時間も許容できる場合は PBT より事例を列挙するほうが良いケースもある。 この場合原因の追跡のしやすさは劣るが、実例が網羅されるためランダム性は必要なくより信頼性も高くなる。

2024-11-17, read count: 1, page: 111 ~ 121

第 5 章 信頼できるテスト。 ココまでで出尽くしてるかのようで特に気づく点なかった。 FsCheck で同じような実習してみるのが練習になりそうやけどまだやってない。

2024-11-18, read count: 1, page: 121 ~ 136

第 6 章 プロパティ駆動開発。 TDD と同じように PDD する。 ポジティブテスト(テストがスべきことの検証)とネガティブテスト(プログラムが処理できないことのテスト)の技法を探っていく。 最初に簡単なプロパティを書き、それを green にするために最小実装、実装後統計を見て妥当性のチェック。 プロパティ書いてジェネレータを書いて実装してって流れは F# だとコンパイルエラーうざそうで先に空実装しちゃいそう。 TDD もなんか苦手やし。

2024-11-19, read count: 1, page: 137 ~ 144

第 6 章 プロパティ駆動開発。 1つ目のプロパティでカバーできなかったケースのテストを新たに作る。複雑化しないように小分けにする。 これはジェネレーターも同じで、テストしたいパターンを構成する最小の要素のジェネレーターを作る。 それらを組み合わせて複雑なパターンを網羅する。 ここまでは想像の範囲で期待の挙動をするかテストするポジティブテスト(ハッピーテスト)。次節からネガティブテスト。 単純で本実装とは違う形で実装ってのが結構むずそうよなーやり方は色々あるってのはわかるんやけどバイアスかかりそう。

2024-11-20, read count: 1, page: 144 ~ 151