2017-06-28 4 views
3

FsCheckを正しく使用する方法を習得しようとしていて、現時点でExpectoと統合しようとしています。デフォルトのFsCheck設定を使用している場合はプロパティテストを実行できますが、独自のGeneratorを使用しようとするとスタックオーバーフロー例外が発生します。ここでExpecto FsCheck文字列を生成するときにスタックオーバーフロー例外が発生する

は私の発電機は

type NameGen() = 
    static member Name() = 
     Arb.generate<string * string> 
     |> Gen.where (fun (firstName, lastName) -> 
      firstName.Length > 0 && lastName.Length > 0 
     ) 
     |> Gen.map (fun (first, last) -> sprintf "%s %s" first last) 
     |> Arb.fromGen 
     |> Arb.convert string id 

であり、私はこのようにそれを使用しようとしている:

let config = { FsCheckConfig.defaultConfig with arbitrary = [typeof<NameGen>] } 

let propertyTests input = 
    let output = toInitials input 
    output.EndsWith(".") 

testPropertyWithConfig config "Must end with period" propertyTests 

それもGen.where機能

何になる前に、例外がスローされます私は間違っている?ありがとう

答えて

5

FsCheckの文字列ジェネレータを使用して、文字列のジェネレータの仕組みを再定義しようとしていますが、そうするとスタックスペースがなくなるまで再帰的に呼び出されます。これは既知の問題です:https://github.com/fscheck/FsCheck/issues/109

この代替手段はありますか?

type NameGen = 
    static member Name() = 
     Arb.Default.NonEmptyString().Generator 
     |> Gen.map (fun (NonEmptyString s) -> s) 
     |> Gen.two 
     |> Gen.map (fun (first, last) -> sprintf "%s %s" first last) 
     |> Arb.fromGen 
3

あなたは、文字列型のための新しいジェネレータを定義しているが、その中に、あなたはstringのための発電機を使用していますstring * stringための発電機を、使用しています。 FsCheckは残念ながらジェネレータをグローバルな可変状態に保存しているようです(おそらく理由がありますか?)、これはジェネレータがスタックオーバーフローまで自分自身を呼び出し続けていることを意味します。

これを解決するには、ジェネレータをプレーンな文字列(下図参照)ではなくカスタムラッパータイプに定義します。

次の問題はnull参照例外になります。初期生成文字列はnullで、.Lengthプロパティにアクセスしようとしました。これは、代わりにString.length関数を使用して解決することができ、nullの場合は0を返します。

type Name = Name of string 

type NameGen() = 
    static member Name() = 
     Arb.generate<string * string> 
     |> Gen.where (fun (firstName, lastName) -> 
      String.length firstName > 0 && String.length lastName > 0 
     ) 
     |> Gen.map (fun (first, last) -> sprintf "%s %s" first last) 
     |> Arb.fromGen 
     |> Arb.convert Name (fun (Name n) -> n) 

そして、あなたの財産は、わずかな修正必要があります:あなたの発電機はこのようになります。これらの変更により

let propertyTests (Name input) = 
    let output = toInitials input 
    output.EndsWith(".") 
関連する問題