Skip to content

Commit 1b82d6b

Browse files
authored
Merge pull request #260 from rbasso/hspec-clock
clock: Rewrite tests to use hspec with fail-fast.
2 parents 602a506 + 25cea32 commit 1b82d6b

File tree

2 files changed

+94
-91
lines changed

2 files changed

+94
-91
lines changed

exercises/clock/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@ tests:
1616
source-dirs: test
1717
dependencies:
1818
- clock
19-
- HUnit
19+
- hspec

exercises/clock/test/Tests.hs

Lines changed: 93 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,109 @@
1-
import Test.HUnit (Assertion, (@=?), runTestTT, Test(..), Counts(..))
2-
import System.Exit (ExitCode(..), exitWith)
1+
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
2+
3+
import Data.Foldable (for_)
4+
import Test.Hspec (Spec, describe, it, shouldBe)
5+
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
6+
37
import Clock (fromHourMin, toString)
48

9+
main :: IO ()
10+
main = hspecWith defaultConfig {configFastFail = True} specs
11+
512
-- Clock should define a data type that is an instance of Eq and
613
-- Num such that the `fromInteger` converts minutes
714
-- to 24 hour clock time. It is not necessary to have
815
-- a sensible implementation of `abs` or `signum`.
916

10-
exitProperly :: IO Counts -> IO ()
11-
exitProperly m = do
12-
counts <- m
13-
exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess
17+
specs :: Spec
18+
specs = describe "clock" $ do
1419

15-
testCase :: String -> Assertion -> Test
16-
testCase label assertion = TestLabel label (TestCase assertion)
20+
-- Track-specific tests.
21+
22+
describe "track-specific tests" $ do
23+
24+
it "fromInteger should work in minutes" $ do
25+
toString 3 `shouldBe` "00:03"
26+
27+
it "constructor and fromInteger should be compatible" $ do
28+
60 `shouldBe` fromHourMin 1 0
29+
30+
it "negate works" $ do
31+
negate (fromHourMin 23 55) `shouldBe` 5
32+
33+
-- Test cases extracted from x-common/clock.json from 2016-03-29
34+
35+
describe "standard tests" $ do
36+
37+
describe "create" $ for_ createCases createTest
38+
describe "add" $ for_ addCases addTest
39+
describe "equal" $ for_ equalCases equalTest
1740

18-
main :: IO ()
19-
main = exitProperly $ runTestTT $ TestList
20-
[ TestList clockTests ]
21-
22-
clockTests :: [Test]
23-
clockTests =
24-
[ testCase "fromInteger should work in minutes" $ do
25-
"00:03" @=? toString 3
26-
, testCase "constructor and fromInteger should be compatible" $ do
27-
fromHourMin 1 0 @=? 60
28-
, testCase "negate works" $ do
29-
5 @=? negate (fromHourMin 23 55)
30-
] ++ standardTests
31-
32-
-- Test cases extracted from x-common/clock.json from 2016-03-29
33-
standardTests :: [Test]
34-
standardTests = concat [ map testCreate casesCreate
35-
, map testAdd casesAdd
36-
, map testEqual casesEqual ]
3741
where
3842

39-
testCreate (l, h, m, e) = testCase l assertion
43+
createTest (l, h, m, e) = it l assertion
4044
where
41-
assertion = e @=? toString (fromHourMin h m)
45+
assertion = toString (fromHourMin h m) `shouldBe` e
4246

43-
testAdd (l, h, m, m', e) = testCase l assertion
47+
addTest (l, h, m, m', e) = it l assertion
4448
where
45-
assertion = e @=? toString (fromHourMin h m + m')
49+
assertion = toString (fromHourMin h m + m') `shouldBe` e
4650

47-
testEqual (l, (h1, m1), (h2, m2), e) = testCase l assertion
51+
equalTest (l, (h1, m1), (h2, m2), e) = it l assertion
4852
where
49-
assertion = e @=? fromHourMin h1 m1 == fromHourMin h2 m2
50-
51-
casesCreate =
52-
[ ("on the hour", 8, 0, "08:00")
53-
, ("past the hour", 11, 9, "11:09")
54-
, ("midnight is zero hours", 24, 0, "00:00")
55-
, ("hour rolls over", 25, 0, "01:00")
56-
, ("hour rolls over continuously", 100, 0, "04:00")
57-
, ("sixty minutes is next hour", 1, 60, "02:00")
58-
, ("minutes roll over", 0, 160, "02:40")
59-
, ("minutes roll over continuously", 0, 1723, "04:43")
60-
, ("hour and minutes roll over", 25, 160, "03:40")
61-
, ("hour and minutes roll over continuously", 201, 3001, "11:01")
62-
, ("hour and minutes roll over to exactly midnight", 72, 8640, "00:00")
63-
, ("negative hour", (-1), 15, "23:15")
64-
, ("negative hour rolls over", (-25), 0, "23:00")
65-
, ("negative hour rolls over continuously", (-91), 0, "05:00")
66-
, ("negative minutes", 1, (-40), "00:20")
67-
, ("negative minutes roll over", 1, (-160), "22:20")
68-
, ("negative minutes roll over continuously", 1, (-4820), "16:40")
69-
, ("negative hour and minutes both roll over", (-25), (-160), "20:20")
70-
, ("negative hour and minutes both roll over continuously", (-121), (-5810), "22:10")
71-
]
72-
casesAdd =
73-
[ ("add minutes", 10, 0, 3, "10:03")
74-
, ("add no minutes", 6, 41, 0, "06:41")
75-
, ("add to next hour", 0, 45, 40, "01:25")
76-
, ("add more than one hour", 10, 0, 61, "11:01")
77-
, ("add more than two hours with carry", 0, 45, 160, "03:25")
78-
, ("add across midnight", 23, 59, 2, "00:01")
79-
, ("add more than one day (1500 min = 25 hrs)", 5, 32, 1500, "06:32")
80-
, ("add more than two days", 1, 1, 3500, "11:21")
81-
, ("subtract minutes", 10, 3, (-3), "10:00")
82-
, ("subtract to previous hour", 10, 3, (-30), "09:33")
83-
, ("subtract more than an hour", 10, 3, (-70), "08:53")
84-
, ("subtract across midnight", 0, 3, (-4), "23:59")
85-
, ("subtract more than two hours", 0, 0, (-160), "21:20")
86-
, ("subtract more than two hours with borrow", 6, 15, (-160), "03:35")
87-
, ("subtract more than one day (1500 min = 25 hrs)", 5, 32, (-1500), "04:32")
88-
, ("subtract more than two days", 2, 20, (-3000), "00:20")
89-
]
90-
casesEqual =
91-
[ ("clocks with same time", (15, 37), (15, 37), True)
92-
, ("clocks a minute apart", (15, 36), (15, 37), False)
93-
, ("clocks an hour apart", (14, 37), (15, 37), False)
94-
, ("clocks with hour overflow", (10, 37), (34, 37), True)
95-
, ("clocks with hour overflow by several days", (3, 11), (99, 11), True)
96-
, ("clocks with negative hour", (22, 40), ((-2), 40), True)
97-
, ("clocks with negative hour that wraps", (17, 3), ((-31), 3), True)
98-
, ("clocks with negative hour that wraps multiple times", (13, 49), ((-83), 49), True)
99-
, ("clocks with minute overflow", (0, 1), (0, 1441), True)
100-
, ("clocks with minute overflow by several days", (2, 2), (2, 4322), True)
101-
, ("clocks with negative minute", (2, 40), (3, (-20)), True)
102-
, ("clocks with negative minute that wraps", (4, 10), (5, (-1490)), True)
103-
, ("clocks with negative minute that wraps multiple times", (6, 15), (6, (-4305)), True)
104-
, ("clocks with negative hours and minutes", (7, 32), ((-12), (-268)), True)
105-
, ("clocks with negative hours and minutes that wrap", (18, 7), ((-54), (-11513)), True)
106-
]
53+
assertion = fromHourMin h1 m1 == fromHourMin h2 m2 `shouldBe` e
54+
55+
createCases =
56+
[ ("on the hour" , 8, 0, "08:00")
57+
, ("past the hour" , 11, 9, "11:09")
58+
, ("midnight is zero hours" , 24, 0, "00:00")
59+
, ("hour rolls over" , 25, 0, "01:00")
60+
, ("hour rolls over continuously" , 100, 0, "04:00")
61+
, ("sixty minutes is next hour" , 1, 60, "02:00")
62+
, ("minutes roll over" , 0, 160, "02:40")
63+
, ("minutes roll over continuously" , 0, 1723, "04:43")
64+
, ("hour and minutes roll over" , 25, 160, "03:40")
65+
, ("hour and minutes roll over continuously" , 201, 3001, "11:01")
66+
, ("hour and minutes roll over to exactly midnight" , 72, 8640, "00:00")
67+
, ("negative hour" , -1, 15, "23:15")
68+
, ("negative hour rolls over" , -25, 0, "23:00")
69+
, ("negative hour rolls over continuously" , -91, 0, "05:00")
70+
, ("negative minutes" , 1, -40, "00:20")
71+
, ("negative minutes roll over" , 1, -160, "22:20")
72+
, ("negative minutes roll over continuously" , 1, -4820, "16:40")
73+
, ("negative hour and minutes both roll over" , -25, -160, "20:20")
74+
, ("negative hour and minutes both roll over continuously", -121, -5810, "22:10") ]
75+
76+
addCases =
77+
[ ("add minutes" , 10, 0, 3, "10:03")
78+
, ("add no minutes" , 6, 41, 0, "06:41")
79+
, ("add to next hour" , 0, 45, 40, "01:25")
80+
, ("add more than one hour" , 10, 0, 61, "11:01")
81+
, ("add more than two hours with carry" , 0, 45, 160, "03:25")
82+
, ("add across midnight" , 23, 59, 2, "00:01")
83+
, ("add more than one day (1500 min = 25 hrs)" , 5, 32, 1500, "06:32")
84+
, ("add more than two days" , 1, 1, 3500, "11:21")
85+
, ("subtract minutes" , 10, 3, -3, "10:00")
86+
, ("subtract to previous hour" , 10, 3, -30, "09:33")
87+
, ("subtract more than an hour" , 10, 3, -70, "08:53")
88+
, ("subtract across midnight" , 0, 3, -4, "23:59")
89+
, ("subtract more than two hours" , 0, 0, -160, "21:20")
90+
, ("subtract more than two hours with borrow" , 6, 15, -160, "03:35")
91+
, ("subtract more than one day (1500 min = 25 hrs)", 5, 32, -1500, "04:32")
92+
, ("subtract more than two days" , 2, 20, -3000, "00:20") ]
93+
94+
equalCases =
95+
[ ("clocks with same time" , (15, 37), ( 15, 37), True )
96+
, ("clocks a minute apart" , (15, 36), ( 15, 37), False)
97+
, ("clocks an hour apart" , (14, 37), ( 15, 37), False)
98+
, ("clocks with hour overflow" , (10, 37), ( 34, 37), True )
99+
, ("clocks with hour overflow by several days" , ( 3, 11), ( 99, 11), True )
100+
, ("clocks with negative hour" , (22, 40), ( -2, 40), True )
101+
, ("clocks with negative hour that wraps" , (17, 3), (-31, 3), True )
102+
, ("clocks with negative hour that wraps multiple times" , (13, 49), (-83, 49), True )
103+
, ("clocks with minute overflow" , ( 0, 1), ( 0, 1441), True )
104+
, ("clocks with minute overflow by several days" , ( 2, 2), ( 2, 4322), True )
105+
, ("clocks with negative minute" , ( 2, 40), ( 3, -20), True )
106+
, ("clocks with negative minute that wraps" , ( 4, 10), ( 5, -1490), True )
107+
, ("clocks with negative minute that wraps multiple times", ( 6, 15), ( 6, -4305), True )
108+
, ("clocks with negative hours and minutes" , ( 7, 32), (-12, -268), True )
109+
, ("clocks with negative hours and minutes that wrap" , (18, 7), (-54, -11513), True ) ]

0 commit comments

Comments
 (0)