Skip to content

Commit 4d73f20

Browse files
authored
Merge pull request #297 from rbasso/hspec-simple-cipher
simple-cipher: Rewrite tests to use hspec with fail-fast.
2 parents 66c8f4c + 74bd6b1 commit 4d73f20

File tree

2 files changed

+56
-55
lines changed

2 files changed

+56
-55
lines changed

exercises/simple-cipher/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,4 @@ tests:
1717
source-dirs: test
1818
dependencies:
1919
- simple-cipher
20-
- HUnit
20+
- hspec

exercises/simple-cipher/test/Tests.hs

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,58 @@
1-
import Test.HUnit (Assertion, (@=?), runTestTT, Test(..), Counts(..))
2-
import System.Exit (ExitCode(..), exitWith)
3-
import Cipher (caesarEncode, caesarDecode, caesarEncodeRandom)
1+
import Test.Hspec (Spec, describe, it, shouldBe)
2+
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
43

5-
exitProperly :: IO Counts -> IO ()
6-
exitProperly m = do
7-
counts <- m
8-
exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess
9-
10-
testCase :: String -> Assertion -> Test
11-
testCase label assertion = TestLabel label (TestCase assertion)
4+
import Cipher (caesarDecode, caesarEncode, caesarEncodeRandom)
125

136
main :: IO ()
14-
main = exitProperly $ runTestTT $ TestList
15-
[ TestList caesarTests ]
16-
17-
caesarTests :: [Test]
18-
caesarTests =
19-
[ testCase "no-op encode" $ do
20-
['a'..'z'] @=? caesarEncode "a" ['a'..'z']
21-
['a'..'z'] @=? caesarEncode (repeat 'a') ['a'..'z']
22-
, testCase "no-op decode" $ do
23-
['a'..'z'] @=? caesarDecode "a" ['a'..'z']
24-
['a'..'z'] @=? caesarDecode (repeat 'a') ['a'..'z']
25-
, testCase "reversible" $ do
26-
let k0 = "alkjsdhflkjahsuid"
27-
"asdf" @=? caesarDecode k0 (caesarEncode k0 "asdf")
28-
let k1 = ['z','y'..'a']
29-
"asdf" @=? caesarDecode k1 (caesarEncode k1 "asdf")
30-
, testCase "known cipher" $ do
31-
let k = ['a'..'j']
32-
encode = caesarEncode k
33-
decode = caesarDecode k
34-
k @=? encode "aaaaaaaaaa"
35-
"aaaaaaaaaa" @=? decode k
36-
['a'..'z'] @=? decode (encode ['a'..'z'])
37-
'z':['a'..'i'] @=? encode "zzzzzzzzzz"
38-
, testCase "double shift" $ do
39-
let plaintext = "iamapandabear"
40-
ciphertext = "qayaeaagaciai"
41-
ciphertext @=? caesarEncode plaintext plaintext
42-
, testCase "shift cipher" $ do
43-
let encode = caesarEncode "d"
44-
decode = caesarDecode "d"
45-
"dddddddddd" @=? encode "aaaaaaaaaa"
46-
"aaaaaaaaaa" @=? decode "dddddddddd"
47-
['d'..'m'] @=? encode ['a'..'j']
48-
['a'..'j'] @=? decode (encode ['a'..'j'])
49-
, testCase "random tests" $ do
50-
let plaintext = take 1000 (cycle ['a'..'z'])
51-
p1 <- caesarEncodeRandom plaintext
52-
plaintext @=? uncurry caesarDecode p1
53-
p2 <- caesarEncodeRandom plaintext
54-
plaintext @=? uncurry caesarDecode p2
55-
-- There's a small chance this could fail, since it's random.
56-
False @=? (p1 == p2)
57-
]
7+
main = hspecWith defaultConfig {configFastFail = True} specs
8+
9+
specs :: Spec
10+
specs = describe "simple-cipher" $ do
11+
12+
-- As of 2016-09-16, there was no reference file
13+
-- for the test cases in `exercism/x-common`.
14+
15+
it "no-op encode" $ do
16+
caesarEncode "a" ['a'..'z'] `shouldBe` ['a'..'z']
17+
caesarEncode (repeat 'a') ['a'..'z'] `shouldBe` ['a'..'z']
18+
19+
it "no-op decode" $ do
20+
caesarDecode "a" ['a'..'z'] `shouldBe` ['a'..'z']
21+
caesarDecode (repeat 'a') ['a'..'z'] `shouldBe` ['a'..'z']
22+
23+
it "reversible" $ do
24+
let k0 = "alkjsdhflkjahsuid"
25+
k1 = ['z','y'..'a']
26+
caesarDecode k0 (caesarEncode k0 "asdf") `shouldBe` "asdf"
27+
caesarDecode k1 (caesarEncode k1 "asdf") `shouldBe` "asdf"
28+
29+
it "known cipher" $ do
30+
let k = ['a'..'j']
31+
encode = caesarEncode k
32+
decode = caesarDecode k
33+
encode "aaaaaaaaaa" `shouldBe` k
34+
decode k `shouldBe` "aaaaaaaaaa"
35+
decode (encode ['a'..'z']) `shouldBe` ['a'..'z']
36+
encode "zzzzzzzzzz" `shouldBe` 'z':['a'..'i']
37+
38+
it "double shift" $ do
39+
let plaintext = "iamapandabear"
40+
ciphertext = "qayaeaagaciai"
41+
caesarEncode plaintext plaintext `shouldBe` ciphertext
42+
43+
it "shift cipher" $ do
44+
let encode = caesarEncode "d"
45+
decode = caesarDecode "d"
46+
encode "aaaaaaaaaa" `shouldBe` "dddddddddd"
47+
decode "dddddddddd" `shouldBe` "aaaaaaaaaa"
48+
encode ['a'..'j'] `shouldBe` ['d'..'m']
49+
decode (encode ['a'..'j']) `shouldBe` ['a'..'j']
50+
51+
it "random tests" $ do
52+
let plaintext = take 1000 (cycle ['a'..'z'])
53+
p1 <- caesarEncodeRandom plaintext
54+
uncurry caesarDecode p1 `shouldBe` plaintext
55+
p2 <- caesarEncodeRandom plaintext
56+
uncurry caesarDecode p2 `shouldBe` plaintext
57+
-- There's a small chance this could fail, since it's random.
58+
(p1 == p2) `shouldBe` False

0 commit comments

Comments
 (0)