Haskell で電卓アプリを作った際のテストコードの書き方を紹介します。この記事は連載記事「Haskell初心者が電卓アプリを作る」の4回目の記事です。
- 「Haskell初心者が電卓アプリを作る : 1」
- 「GUIと計算部分の実装 (Haskell初心者が電卓アプリを作る : 2)」
- 「Haskellでstateパターンを実装する (Haskell初心者が電卓アプリを作る : 3)」
- 「hspecでHaskellのテストコードを書く (Haskell初心者が電卓アプリを作る : 4)」← 今ここ
ソースコードは以下にアップしています。
https://github.com/daikon-oroshi/haskell-calculator-sample
準備
package.yaml の test の dependencies に hspec を追加します。
...
tests:
calculator-test:
main: Spec.hs
source-dirs: test
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- calculator
- hspec
次に test/Spec.hs に 1 行だけ記載します。
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
テストコードの書き方
ファイル名を xxxSpec.hs とします。今回は ExpNotation をテストするので ExpNotationSpec.hs という名前にします。以下の様に spec という関数を定義し spec を export します。
module ExpNotationSpec (spec) where
import Test.Hspec ( describe, it, shouldBe, Spec, Expectation )
spec :: Spec
spec = do
describe "表示(display)のテスト" $ do
it "1の表示" $
display unitDispVal `shouldBe` "1"
it "-1の表示" $
display (unitDispVal {_significand = -1}) `shouldBe` "-1"
describe "addDigitのテスト" $ do
it "0に追加" $
display (addDigit zeroDispVal 3) `shouldBe` "3"
it "1に1を追加" $
display (addDigit unitDispVal 1) `shouldBe` "11"
以下の様に書くこともできます。
module ExpNotationSpec (spec) where
import Test.Hspec ( describe, it, shouldBe, Spec, Expectation )
testDisplay :: ExpNotation -> String -> Expectation
testDisplay val _exp = display val `shouldBe` _exp
testAddDigit :: (ExpNotation, Int) -> String -> Expectation
testAddDigit (dv, num) _epx = display (addDigit dv num) `shouldBe` _epx
tests :: [(String, [(String, Expectation)])]
tests = [
("表示(display)のテスト", [
("1の表示", testDisplay unitDispVal "1")
, ("-1の表示", testDisplay (unitDispVal {_significand = -1}) "-1"
])
, ("addDigitのテスト",[
("0に追加", testAddDigit (zeroDispVal, 3) "3")
, ("1に1を追加", testAddDigit (unitDispVal, 1) "11")
] )
]
spec :: Spec
spec = do
mapM_ (\(n, p) ->
describe n $ do
mapM_ (uncurry it) p
) tests
実行
テストファイル名を xxxSpec.hs という名前で作成し、
stack test
または
stack build --test
を実行すると、test/ 以下のファイルが全て実行されます。
実行結果
実行結果は以下のように出力されます。
ExpNotation
表示(display)のテスト
1の表示 [✔]
-1の表示 [✔]
0. の表示 [✔]
0.00 の表示 [✔]
91. の表示 [✔]
9.1 の表示 [✘]
-91. の表示 [✔]
addDigitのテスト
0に追加 [✔]
1に1を追加 [✔]
掛け算のテスト
5 * 9 [✔]
足し算のテスト
0と1の足し算 [✔]
MExpNotation
表示(display)のテスト
Nothing [✔]
1 [✔]
addDigitのテスト
Nothingに追加 [✔]
1に追加 [✔]
掛け算のテスト
5 * 9 [✔]
5 * Nothin [✔]
Nothing * 9 [✔]
Nothing * Nothing [✔]
足し算のテスト
0と1の足し算 [✔]
Nothing + 1 [✔]
0 + Nothing [✔]
Nothing + Nothing [✔]
割り算のテスト
1 / 2 [✔]
1 / 0 [✔]
Nothing / 2 [✔]
1 / Nothing [✔]
Nothing / Nothing [✔]
Failures:
test/ExpNotationSpec.hs:22:36:
1) ExpNotation.表示(display)のテスト 9.1 の表示
expected: "9.11"
but got: "9.1"
To rerun use: --match "/ExpNotation/表示(display)のテスト/9.1 の表示/"
Randomized with seed 1499174619
Finished in 0.0078 seconds
47 examples, 1 failure
ご支援のお願い
記事を読んで、「支援してもいいよ」と思っていただけましたら、ご支援いただけると幸いです。サーバー維持費などに充てさせていただきます。登録不要で、100円から寄付でき、金額の90%がクリエイターに届きます。