Sunday, August 30, 2009

F# unit testing and code coverage

And you thought it was going to be easy to get full coverage of functional code... Try this little example, assuming a Haskell-like Either<'a,'b>:

let ExpandFile name =
try
Right (new FileInfo(name)).FullName
with
| :? ArgumentException -> Left "fileNotFound"
view raw gistfile1.fs hosted with ❤ by GitHub

Feed it "dummy.txt" for the happy case, and something like "!!" for the bad case -- and you have an uncovered code-point for the untaken branch of the pattern -- i.e. rethrow any other exception type.

Then take that second case

[<Test>]
member self.ExpandFileWithJunkShouldFail() =
let expected = MakeEither "fileNotFound" String.Empty false
Assert.That( ExpandFile "!!", Is.EqualTo( expected ), "should not be a file name") |> ignore
view raw gistfile1.fs hosted with ❤ by GitHub

from which NCover reveals we have hidden classes like <StartupCode$Tinesware-InfrastructureTests>.$Tests+ExpandFileWithJunkShouldFail@24 and <StartupCode$Tinesware-InfrastructureTests>.$Tests+ExpandFileWithJunkShouldFail@24-1 where the module is Tinesware.InfrastructureTests, the file Tests.fs and the Assert call is on line 24 of the file. And the first is 100% covered and the second is 0% covered.

The Feb 2010 CTP only generates 1 indirecting class on that line, according to Reflector, the @24 one and not the @24-1 one.

No comments :