我正在尝试实现一个Arbitrary
生成 glob 语法模式的自定义,例如a*c?
. 我认为我的实现是正确的,只是在使用 Xunit 运行测试时,FsCheck 似乎没有使用自定义任意Pattern
生成测试数据。但是,当我使用 LINQPad 时,一切都按预期工作。这是代码:
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
这是输出:
可证伪,经过 2 次测试(0 次收缩)(StdGen (1884571966,296370531)):原始:模式 null 异常:System.NullReferenceException ...
这是我在 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)):原始:模式“a*”
如您所见,尽管我使用and来控制测试数据,但 FsCheck 在 Xunit 测试中生成了一个null
值。此外,当我运行它几次时,我看到了超出指定字符范围的测试模式。在 LINQPad 中,这些模式是正确生成的。我还在 Visual Studio 2017 中使用常规 F# 控制台应用程序进行了相同的测试,并且自定义工作也按预期工作。Pattern
Gen.elements
Gen.nonEmptyListOf
Arbitrary
出了什么问题?在 Xunit 中运行时 FsCheck是否回退到默认值string
Arbitrary
?
您可以克隆此 repo 以亲自查看:https ://github.com/bert2/GlobMatcher
(我不想使用Prop.forAll
,因为每个测试都会有多个 customArbitrary
并且Prop.forAll
不适合。据我所知,我只能将它们组合起来,因为 F# 版本Prop.forAll
只接受一个Arbitrary
。)