2
\$\begingroup\$

I'm just getting started with F# and was writing some unit tests for some functionality I had written. In the interest of brevity, I decided to create some lists of the different test cases and just run through them all in one test instead of creating separate test methods for each one (I'm not focusing on that design decision here, just pointing it out as otherwise my question won't make much sense).

So here's my code:

// simple helper to cut down on repeated code
let testRunner cases func =
    cases |> List.map func

// isNumeric is the function under test, its functionality should be obvious
[<Test>]
let ``IsNumericTest``() =
    let testCases = ["123"; "Foo"; "123Foo123"]
    let expectedResults = [true; false; false]
    let results = testRunner testCases isNumeric
    results |> should equal expectedResults

I started thinking about creating a simple type to encapsulate the test case input and the expected result, something like this:

type TestCase = { Input : string; ExpectedResult : bool}

type TestCases = TestCase list

let testCases = [{Input="123"; ExpectedResult=true};{Input="Foo"; ExpectedResult=false}; {Input="123Foo123"; ExpectedResult=false}]

Then I struggled to think of how to split each of those down to use in my testRunner method until I came up with this:

let results = testRunner (testCases |> List.map (fun (T) -> T.Input)) isNumeric
results |> should equal (testCases |> List.map (fun (T) -> T.ExpectedResult))

But that just looks ugly. Is there a better way to split out the Input value for my testRunner method? I am fine with changing it, but figured that while my question is specific to a unit testing scenario, the lessons I should learn would be widely applicable.

\$\endgroup\$
1

1 Answer 1

2
\$\begingroup\$

Since you're on NUnit, why don't you just use its built-in TestCase attribute? Your test would then look like this:

[<TestCase("123", true)>]
[<TestCase("Foo", false)>]
[<TestCase("123Foo123", false)>]
let ``IsNumericTest``(candidate : string, expected : bool) =
    let actual = isNumeric candidate
    actual |> should equal expected

xUnit.net (a better unit testing framework for .NET) has a similar feature.

\$\endgroup\$
4
  • \$\begingroup\$ Because I didn't know about the TestCase attribute? ;) \$\endgroup\$ Feb 10, 2015 at 14:08
  • \$\begingroup\$ Do you care to comment on my question on splitting out the Input value? \$\endgroup\$ Feb 10, 2015 at 14:12
  • \$\begingroup\$ @SvenGrosen What specifically are you asking about? Is there a better way? Yes; I just showed you, but you must have something else in mind as well... \$\endgroup\$ Feb 10, 2015 at 22:08
  • \$\begingroup\$ I can't think of a good way of asking it, which probably means I'm not prepared to truly ask it. Thank you for your help. \$\endgroup\$ Feb 12, 2015 at 1:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.