本質的にランダム/非決定的アルゴリズムの単体テスト
私の現在のプロジェクトは、簡潔に「制約のあるランダムなイベント」の作成に関係しています。私は基本的に検査のスケジュールを生成しています。それらのいくつかは、厳密なスケジュールの制約に基づいています。金曜日の午前10:00に週に1回検査を行います。他の検査は「ランダム」です。「検査は週に3回行う必要がある」、「検査は午前9時から午後9時までの間に行う必要がある」、「同じ8時間内に2つの検査を行うべきではない」などの基本的な構成可能な要件がありますが、特定の検査セットに対して設定された制約の範囲内で、結果の日付と時刻は予測できません。 ユニットテストとTDD、IMOは、このシステムで大きな価値があります。これは、要件の完全なセットがまだ不完全でありながら、段階的にビルドするために使用できるためです。現在、私が必要だとは知らない。厳密なスケジュールは、TDDにとって欠かせないものでした。ただし、システムのランダムな部分のテストを作成するときに、テスト対象を実際に定義するのは難しいと感じています。スケジューラによって生成されるすべての時間は制約内に収まる必要があると断言できますが、実際の時間を非常に「ランダム」にせずにこのようなすべてのテストに合格するアルゴリズムを実装できます。実際、それはまさに起こったことです。時刻は、正確には予測できませんが、許容される日付/時刻範囲の小さなサブセットに分類される問題を発見しました。アルゴリズムは、私が合理的に行うことができると思うすべてのアサーションに合格し、そのような状況で失敗する自動テストを設計することはできませんでしたが、「よりランダムな」結果が与えられると合格します。既存のテストを再構築して何度も繰り返すことで問題が解決したことを実証し、生成された時間が完全に許容範囲内に収まったことを視覚的に確認する必要がありました。 非決定論的な動作を期待するテストを設計するためのヒントはありますか? すべての提案に感謝します。主な意見は、決定論的で、再現性があり、主張可能な結果を得るために、決定論的テストが必要だということです。理にかなっています。 制約プロセス(任意の長いバイト配列が最小と最大の間で長くなるプロセス)の候補アルゴリズムを含む一連の「サンドボックス」テストを作成しました。次に、そのコードをFORループで実行し、アルゴリズムにいくつかの既知のバイト配列(開始時に1から10,000,000の値)を与え、アルゴリズムにそれぞれ1009から7919の間の値に制約させます(素数を使用して、アルゴリズムは、入力範囲と出力範囲の間で偶然のGCFを通過しません)。結果の制約値がカウントされ、ヒストグラムが作成されます。「パス」するには、すべての入力をヒストグラム内に反映する必要があり(「失わない」ようにするための健全性)、ヒストグラム内の2つのバケットの差は2より大きくすることはできません(実際には<= 1でなければなりません) 、しばらくお待ちください)。勝ったアルゴリズムがあれば、それをカットして実動コードに直接貼り付け、永続的なテストを実施して回帰することができます。 コードは次のとおりです。 private void TestConstraintAlgorithm(int min, int max, Func<byte[], long, long, long> constraintAlgorithm) { var histogram = new int[max-min+1]; for (int i = 1; i <= 10000000; i++) { //This is the stand-in for the PRNG; produces a known byte array var buffer = …