FsCheck 与 C# 中的 NUnit 集成
FsCheck integration with NUnit in C#
TL;DR:我无法在 C# 中成功地将 FsCheck 与 NUnit 结合使用:要么:
- 它在标准输出上告诉我测试失败但测试仍然显示为绿色
- 它告诉我它没有找到 运行
的任何测试
- 或者我不明白如何在 C# 中应用我阅读的文档
我认为一个虚拟但完整的例子会有所帮助...
(更多详情)
第一步:测试保持绿色
我安装了Nuget包FsCheck.NUnit
(2.10.4),天真地试了一下:
[NUnit.Framework.Test]
public void SomeTest()
{
// Note the subtle bug: I Reverse only once, because I want the test to fail
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
Prop.ForAll(revRevIsOrig).QuickCheck();
}
当我 运行 它就像我 运行 任何 NUnit 测试一样,它最终是绿色的,即使我在标准输出上看到
Falsifiable, after 3 tests (1 shrink) (StdGen (2129798881,296376481)):
Original:
[|-1; 0|]
Shrunk:
[|1; 0|]
第二步:测试无定论
所以我继续,发现了一些 doc,并注意到我应该使用 Property
而不是 Test
。所以我将代码更改为
[FsCheck.NUnit.Property] // <-- the line that changed
public void SomeTest()
{
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
Prop.ForAll(revRevIsOrig).QuickCheck();
}
我从 Visual 启动了测试,结果状态为 inconclusive
。一些日志告诉我:
Cannot run tests: No suitable tests found in 'xxx.exe'. Either assembly contains no tests or proper test driver has not been found
第三步:我发现我没看懂文档
当我重新阅读文档时,我注意到它说我的测试方法可以接受参数并且应该 return 和 属性。我显然没有这样做,因为我 return 什么都没有。
可悲的是,我不明白我实际上应该做什么(而且我对 F# 不够熟悉,无法理解下面的示例...)...(我盲目地尝试了一些看起来有意义的随机东西,但我从未以红色测试结束)
非常感谢任何帮助我通过此测试的指示!
尝试使用 QuickCheckThrowOnFailure
函数
the QuickThrowOnFailure
ensures that if the test fails, an exception with the necessary information is raised so the runner know the test failed.
[Test]
public void SomeTest() {
// Note the subtle bug: I Reverse only once, because I want the test to fail
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
Prop.ForAll(revRevIsOrig).QuickCheckThrowOnFailure();
}
将 FsCheck 与 NUnit 结合使用的另一种方法(来自 FsCheck github 示例)是
[FsCheck.NUnit.Property(Verbose = true)]
public void SomeTest()
{
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
return Prop.ForAll(revRevIsOrig);
}
但是这种方式不会向您报告测试失败的原因。所以 Nkosi 的答案现在更好了,但我认为它会在某一天得到修复。
除了提到的其他选项之外,您可以使用 Property
属性将此测试转换为基于 属性 的测试 并更正 return 类型(为清楚起见,我包含了名称空间)。
注意 .ToProperty
调用将它变成 Property
。
[FsCheck.NUnit.Property]
public FsCheck.Property RevRev_IsOriginal(int[] xs)
{
Func<bool> revRevIsOrig = () => xs.Reverse().Reverse().SequenceEqual(xs);
return revRevIsOrig.ToProperty();
}
框架将通过int[] xs
方法参数生成测试数据。
这需要 nuget 包 fscheck
和 fscheck.nunit
(除了我的 .NET Core 3.1
中的 NUnit3TestAdapter
和 Microsoft.NET.Test.Sdk
测试项目)。
TL;DR:我无法在 C# 中成功地将 FsCheck 与 NUnit 结合使用:要么:
- 它在标准输出上告诉我测试失败但测试仍然显示为绿色
- 它告诉我它没有找到 运行 的任何测试
- 或者我不明白如何在 C# 中应用我阅读的文档
我认为一个虚拟但完整的例子会有所帮助...
(更多详情)
第一步:测试保持绿色
我安装了Nuget包FsCheck.NUnit
(2.10.4),天真地试了一下:
[NUnit.Framework.Test]
public void SomeTest()
{
// Note the subtle bug: I Reverse only once, because I want the test to fail
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
Prop.ForAll(revRevIsOrig).QuickCheck();
}
当我 运行 它就像我 运行 任何 NUnit 测试一样,它最终是绿色的,即使我在标准输出上看到
Falsifiable, after 3 tests (1 shrink) (StdGen (2129798881,296376481)):
Original:
[|-1; 0|]
Shrunk:
[|1; 0|]
第二步:测试无定论
所以我继续,发现了一些 doc,并注意到我应该使用 Property
而不是 Test
。所以我将代码更改为
[FsCheck.NUnit.Property] // <-- the line that changed
public void SomeTest()
{
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
Prop.ForAll(revRevIsOrig).QuickCheck();
}
我从 Visual 启动了测试,结果状态为 inconclusive
。一些日志告诉我:
Cannot run tests: No suitable tests found in 'xxx.exe'. Either assembly contains no tests or proper test driver has not been found
第三步:我发现我没看懂文档
当我重新阅读文档时,我注意到它说我的测试方法可以接受参数并且应该 return 和 属性。我显然没有这样做,因为我 return 什么都没有。
可悲的是,我不明白我实际上应该做什么(而且我对 F# 不够熟悉,无法理解下面的示例...)...(我盲目地尝试了一些看起来有意义的随机东西,但我从未以红色测试结束)
非常感谢任何帮助我通过此测试的指示!
尝试使用 QuickCheckThrowOnFailure
函数
the
QuickThrowOnFailure
ensures that if the test fails, an exception with the necessary information is raised so the runner know the test failed.
[Test]
public void SomeTest() {
// Note the subtle bug: I Reverse only once, because I want the test to fail
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
Prop.ForAll(revRevIsOrig).QuickCheckThrowOnFailure();
}
将 FsCheck 与 NUnit 结合使用的另一种方法(来自 FsCheck github 示例)是
[FsCheck.NUnit.Property(Verbose = true)]
public void SomeTest()
{
Func<int[],bool> revRevIsOrig = xs => xs.Reverse().SequenceEqual( xs );
return Prop.ForAll(revRevIsOrig);
}
但是这种方式不会向您报告测试失败的原因。所以 Nkosi 的答案现在更好了,但我认为它会在某一天得到修复。
除了提到的其他选项之外,您可以使用 Property
属性将此测试转换为基于 属性 的测试 并更正 return 类型(为清楚起见,我包含了名称空间)。
注意 .ToProperty
调用将它变成 Property
。
[FsCheck.NUnit.Property]
public FsCheck.Property RevRev_IsOriginal(int[] xs)
{
Func<bool> revRevIsOrig = () => xs.Reverse().Reverse().SequenceEqual(xs);
return revRevIsOrig.ToProperty();
}
框架将通过int[] xs
方法参数生成测试数据。
这需要 nuget 包 fscheck
和 fscheck.nunit
(除了我的 .NET Core 3.1
中的 NUnit3TestAdapter
和 Microsoft.NET.Test.Sdk
测试项目)。