我试图用FsCheck和xUnit进行我的第一次测试。我有以下设置:
具有单个文件的F#类库
namespace Lib
type ABC = A | B | C
一个名为Tests的项目,其中包含对单个文件的FsCheck.xUnit NuGet包的引用:
module LibTests
open FsCheck.Xunit
open Lib
[<Property>]
let ``ABC is always A`` v =
v = A
当我运行项目时(使用VS或控制台运行程序),我收到以下错误:
System.Exception : The type Lib.ABC is not handled automatically by FsCheck.
Consider using another type or writing and registering a generator for it
如果我将我的类型移动到Tests组件,一切正常(测试失败)。我如何测试外部类型?
答案 0 :(得分:4)
它似乎与已知问题described on FsCheck GitHub有关。
基本上,FsCheck NuGet包依赖于旧版本的FSharp.Core库。旧版本被引用,这使得测试代码与被测系统不兼容。
解决问题:
安装FsCheck NuGet包后,转到测试项目引用并删除对旧版FSharp.Core的引用(在我的情况下为4.3.1.0)。
点击“添加参考”再次添加,转到“装配” - &gt;扩展并添加与您的其他项目中使用的版本相同的FSharpCore,在我的情况下为 4.4.0.0 。
使用以下内容将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>
答案 1 :(得分:3)
首先,当我运行这个时,我确实会对你产生不同的行为。我的测试项目的一个示例结果:
结果消息:FsCheck.Xunit.PropertyFailedException:Falsifiable, 经过4次测试(0缩小)(StdGen(196938613,296107830)):原文:B
这是有道理的,因为fscheck应该能够通过反射自动为受歧视的联合类型(例如ABC
)创建生成器,请参阅:https://fscheck.github.io/FsCheck/TestData.html
因此,我建议您检查所有正确安装的软件包并完全更新。
我安装了:
<强> 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
。