Combining FsCheck Properties in a single Test

You may have a bunch of tests that are very similar, and you don’t want to repeat yourself so many times. In FsCheck you can “and” properties with the .&. operator and label failures with either of the @| or |@ operators. The only problem is the first failing property will trigger all the subsequent labels to write as well. Here’s a little work-around to that situation:

1: 
2: 
3: 
4: 
5: 
6: 
7: 
[<Test>]
let ``returns expected length``() =
    Check.VerboseThrowOnFailure 
        ( (1 = 1) |@ sprintf "1 != 2" 
        .&. (2 = 3) |@ sprintf (if false then "" else "2 != 3")
        .&. (3 = 3) |@ sprintf (if (3 = 3) then "" else "3 != 4") 
        .&. (4 = 5) |@ sprintf (if false then "" else "4 != 5") )

Remember the code to the left of |@ is an FsCheck property, and the similar looking statement to the right is an F# expression returning a bool, so you have to keep these two pieces of code in sync. Other than that hassle, this works and will only print labels from failing properties in your combined test.

val ( returns expected length ) : unit -> unit

Full name: Snippet.( returns expected length )

type Check =
  static member All : config:Config -> unit
  static member All : config:Config * test:Type -> unit
  static member Method : config:Config * methodInfo:MethodInfo * ?target:obj -> unit
  static member One : config:Config * property:’Testable -> unit
  static member One : name:string * config:Config * property:’Testable -> unit
  static member Quick : property:’Testable -> unit
  static member Quick : name:string * property:’Testable -> unit
  static member QuickAll : unit -> unit
  static member QuickAll : test:Type -> unit
  static member QuickThrowOnFailure : property:’Testable -> unit
  …

Full name: FsCheck.Check

static member Check.VerboseThrowOnFailure : property:’Testable -> unit
val sprintf : format:Printf.StringFormat<‘T> -> ‘T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf

3 thoughts on “Combining FsCheck Properties in a single Test

  1. Hi Jack,

    Well, that sucks. Thanks for bringing it to attention.

    It’s a consequence of the fixity of .&. and |@ being equal, which means that this get parsed somewhat counter-intuitively. If you put parenthesis around all the various parts of the .&. it no longer prints the other ones, only the first one that fails (it is a shortcutting and so in your example you’ll only see the 2 != 3).

    I will have a look at the fixity definition of fsharp, sadly you can’t define those separately but they’re derived from the name somehow, so will need to deprecate or rename some operators to make it work.

    Best, Kurt

  2. Pingback: F# Weekly #5, 2014 | Sergey Tihon's Blog

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>