Search code examples
f#nunit-2.5fscheck

Why am I receiving a "No arguments provided" error on a property-based test?


The following test fails:

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``

Error:

Message: No arguments were provided

I thought FsCheck would provide the argument for me on each test iteration.

I am referencing the following documentation.


Solution

  • Here's a version for xUnit.net that sort of works:

    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``
    

    When you use it that way, the first function is the property, and it can take arguments.

    The [<Fact>]-annotated function takes no argument.

    The problem with that approach is that Check.Quick doesn't cause the test to fail if the property doesn't hold. It only outputs that the property was falsified. If you want the test to fail if the property is falsified, you should use 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``
    

    Another issue is that there's no reason to write this in such a verbose fashion. Here's a more compact way to write the same property:

    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)