It is about time to release a new version of FsCheck, and here it is.
What’s new in this release?
-
A fluent interface for C# and VB
This is in prototype stage at the moment, and has some limitations with respect to the F# interface, but I would say it’s about 90% functional. An example of a property in C#:
Spec.ForAny<int, int[]>((x, xs) => xs.Insert(x).IsOrdered()) .When((x, xs) => xs.IsOrdered()) .Classify((x, xs) => new int[] { x }.Concat(xs).IsOrdered(), "at-head") .Classify((x, xs) => xs.Concat(new int[] { x }).IsOrdered(), "at-tail") .QuickCheck("InsertClassify");
This property is the equivalent of the following in F#:
let prop_InsertClassify (x:int) xs = ordered xs ==> (ordered (insert x xs)) |> classify (ordered (x::xs)) "at-head" |> classify (ordered (xs @ [x])) "at-tail" quickCheck prop_InsertClassify
As you can see, it’s about the same amount of code, but because of the fluent interface I have to add a class for each number of type arguments - currently limited to three. Ideally, I’d like to generate some code for classes up to six or nine, but for the moment it’s all copy-paste and you can only write properties with up to three parameters this way. For the rest, almost everything should be working: you can register generators, provide configuration, add shrinkers, and write generators using some combinators and LINQ:
var gen = from x in Any.OfType<int>() from y in Any.IntBetween(5, 10) where x > 5 select new { Fst = x, Snd = y };
Pretty neat.
Incidentally, there is no C# code in FsCheck itself, and the fluent interface is all pure F# code. This was a good test to see how interoperable F# really is. Overall, the experience has been great, with just a few minor hiccups.
I translated most of the F# examples from the documentation to C# as well, you can find those in the F# source distribution.
-
Possibility to replay a test run. FsCheck now displays the seed it used to start a test run when it fails. You can give this seed to a configuration parameter, so that FsCheck will repeat the run with exactly the same generated values:
check { quick with Name="Counter-replay"; Replay = Some <| Random.StdGen (395461793,1) } (asProperty spec)
-
Various bug fixes and updates to xml docs.
-
I’m making headway in testing FsCheck using FsCheck itself. It’s an interesting experience, and I have a blog post lined up about it.
The C#/VB “mainstream” support is something that I hope to continue to improve – I also plan to add reflective object generators and Gallio integration, mainly as a means to get some more attention for FsCheck. It’s also an interesting exercise to compare approaches. So far, if you know F#, I’d stick with it, but you can see that LINQ is occasionally very elegant for defining generators.
Happy FsChecking!
Share this post : | Technet! | del.icio.us it! | del.iri.ous! | digg it! | dotnetkicks it! | reddit! | technorati! |
The C# and VB interface will make FsCheck much more approachable for the average .NET developer. Great job.
ReplyDeleteExcellent work.
ReplyDeleteRight now I'm only using FsCheck to do simple back-and-forth tests on some F# tree transforms, but I can see its usage sneaking out into other languages being VERY AWESOME.