Haskell には、コード片の型シグネチャによって、そのコードが何をするかがわかるという優れた特性があります。そして、私は考えました...型シグネチャに基づいてテストを構築できますか?
たとえば、 などのモジュールを考えてみましょうData.Map
。データ型と、その型で動作するいくつかの関数を定義します。型シグネチャだけを見ると、[原則として]値を構築するすべての可能な方法を把握できるはずMap
です。つまり、アルゴリズム的に可能ということです。モジュールへのインターフェイスを取り、モジュールに対して実行できるすべての可能な関数呼び出しを計算するプログラムを作成できるはずです。
さて、よく書かれたテスト スイートは、ライブラリが何をすべきかの「仕様」と見なすことができると感じる人がいます。明らかに、コードを書いた人間は何をしようとしているのかを知っていますが、機械は知りません。しかし、あなたが提供した型シグネチャがあれば、マシンは何を要求できるかを理解できるはずです。
より具体的なケースとして、すべての可能な値に適用されるはずの一連の不変条件があるとしますMap
。(たとえば、null m == (size m == 0)
、またはおそらく内部の健全性チェック関数は常に true を返す必要があります。) テスト フレームワークを作成し、それをモジュールに渡し、「型の値はMap X Y
常にこれらの不変条件を満たさなければならない」と言って、テスト フレームワークをマップを作成し、それらがすべての条件を満たしていることを確認するために提供した関数のすべての可能な組み合わせを実行してみてください。そうでない場合は、違反している条件と、この無効な値を作成するために必要な式が示されます。
私の質問は、この種のアプローチは扱いやすいと思いますか? 望ましい?面白い?このような問題を解決するには、どのようにアプローチしますか? Djinn は、既存の関数と定数を指定して、指定された型の値を構築する方法を既に知っているようです。そのため、特定の型を持つ複数の式を考え出すことはそれほど難しいことではありません。適切なコード カバレッジを取得するために、どのような種類のヒューリスティックを適用できますか? (明らかに、型だけでなくコードを分析することは非常に困難です...ライスの定理が待ち構えています。)
(この種のマシン チェックが手書きのテスト コードに取って代わるべきだと言っているわけではないことに注意してください。この考えは、それを補強することを目的としています。おそらく、より困難なケースでは、マシンが考えられる表現をせき止めて、人間にそのコードの意味を尋ねます。これは新しいテスト ケースとして記録され、テスト スイートが実行されるたびに実行されます。)