2016-12-09 13 views
4

最初に5つの要素が固定されているジェネレータを作成しようとしましたが(最初の5つが常に実行されるProp.forAllを使用するテストでは) 。FsCheckの項目リストを固定してジェネレータを作成するには

ここでは、範囲内のランダムデータ用の1つのジェネレータと、非ランダムデータ用の1つのジェネレータ(固定シーケンス)を使用することで、これを簡略化しようとしています。 1つの値の代わりに一連の値である点を除いて、Gen.constantに似ています。

私はこの(簡易再現可能な例、NUnitのとxUnitフレームで動作します)があります。

[<Property(Verbose = true, MaxTest=5)>] 
static member MultiplyIdentityCornerCases() = 
    Gen.elements [0L; -1L; 1L; Int64.MinValue; Int64.MaxValue] 
    |> Arb.fromGen 
    |> Prop.forAll <| fun x -> x = x * 1L 

出力(nullから来て全く分から)ではありません:私が好きな

0: 
<null> 
9223372036854775807L 
1: 
<null> 
-9223372036854775807L 
2: 
<null> 
-9223372036854775807L 
3: 
<null> 
1L 
4: 
<null> 
-9223372036854775807L 
Ok, passed 5 tests. 

をシーケンス内の5つのテストのすべてを含む出力、好ましくは必ずしもそうではないが、順番に出力される。私はtestdataプロバイダを使ってNUnit(または任意のユニットテストシステム)でこれを行うことができますが、私はFsCheckでそれを行うことができるかどうか、あるいは私はそれが悪い考えであるかどうかは疑問です。

私はFsCheckを使うと便利です。複数の関数引数がある状況については、私が与えたコーナーケースの引数のすべての組み合わせを網羅的にテストしたいと思います。これは、FsCheckがtestdataプロバイダよりもうまくいけば簡単です。

+0

これを修正する方法の1つは、おそらくナンバージェネレータの非ランダム性を使用しているか(またはその仕方を確認してください)、それが動作するのに必要な方法で正確に動作するように見えます(FsCheck出力私の[以前の質問](http://stackoverflow.com/questions/40923916/how-to-use-fscheck-to-generate-random-numbers-as-input-for-property-based-testin?rq = 1)) – Abel

答えて

7

私はそれが可能だと認識していないんだけど、あなたがこれを行うことができます:

open System 
open FsCheck 
open FsCheck.Xunit 

[<Property>] 
let MultiplyIdentityCornerCases() = 
    Gen.oneof [ 
     Gen.elements [Int64.MinValue; -1L; 0L; 1L; Int64.MaxValue] 
     Arb.generate ] 
    |> Arb.fromGen 
    |> Prop.forAll <| fun x -> x = x * 1L 

二つの発電機は、Gen.oneofに渡されますので、これらのそれぞれの値の約半分を生成します。

Gen.elementsは、指定されたシーケンス内のすべての値から一様に選択する必要があります。 0L時間の20%ですが、Gen.oneofGen.elementsの場合の半分の場合に限ります。

つまり、それぞれの「特別な」値は、50%* 20%= 10%の時間で生成されます。

デフォルトでは、プロパティは100テストケースを実行するため、平均で10 0L値、10 Int64.MinValue値などが生成されます。それはしばしば十分に良いはずです。


されていない場合は、このような何か、あなたはいつでもできます。ここでは

open System 
open Xunit 
open FsCheck 
open FsCheck.Xunit 
open Swensen.Unquote 

[<Theory>] 
[<InlineData(Int64.MinValue)>] 
[<InlineData(-1L)>] 
[<InlineData(0L)>] 
[<InlineData(1L)>] 
[<InlineData(Int64.MaxValue)>] 
let MultiplyIdentityCornerCases x = x =! x * 1L 

[<Property>] 
let MultiplyIdentityCornerCasesProperty x = 
    MultiplyIdentityCornerCases x 

を、あなたはxUnit.netの[<Theory>]機能を使用してパラメータ化されたテストを定義し、5コーナーケースにあなたをそれを養いますと関連している。テストを実行すると、テストランナーは5つのテストケースを実行します。

[<Property>]と注釈されているため、この関数は単に他の関数を呼び出します。

+1

私は2番目のコードスニペットが一番好きです。それは実際にはかなりきれいです。 –

+0

もう一度、ありがとう。私は、データプロバイダの静的データを置き換えることができれば、2番目のアプローチが気に入っていますが、それは問題ではありません。現時点では、上記の最初のアプローチの変種を使用しましたが、実際にはうまくいくように見えます(すべての確率を一定の確実性で満たすために十分なテストが実行されていることを確認してください)。 – Abel

関連する問題