如何定义FSCheck生成器以便可以发现它

时间:2017-04-17 14:41:16

标签: f# fscheck

我正在编写FSCheck生成器来创建具有以下属性的字符串:

  • 它们是非空的
  • 修剪它们不会影响长度
  • 它们不包含空格。

这是我的生成器代码:

namespace Example

open FsCheck.Arb

module public Generation = 

    let hasChars (s : string) =
        (isNull s |> not)
        && s.Length > 0

    let isTrimmed (s : string) =
        s.Trim().Length = s.Length

    let isContinuous (s : string) =
        s
        |> Seq.exists ((=) ' ')
        |> not

    [<AbstractClass; Sealed>]
    type public Generators = class end

    type public ContinuousString = ContinuousString of string with
        member x.Get = match x with ContinuousString r -> r
        override x.ToString() = x.Get

    type public Generators with

        static member ContinuousString() =
            Default.String()
            |> filter hasChars
            |> filter isTrimmed
            |> filter isContinuous
            |> convert ContinuousString string

这是一个旨在验证这一代的测试:

[<Property(Arbitrary=[| typeof<ContinuousString> |], MaxTest=2)>]
let ``A continuous string contains no spaces`` (s: ContinuousString) =
    s.Get.Contains " " |> not

当我运行此测试时,我得到:

System.Exception: No instances found on type Example.Generation+ContinuousString. Check that the type is public and has public static members with the right signature.

据我所知,查看FSCheck源代码,我已定义的成员应该由发现过滤器找到,该方法似乎类似于类似的内置类似NonEmptyString

我错过了什么?谢谢!

1 个答案:

答案 0 :(得分:5)

您正在通过FsCheck错误的类型。您应该将Generators课程传递给您,而不是您的ContinuousString DU。即,这个:

[<Property(Arbitrary=[| typeof<ContinuousString> |], MaxTest=2)>]
let ``A continuous string contains no spaces`` (s: ContinuousString) =
    s.Get.Contains " " |> not

应该是:

[<Property(Arbitrary=[| typeof<Generators> |], MaxTest=2)>]
let ``A continuous string contains no spaces`` (s: ContinuousString) =
    s.Get.Contains " " |> not

FsCheck错误消息也试图告诉你:

  

检查类型是否为公共类型,并且具有正确签名的公共静态成员。

您创建的匹配其所需内容的类型为Generators