How would you go about writing a Tasty HUnit test that incorporates multiple checks against a single fixture variable in a single test, or at least a tidy group of such tests?
For example, consider this Gherkin specification:
Scenario: A 3-Vector has x, y and z components
Given: a <- Vec(1.0, 2.0, 3.0)
Then: a.x = 1.0
And a.y = 2.0
And a.z = 3.0
I could do something like this, but it's very repetitive:
unitTests = testGroup "All Unit Tests"
[ testCase "A 3-Vector has x, y and z components" $ assertEqual [] (x $ Vec 1.0 2.0 3.0) 1.0
, testCase "A 3-Vector has x, y and z components" $ assertEqual [] (y $ Vec 1.0 2.0 3.0) 2.0
, testCase "A 3-Vector has x, y and z components" $ assertEqual [] (z $ Vec 1.0 2.0 3.0) 3.0
]
The concern I have about this is that I've repeated the scenario name three times, and I've also created the fixture three times. I'd like to find a way to group all three assertions into a single group with the title "A 3-Vector has x, y and z components", and only specify the fixture Vec once.
I could expand the test specification to minimise some of the description repetition, but I'd rather stick to the Gherkin spec if I can:
unitTests = testGroup "All Unit Tests"
[ testCase "A 3-Vector has x component" $ assertEqual [] (x $ Vec 1.0 2.0 3.0) 1.0
, testCase "A 3-Vector has y component" $ assertEqual [] (y $ Vec 1.0 2.0 3.0) 2.0
, testCase "A 3-Vector has z component" $ assertEqual [] (z $ Vec 1.0 2.0 3.0) 3.0
]
I don't know of a way to define the Vec just once, for the group.
What I'd like to do is something like this (not real code!):
unitTests = testGroup "All Unit Tests"
[ testScenario "A 3-Vector has x, y and z components"
let v = Vec 1.0 2.0 3.0 in
[ testCase "x" assertEqual [] (x $ v) 1.0
, testCase "y" assertEqual [] (y $ v) 2.0
, testCase "z" assertEqual [] (z $ v) 3.0
]
]
Thank you to Joachim Breitner who suggested that my "not real code" wasn't too far off the mark. He is correct.
With a bit of tweaking I ended up with this, which works as I want it to:
data Vec = Vec { x, y, z :: Double } deriving (Show)
unitTests = testGroup "All Unit Tests"
[ testGroup "A 3-Vector has x, y and z components" $
let v = Vec 1.0 2.0 3.0 in
[ testCase "x" $ assertEqual [] (x v) 1.0
, testCase "y" $ assertEqual [] (y v) 2.0
, testCase "z" $ assertEqual [] (z v) 3.0
]
]