vendredi 22 septembre 2017

Why are preconditions failing to work in this FsCheck example?

I am trying to use the FsCheck library. I can do some tests but preconditions do not seem to work. The code below provides an example:

let sortEven (xs: int list) =
    xs
    |> List.filter (fun x -> x % 2 = 0)
    |> List.sort

let lengthGT0 (xs: int list) = (List.length xs) > 0

[<Property>]
let checkSortEven (xs: int list) =
    lengthGT0 xs ==>
    ((xs |> sortEven |> List.sum) = (xs |> List.rev |> sortEven |> List.max))

Calling the function checkSortEven with an empty list as its argument generates an exception because List.rev does the same. So, in the code above, I tried to use a precondition, using the ==> operator, to prevent the FsCheck from trying empty lists. However, whether the first list tested is empty or a shrunk list is empty checkSortEven is called an exception is generated:

Falsifiable, after 1 test (0 shrinks) (StdGen (843297067,296354622)):
Original:
[]
with exception:
System.ArgumentException: The input sequence was empty.

Falsifiable, after 1 test (1 shrink) (StdGen (1296284131,296354622)):
Original:
[-1]
Shrunk:
[]
with exception:

    System.ArgumentException: The input sequence was empty.

Falsifiable, after 1 test (2 shrinks) (StdGen (1865393009,296354622)):
Original:
[-1; 1]
Shrunk:
[]
with exception:
System.ArgumentException: The input sequence was empty.

There is a related question on SO at Why is my precondition being ignored on my Property-based test? but it seems to be a different case (nested functions).

I also tried Check.QuickThrowOnFailure instead of Check.Quick with basically the same results.

Any ideas on why preconditions are not working in this example?

Aucun commentaire:

Enregistrer un commentaire