为什么我在基于 属性 的测试中收到 "No arguments provided" 错误?
Why am I receiving a "No arguments provided" error on a property-based test?
以下测试失败:
open FsCheck
open FsCheck.NUnit
open NUnit.Framework
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
[<Test>]
let ``reversing list two times is equal to not reversing list at all`` list =
Check.Quick ``Property: double negation equals no negation``
错误:
Message: No arguments were provided
我以为 FsCheck 会在每次测试迭代时为我提供参数。
我参考了以下 documentation。
这是 xUnit.net 的一个版本:
open FsCheck
open Xunit
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
[<Fact>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.Quick ``Property: double negation equals no negation``
当你那样使用它时,第一个函数是 属性,它可以接受参数。
带 [<Fact>]
注释的函数不带参数。
该方法的问题在于,如果 属性 不成立,Check.Quick
不会导致测试失败。它只输出 属性 是伪造的。如果你想让测试在 属性 被伪造时失败,你应该使用 Check.QuickThrowOnFailure
:
open FsCheck
open Xunit
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
[<Fact>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.QuickThrowOnFailure ``Property: double negation equals no negation``
另一个问题是没有理由把它写得这么冗长。这里有一个更紧凑的方式来写同样的 属性:
open FsCheck
open Xunit
[<Fact>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.QuickThrowOnFailure <| fun (l : int list) ->
l = List.rev (List.rev l)
Mark 的回答很好,但只是为了澄清 NUnit 的情况。
FsCheck.NUnit 提供 PropertyAttribute
来修饰接受参数的测试方法。它不会连接到普通的 NUnit TestAttribute
。所以换句话说,你的例子有一个正常的 NUnit 测试,它接受一个参数——NUnit 无法处理这个。采用您希望 FsCheck 为其生成值的参数的测试如下所示:
[<Property>]
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
另一个选择 - 如果你不想与 NUnit 和 FsCheck.NUnit 纠缠不清,正如 Mark 所说,它可能非常脆弱,主要是由于 NUnit 2 非常烦人的插件模型 - 是不使用 FsCheck.NUnit,而是使用正常的 NUnit 测试。使用 QuickCheckThrowOnFailure
通过异常将 FsCheck 的测试失败信号发送给 NUnit:
[<Test>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.QuickThrowOnFailure ``Property: double negation equals no negation``
您的示例以某种方式混合了这两个选项。
以下测试失败:
open FsCheck
open FsCheck.NUnit
open NUnit.Framework
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
[<Test>]
let ``reversing list two times is equal to not reversing list at all`` list =
Check.Quick ``Property: double negation equals no negation``
错误:
Message: No arguments were provided
我以为 FsCheck 会在每次测试迭代时为我提供参数。
我参考了以下 documentation。
这是 xUnit.net 的一个版本:
open FsCheck
open Xunit
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
[<Fact>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.Quick ``Property: double negation equals no negation``
当你那样使用它时,第一个函数是 属性,它可以接受参数。
带 [<Fact>]
注释的函数不带参数。
该方法的问题在于,如果 属性 不成立,Check.Quick
不会导致测试失败。它只输出 属性 是伪造的。如果你想让测试在 属性 被伪造时失败,你应该使用 Check.QuickThrowOnFailure
:
open FsCheck
open Xunit
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
[<Fact>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.QuickThrowOnFailure ``Property: double negation equals no negation``
另一个问题是没有理由把它写得这么冗长。这里有一个更紧凑的方式来写同样的 属性:
open FsCheck
open Xunit
[<Fact>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.QuickThrowOnFailure <| fun (l : int list) ->
l = List.rev (List.rev l)
Mark 的回答很好,但只是为了澄清 NUnit 的情况。
FsCheck.NUnit 提供 PropertyAttribute
来修饰接受参数的测试方法。它不会连接到普通的 NUnit TestAttribute
。所以换句话说,你的例子有一个正常的 NUnit 测试,它接受一个参数——NUnit 无法处理这个。采用您希望 FsCheck 为其生成值的参数的测试如下所示:
[<Property>]
let ``Property: double negation equals no negation`` list =
list = List.rev (List.rev list)
另一个选择 - 如果你不想与 NUnit 和 FsCheck.NUnit 纠缠不清,正如 Mark 所说,它可能非常脆弱,主要是由于 NUnit 2 非常烦人的插件模型 - 是不使用 FsCheck.NUnit,而是使用正常的 NUnit 测试。使用 QuickCheckThrowOnFailure
通过异常将 FsCheck 的测试失败信号发送给 NUnit:
[<Test>]
let ``reversing list two times is equal to not reversing list at all`` () =
Check.QuickThrowOnFailure ``Property: double negation equals no negation``
您的示例以某种方式混合了这两个选项。