Skip to content

Commit a1b6e6d

Browse files
authored
Merge pull request #388 from rbasso/hspec-forth
forth: Rewrite tests to use hspec with fail-fast.
2 parents ea73a3f + c7ab053 commit a1b6e6d

File tree

2 files changed

+74
-70
lines changed

2 files changed

+74
-70
lines changed

exercises/forth/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ tests:
1818
source-dirs: test
1919
dependencies:
2020
- forth
21-
- HUnit
21+
- hspec

exercises/forth/test/Tests.hs

Lines changed: 73 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,78 @@
11
{-# LANGUAGE OverloadedStrings #-}
2-
import Test.HUnit (Assertion, (@=?), runTestTT, Test(..), Counts(..))
3-
import System.Exit (ExitCode(..), exitWith)
4-
import Forth (ForthError(..), evalText, empty, formatStack)
5-
import Control.Monad (foldM)
6-
import Data.Text (Text)
72

8-
exitProperly :: IO Counts -> IO ()
9-
exitProperly m = do
10-
counts <- m
11-
exitWith $ if failures counts /= 0 || errors counts /= 0 then ExitFailure 1 else ExitSuccess
3+
import Control.Monad (foldM)
4+
import Test.Hspec (Spec, describe, it, shouldBe)
5+
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
126

13-
testCase :: String -> Assertion -> Test
14-
testCase label assertion = TestLabel label (TestCase assertion)
7+
import Forth (ForthError(..), empty, evalText, formatStack)
158

169
main :: IO ()
17-
main = exitProperly $ runTestTT $ TestList
18-
[ TestList forthTests ]
19-
20-
runTexts :: [Text] -> Either ForthError Text
21-
runTexts xs = formatStack <$> foldM (flip evalText) empty xs
22-
23-
forthTests :: [Test]
24-
forthTests =
25-
[ testCase "no input, no stack" $
26-
"" @=? formatStack empty
27-
, testCase "numbers just get pushed onto the stack" $
28-
Right "1 2 3 4 5" @=? runTexts ["1 2 3 4 5"]
29-
, testCase "non-word characters are separators" $
30-
-- Note the Ogham Space Mark ( ), this is a spacing character.
31-
Right "1 2 3 4 5 6 7" @=? runTexts ["1\NUL2\SOH3\n4\r5 6\t7"]
32-
, testCase "basic arithmetic" $ do
33-
Right "-1" @=? runTexts ["1 2 + 4 -"]
34-
Right "2" @=? runTexts ["2 4 * 3 /"]
35-
, testCase "division by zero" $
36-
Left DivisionByZero @=? runTexts ["4 2 2 - /"]
37-
, testCase "dup" $ do
38-
Right "1 1" @=? runTexts ["1 DUP"]
39-
Right "1 2 2" @=? runTexts ["1 2 Dup"]
40-
Left StackUnderflow @=? runTexts ["dup"]
41-
, testCase "drop" $ do
42-
Right "" @=? runTexts ["1 drop"]
43-
Right "1" @=? runTexts ["1 2 drop"]
44-
Left StackUnderflow @=? runTexts ["drop"]
45-
, testCase "swap" $ do
46-
Right "2 1" @=? runTexts ["1 2 swap"]
47-
Right "1 3 2" @=? runTexts ["1 2 3 swap"]
48-
Left StackUnderflow @=? runTexts ["1 swap"]
49-
Left StackUnderflow @=? runTexts ["swap"]
50-
, testCase "over" $ do
51-
Right "1 2 1" @=? runTexts ["1 2 over"]
52-
Right "1 2 3 2" @=? runTexts ["1 2 3 over"]
53-
Left StackUnderflow @=? runTexts ["1 over"]
54-
Left StackUnderflow @=? runTexts ["over"]
55-
, testCase "defining a new word" $
56-
Right "1 1 1" @=? runTexts [ ": dup-twice dup dup ;"
57-
, "1 dup-twice"
58-
]
59-
, testCase "redefining an existing word" $
60-
Right "1 1 1" @=? runTexts [ ": foo dup ;"
61-
, ": foo dup dup ;"
62-
, "1 foo"
63-
]
64-
, testCase "redefining an existing built-in word" $
65-
Right "1 1" @=? runTexts [ ": swap dup ;"
66-
, "1 swap"
67-
]
68-
, testCase "defining words with odd characters" $
69-
Right "220371" @=? runTexts [": € 220371 ; €"]
70-
, testCase "defining a number" $
71-
Left InvalidWord @=? runTexts [": 1 2 ;"]
72-
, testCase "calling a non-existing word" $
73-
Left (UnknownWord "foo") @=? runTexts ["1 foo"]
74-
]
10+
main = hspecWith defaultConfig {configFastFail = True} specs
11+
12+
specs :: Spec
13+
specs = describe "forth" $ do
14+
15+
-- As of 2016-10-02, there was no reference file
16+
-- for the test cases in `exercism/x-common`.
17+
18+
let runTexts = fmap formatStack . foldM (flip evalText) empty
19+
20+
it "no input, no stack" $
21+
formatStack empty `shouldBe` ""
22+
23+
it "numbers just get pushed onto the stack" $
24+
runTexts ["1 2 3 4 5"] `shouldBe` Right "1 2 3 4 5"
25+
26+
it "non-word characters are separators" $
27+
runTexts ["1\NUL2\SOH3\n4\r5 6\t7"] `shouldBe` Right "1 2 3 4 5 6 7"
28+
29+
it "basic arithmetic" $ do
30+
runTexts ["1 2 + 4 -"] `shouldBe` Right "-1"
31+
runTexts ["2 4 * 3 /"] `shouldBe` Right "2"
32+
33+
it "division by zero" $
34+
runTexts ["4 2 2 - /"] `shouldBe` Left DivisionByZero
35+
36+
it "dup" $ do
37+
runTexts ["1 DUP" ] `shouldBe` Right "1 1"
38+
runTexts ["1 2 Dup"] `shouldBe` Right "1 2 2"
39+
runTexts ["dup" ] `shouldBe` Left StackUnderflow
40+
41+
it "drop" $ do
42+
runTexts ["1 drop" ] `shouldBe` Right ""
43+
runTexts ["1 2 drop"] `shouldBe` Right "1"
44+
runTexts ["drop" ] `shouldBe` Left StackUnderflow
45+
46+
it "swap" $ do
47+
runTexts ["1 2 swap" ] `shouldBe` Right "2 1"
48+
runTexts ["1 2 3 swap"] `shouldBe` Right "1 3 2"
49+
runTexts ["1 swap" ] `shouldBe` Left StackUnderflow
50+
runTexts ["swap" ] `shouldBe` Left StackUnderflow
51+
52+
it "over" $ do
53+
runTexts ["1 2 over" ] `shouldBe` Right "1 2 1"
54+
runTexts ["1 2 3 over"] `shouldBe` Right "1 2 3 2"
55+
runTexts ["1 over" ] `shouldBe` Left StackUnderflow
56+
runTexts ["over" ] `shouldBe` Left StackUnderflow
57+
58+
it "defining a new word" $
59+
runTexts [ ": dup-twice dup dup ;"
60+
, "1 dup-twice" ] `shouldBe` Right "1 1 1"
61+
62+
it "redefining an existing word" $
63+
runTexts [ ": foo dup ;"
64+
, ": foo dup dup ;"
65+
, "1 foo" ] `shouldBe` Right "1 1 1"
66+
67+
it "redefining an existing built-in word" $
68+
runTexts [ ": swap dup ;"
69+
, "1 swap" ] `shouldBe` Right "1 1"
70+
71+
it "defining words with odd characters" $
72+
runTexts [": € 220371 ; €"] `shouldBe` Right "220371"
73+
74+
it "defining a number" $
75+
runTexts [": 1 2 ;"] `shouldBe` Left InvalidWord
76+
77+
it "calling a non-existing word" $
78+
runTexts ["1 foo"] `shouldBe` Left (UnknownWord "foo")

0 commit comments

Comments
 (0)