FsCheck を試してみようと思ったのですが、思ったより難しいことがわかりました。、ジェネレーターなどに関する多くのドキュメントArb
がありますが、その知識を適用する方法についてのガイダンスはないようです。または、私はそれを理解していません。
テスト、プロパティ、ジェネレーター、任意、シュリンク、そして私の場合はランダム性 (自動的にランダム データを生成するテストもあれば、生成しないテストもあります) との関係が明確ではないため、理解が難しくなっている可能性があります。私は Haskell のバックグラウンドを持っていないので、それもあまり役に立ちません。
ここで質問があります: ランダムな整数を生成するにはどうすればよいですか?
私のテストシナリオは、乗算の特性で説明できます。たとえば、分配性を考えてみましょう。
static member ``Multiplication is distributive`` (x: int64) y z =
let res1 = x * (y + z)
let res2 = x * y + x * z
res1 = res2
// run it:
[<Test>]
static member FsCheckAsUnitTest() =
Check.One({ Config.VerboseThrowOnFailure with MaxTest = 1000 }, ``Multiplication is distributive``)
これを NUnit 統合で実行するとCheck.Verbose
、次のようなテスト シーケンスが得られます。
0:
(-1L, -1L, -1L)
1:
(-1L, -1L, 0L)
2:
(-1L, -1L, -1L)
3:
(-1L, -1L, -1L)
4:
(-1L, 0L, -1L)
5:
(1L, 0L, 2L)
6:
(-2L, 0L, -1L)
7:
(-2L, -1L, -1L)
8:
(1L, 1L, -2L)
9:
(-2L, 2L, -2L)
1000回のテストの後、それは乗り越えられませんでした100L
. どういうわけか、これが の全範囲に均等に分散された乱数を「自動的に」選択すると想像しint64
ました。少なくとも、それがドキュメントの解釈方法でした。
そうでないので、私は実験を開始し、より高い数値を得るために次のようなばかげた解決策を思いつきました:
type Generators =
static member arbMyRecord =
Arb.generate<int64>
|> Gen.where ((<) 1000L)
|> Gen.three
|> Arb.fromGen
しかし、これは信じられないほど遅くなり、明らかに正しいアプローチではありません。私が見逃している簡単な解決策があるに違いないと確信しています。で試しましGen.choose(Int64.MinValue, Int64.MaxValue)
たが、これは int のみをサポートし、long はサポートしていません (ただし、int だけでも機能しませんでした)。
最後に、すべてのプリミティブな数値データ型に対して機能するソリューションが必要です。これには、最大値と最小値、ゼロと 1、およびその中にあるものからのランダムな選択が含まれます。