2016-12-02 15 views
5

FsCheckを試してみる時間だと思っていましたが、思っていた以上に厳しいものになりました。 Arb、ジェネレータなどに関する多くのドキュメントがありますが、その知識をどのように適用するかについてのガイダンスはないようです。または私はそれを得ていないだけです。プロパティベースのテストの入力としてFsCheckを使用して乱数を生成する方法

テスト、プロパティ、ジェネレータ、仲裁人、縮小、そして私の場合はランダム性(いくつかのテストでは自動的にランダムなデータが生成されますが、他のものではありません) 。私はハスケルのバックグラウンドを持っていないので、あまり役に立たない。

質問:乱数を生成するにはどうすればよいですか?

私のテストシナリオはのは、分配性を言わせて、掛け算の性質に説明することができます。

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``) 

私はCheck.VerboseまたはNUnitの統合でこれを実行すると、私は次のようにテストシーケンスを取得:

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)で試してみましたが、これはintsをサポートしていますが、longsではなく(ちょうどintであっても動作させることはできませんでした)。

最後に、すべての基本数値データ型(その最大値と最小値、ゼロと1を含む)、およびその中の何らかのランダム選択を含むソリューションが必要です。

+1

私はそれが最初に最大値を制限すると思います。 〜100、参照してください:[fscheck Q](http://stackoverflow.com/questions/40591229/fscheck-doesnt-generate-random-enough-data/) – s952163

+1

@ s952163、はい、私は 'MaxTest = 1000 '、上記のコードを参照してください。しかし、それは役に立たない。おそらく、あなたは 'StartTest'と' EndTest'の値を意味するでしょうが、これらを 'Int32.MinValue/MaxValue'に設定すると、すべての順列が' Int32.MinValue'を定数として使うという効果があります。 – Abel

答えて

5

this other FsCheck questionで説明したように、Check関数のほとんどのデフォルト設定はEndSize = 100です。あなたはその数を増やすことができますが、あなたも同様に、Gen.chooseを使用することができます。

でも、intintentionally well-behavedです。たとえば、Int32.MinValueInt32.MaxValueを含めると、オーバーフローが発生する可能性があります。

しかし、FsCheckには、Arb.Default.DoNotSizeInt16,Arb.Default.DoNotSizeUInt64などの全範囲にわたって一様な分布を与えるジェネレータも付属しています。浮動小数点値について

は、そのマニュアルに従って、"かなり頻繁に含まれる任意のフロートは、NaN、NegativeInfinity、PositiveInfinity、MAXVALUE、MinValueプロパティ、イプシロン" を生成Arb.Default.Float32、があります。

F#にはタイプクリスがありません(これはHaskellで表現できるものです)。

また、一般的なユニットテストフレームワークでジェネリックテストを実行することはできませんが、少なくともxUnit.netではthis trick to run generically typed testsを使用できます。


具体的には、しかし、あなたはFsCheck.Xunitを使用して、このような上記のテストを書くことができます。

open FsCheck 
open FsCheck.Xunit 

[<Property>] 
let ``Multiplication is distributive``() = 
    Arb.generate<DoNotSize<int64>> 
    |> Gen.map (fun (DoNotSize x) -> x) 
    |> Gen.three 
    |> Arb.fromGen 
    |> Prop.forAll <| fun (x, y, z) -> 

     let res1 = x * (y + z) 
     let res2 = x * y + x * z 

     res1 = res2 

これは、仮想的に溢れから失敗する可能性がありますが、いくつか百万例を実行した後、I避難所」それがまだ失敗するのを見た。それは64ビット整数の全範囲から値を選んだよう

ジェネレータは、しかし、実際に見てん:私は1Gen.samplesize引数を結合していても、それは選ぶこと

> Arb.generate<DoNotSize<int64>> |> Gen.sample 1 10;; 
val it : DoNotSize<int64> list = 
    [DoNotSize -28197L; DoNotSize -123346460471168L; DoNotSize -28719L; 
    DoNotSize -125588489564554L; DoNotSize -29241L; 
    DoNotSize 7736726437182770284L; DoNotSize -2382327248148602956L; 
    DoNotSize -554678787L; DoNotSize -1317194353L; DoNotSize -29668L] 

お知らせ任意に大きな正の値と負の値。

+0

ポインタと説明をありがとう。私は特定の数値型の完全な範囲を取ることができるアルゴリズムの動作をテストしているので、これを入力として使用することに興味があり、オーバーフローまたはアンダーフローはバグになります。私は、 '[0; 1; -1; MinValue; MaxValue]のすべての組み合わせを含む三方向パーミュテーションをどのように取得するのかまだ分かりませんし、テストカウントから残ったものがあれば、 'Arb.Default.Float32'のスタイル)。それとも、Arb.Default.DoNoSitzeXXXとまったく同じですか? – Abel

+0

私は以下のようにテストを実行しようとしました: 'Check.One({Config.VerboseThrowOnFailure with Arbitrary = [typeof >}}、MyDistribTestThreeArgs)'(そして '[t; t; t]'を持つバリアントif 3つの議論のために必要です)。ただし、いずれのメソッドも、_ "型FsCheck.DoNotSize'1 [[System.Int64 ...." _。私は 'Arb.Default ... 'を直接使うことはできません、configは' Type'を必要とします。私は明白なことを欠いていると確信していますが、何ですか? – Abel

+0

ああ、 'Arbitrary = Arb.Default.DoNotSizeInt64()。GetType()'も同様のエラーを投げます。奇妙なのは、デフォルトのctorを持つ正確な型を与えますが、それはその型を見つけることができないということです。 – Abel

関連する問題