SO question 13350164 How do I test for an error in Haskell? に基づく 、無効な入力が与えられた場合、再帰関数が例外を発生させることをアサートする単体テストを作成しようとしています。私が採用したアプローチは、非再帰関数 (または最初の呼び出しで例外が発生した場合) にはうまく機能しますが、例外が呼び出しチェーンの奥深くで発生するとすぐに、アサーションは失敗します。
質問 6537766 Haskell のエラー処理へのアプローチに対する優れた回答を読みましたが、残念ながら、私の学習曲線のこの時点ではアドバイスが一般的すぎます。ここでの問題は、遅延評価と非純粋なテスト コードに関連していると思いますが、専門家の説明をいただければ幸いです。
Maybe
このような状況 (例:や) では、エラー処理に別のアプローチを採用するEither
必要がありますか? または、このスタイルを使用しているときにテスト ケースを正しく動作させるための適切な修正方法はありますか?
これが私が思いついたコードです。最初の 2 つのテスト ケースは成功しますが、3 番目のテスト ケースは で失敗し"Received no exception, but was expecting exception: Negative item"
ます。
import Control.Exception (ErrorCall(ErrorCall), evaluate)
import Test.HUnit.Base ((~?=), Test(TestCase, TestList))
import Test.HUnit.Text (runTestTT)
import Test.HUnit.Tools (assertRaises)
sumPositiveInts :: [Int] -> Int
sumPositiveInts [] = error "Empty list"
sumPositiveInts (x:[]) = x
sumPositiveInts (x:xs) | x >= 0 = x + sumPositiveInts xs
| otherwise = error "Negative item"
instance Eq ErrorCall where
x == y = (show x) == (show y)
assertError msg ex f =
TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f
tests = TestList [
assertError "Empty" "Empty list" (sumPositiveInts ([]))
, assertError "Negative head" "Negative item" (sumPositiveInts ([-1, -1]))
, assertError "Negative second item" "Negative item" (sumPositiveInts ([1, -1]))
]
main = runTestTT tests