How to check a bug in Haskell?

I want to make sure that the function will cause an error when it is received and an invalid value. For example, let it say that I have a pos function that returns only a positive number:

pos :: Int -> Int pos x | x >= 0 = x | otherwise = error "Invalid Input" 

This is a simplified example, but I hope you get this idea.

I want to be able to write a test case that will expect errors and consider it a passing test. For example:

 tests = [pos 1 == 1, assertError pos (-1), pos 2 == 2, assertError pos (-2)] runTests = all (== True) tests 

[My decision]

Here's what I ended up based on @hammar's comment.

 instance Eq ErrorCall where x == y = (show x) == (show y) assertException :: (Exception e, Eq e) => e -> IO a -> IO () assertException ex action = handleJust isWanted (const $ return ()) $ do action assertFailure $ "Expected exception: " ++ show ex where isWanted = guard . (== ex) assertError ex f = TestCase $ assertException (ErrorCall ex) $ evaluate f tests = TestList [ (pos 0) ~?= 0 , (pos 1) ~?= 1 , assertError "Invalid Input" (pos (-1)) ] main = runTestTT tests 
+7
source share
2 answers

The OP solution defines an assertException , but it looks like Test.HUnit.Tools.assertRaises from testpack can also be used here.

I added the msg argument to assertError to match how assertRaises works and assertRaises selective import so that noobs like me can find out where things usually come from.

 import Control.Exception (ErrorCall(ErrorCall), evaluate) import Test.HUnit.Base ((~?=), Test(TestCase, TestList)) import Test.HUnit.Text (runTestTT) import Test.HUnit.Tools (assertRaises) pos :: Int -> Int pos x | x >= 0 = x | otherwise = error "Invalid Input" instance Eq ErrorCall where x == y = (show x) == (show y) assertError msg ex f = TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f tests = TestList [ (pos 0) ~?= 0 , (pos 1) ~?= 1 , assertError "Negative argument raises an error" "Invalid Input" (pos (-1)) ] main = runTestTT tests 
+3
source

There are several ways to handle errors in Haskell. Here is a review: http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors

[change]

The first example shows how to catch errors, for example

 half :: Int -> Int half x = if even x then x `div` 2 else error "odd" main = do catch (print $ half 23) (\err -> print err) 

However, this error handling is better suited for IO things, in clean code like yours. Maybe, or something like that, usually the best choice. It can be as simple as ...

 pos :: Int -> Maybe Int pos x | x >= 0 = Just x | otherwise = Nothing tests = [pos 1 == Just 1 ,pos (-1) == Nothing ,pos 2 == Just 2 ,pos (-2) == Nothing ] main = print $ and tests 

... if you do not need the type of error.

0
source

All Articles