FsCheck.xUnit: 测试来自另一个程序集的类型

FsCheck.xUnit: testing types from another assembly

我正在尝试使用 FsCheck 和 xUnit 进行第一次测试。我有以下设置:

当我 运行 项目(使用 VS 或控制台 运行ner)时,出现以下错误:

System.Exception : The type Lib.ABC is not handled automatically by FsCheck. 
Consider using another type or writing and registering a generator for it

如果我将类型移至测试程序集,一切正常(测试失败)。如何测试外部类型?

首先,当我 运行 这样做时,我确实得到了与你不同的行为。我的测试项目的示例结果:

Result Message: FsCheck.Xunit.PropertyFailedException : Falsifiable, after 4 tests (0 shrinks) (StdGen (196938613,296107830)): Original: B

这是有道理的,因为 fscheck 应该能够通过反射自动为可区分的联合类型(例如 ABC)创建生成器,请参阅:https://fscheck.github.io/FsCheck/TestData.html

因此,我建议检查您的所有软件包是否已正确安装且完全是最新的。

我安装了:

  • FsCheck (v2.2.4)
  • FsCheck.Xunit (v2.2.4)
  • xunit (v2.1.0)

FSharp.Core

安装引用 FSharp.Core 的 nuget 包时务必小心,因为它们通常随特定版本一起分发,会覆盖您的项目设置。

如果发生这种情况,请从 packages.config 文件中删除 FSharp.Core,删除项目中对 FSharp.Core 的引用,并将其替换为所需版本的 FSharp.Core程序集列表。您可以在扩展名下找到 FSharp.Core。

您还可以在 app.config 文件中使用绑定重定向将对旧 FSharp.Core 版本的引用重定向到指定的较新版本。

在您的 .fsproj 中使用 <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> 可以自动生成此类绑定重定向。有关用法的更多详细信息,请参阅 https://fsharp.github.io/2015/04/18/fsharp-core-notes.html

发电机

您的错误消息涉及功能 fscheck,您可以在其中指定如何为 属性 测试目的创建类型的任意实例。自定义生成器的示例:

type MyGenerators =
    static member ABC() =
        {new Arbitrary<ABC>() with
            override x.Generator = gen { return A; } // generator that creates only A
            override x.Shrinker t = Seq.empty }

然后我可以使用这个生成器来检查我的 属性:

[<Property(Arbitrary=[|typeof<MyGenerators>|])>]
static member ``ABC is always A`` v =
    v = A

这个测试现在总是通过,因为我一直指定生成器创建一个 A

它似乎与一个已知问题有关 described on FsCheck GitHub

基本上,FsCheck NuGet 包依赖于旧版本的 FSharp.Core 库。旧版本被引用,导致测试代码与被测系统不兼容

解决问题:

  1. 安装 FsCheck NuGet 包后,转到测试项目引用并删除对旧版本 FSharp.Core(在我的例子中是 4.3.1.0)的引用。

  2. 单击"Add reference"再次添加它,转到程序集-> 扩展并添加与您其他项目中使用的相同版本的 FSharpCore,4.4.0.0 就我而言。

  3. 向您的测试项目添加一个 App.config 文件,其内容如下:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
            <bindingRedirect oldVersion="4.3.1.0" newVersion="4.4.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>