a*c?
のようなグロブ構文パターンを生成するカスタムArbitrary
を実装しようとしています。私は自分の実装が正しいと思います.Xunitでテストを実行すると、FsCheckはテストデータを生成するために任意のカスタムPattern
を使用しているようには見えません。 LINQPadを使用すると、すべてが期待通りに機能します。オリジナル:例外を除いてヌルパターン:System.NullReferenceException 2つのテスト(0が縮む)(StdGen(1884571966,296370531))の後、カスタムFsCheck Xunitで任意の型が壊れていますが、LINQPadと通常のF#プログラムで動作しています
反証:これは出力され
open Xunit open FsCheck type Pattern = Pattern of string with static member op_Explicit(Pattern s) = s type MyArbitraries = static member Pattern() = (['a'..'c']@['?'; '*']) |> Gen.elements |> Gen.nonEmptyListOf |> Gen.map (List.map string >> List.fold (+) "") |> Arb.fromGen |> Arb.convert Pattern string Arb.register<MyArbitraries>() |> ignore [<Fact>] let test() = let prop (Pattern p) = p.Length = 0 Check.QuickThrowOnFailure prop
:ここでは、コードです...
そして、ここで私は出力とともにLINQPadで実行しているコードです:
open FsCheck
type Pattern = Pattern of string with
static member op_Explicit(Pattern s) = s
type MyArbitraries =
static member Pattern() =
(['a'..'c']@['?'; '*'])
|> Gen.elements
|> Gen.nonEmptyListOf
|> Gen.map (List.map string >> List.fold (+) "")
|> Arb.fromGen
|> Arb.convert Pattern string
Arb.register<MyArbitraries>() |> ignore
let prop (Pattern p) = p.Length = 0
Check.Quick prop
反証は、1回の試験後(0は縮む)(StdGen(1148389153,296370531)):オリジナル:パターン "*"
あなたはFsCheckはxUnitの中Pattern
ためnull
値を生成見ることができるように私はGen.elements
とGen.nonEmptyListOf
を使ってテストデータをコントロールしています。また、何回か実行すると、指定した文字範囲外のテストパターンが表示されます。 LINQPadでは、これらのパターンは正しく生成されます。私はまた、Visual Studio 2017の標準的なF#コンソールアプリケーションと同じものをテストしました。そこにはカスタムArbitrary
も期待通りに動作します。
何が問題になりますか? FsCheckはXunitで動作しているときにデフォルトのstring
Arbitrary
に戻っていますか?
:https://github.com/bert2/GlobMatcher
(私は、各テストはそれとうまくいかない複数のカスタムArbitrary
sおよびProp.forAll
を持つことになりますので、Prop.forAll
を使用しない限り。 Prop.forAll
のF#バージョンはArbitrary
を1つしか受け入れないため、私はそれらをタプル化することができます。
'MyArbitraries'を登録するために' Property'属性を使用することは、そのトリックを行いました。私はコンビネータを使用していませんでした。なぜなら、それぞれのテストには複数のカスタム仲裁が必要だからです。しかし、Prop.forAllは1つだけを受け入れます。少なくともF#で。 C#バージョン 'Prop.ForAll'は複数の仲裁人のために過負荷になっています。また、 'FsCheck.Xunit.Property'がテスト関数のパラメータを使用して必要なジェネレータを生成する方法も気に入っています。 'Prop.forAll'を使うより読みやすいIMOです。 –
ちょうど 'Prop.forAllFunc2Bool'のソースをチェックして、私がばかだと気づいた。もちろん、プロパティlambdasを使って 'Prop.forAll'の呼び出しをいつでもネストすることができます。すべての「任意」は、最も深いラムダの内部で利用可能です。 –
さて、もう少し掘り下げましたが、 'gen'計算式が本当に私の問題にとって最もクリーンで拡張可能な解決策であることが分かりました。 –