How to test my haskell functions
Asked Answered
P

6

5

I just started with Haskell and tried to do write some tests first. Basically, I want to define some function and than call this function to check the behavior.

add :: Integer -> Integer -> Integer
add a b = a+b

-- Test my function 
add 2 3

If I load that little script in Hugs98, I get the following error:

Syntax error in declaration (unexpected `}', possibly due to bad layout)

If I remove the last line, load the script and then type in "add 2 3" in the hugs interpreter, it works just fine.

So the question is: How can I put calls of my functions in the same script as the function definition? I just want to load the script and be able to check if it does what I expect it to...I don't want to type them in manually all the time.

Polymeric answered 13/10, 2011 at 8:19 Comment(0)
M
3

Make a top level definition:

add :: Integer -> Integer -> Integer
add a b = a + b

test1 = add 2 3

Then call test1 in your Hugs session.

Motivation answered 13/10, 2011 at 8:25 Comment(1)
Ok, this works fine. Thus, I could write a few tests like "test1=add 2 3 == 5" and then just use a conjunction of all the tests that must equal true.Polymeric
M
14

Others have said how to solve your immediate problem, but for testing you should be using QuickCheck or some other automated testing library.

import Test.QuickCheck
prop_5 = add 2 3 == 5
prop_leftIdentity n = add 0 n == n

Then run quickCheck prop_5 and quickCheck prop_leftIdentity in your Hugs session. QuickCheck can do a lot more than this, but that will get you started.

(Here's a QuickCheck tutorial but it's out of date. Anyone know of one that covers QuickCheck 2?)

Monopoly answered 13/10, 2011 at 8:40 Comment(2)
That's what I was about to propose. Though, it will require you make friends with type classes if you want to use it on custom data types, but it will pay quite fast!Arleta
Thanks for the tip. I'll look into it as soon as I' a bit more familiar with Haskell - I just started today :)Polymeric
H
8

the most beginner friendly way is probably the doctest module. Download it with "cabal install doctest", then put your code into a file "Add.hs" and run "doctest Add.hs" from the command line.

Your code should look like this, the formatting is important:

module Add where

-- | add adds two numbers
--
-- >>> add 2 3
-- 5
-- >>> add 5 0
-- 5
-- >>> add 0 0
-- 0
add :: Integer -> Integer -> Integer
add a b = a+b

HTH Chris

Hyperform answered 13/10, 2011 at 9:27 Comment(1)
this looks just the way I'd like it!Polymeric
M
3

Make a top level definition:

add :: Integer -> Integer -> Integer
add a b = a + b

test1 = add 2 3

Then call test1 in your Hugs session.

Motivation answered 13/10, 2011 at 8:25 Comment(1)
Ok, this works fine. Thus, I could write a few tests like "test1=add 2 3 == 5" and then just use a conjunction of all the tests that must equal true.Polymeric
T
2

How can I put calls of my functions in the same script as the function definition? I just want to load the script and be able to check if it does what I expect it to...I don't want to type them in manually all the time.

In short, you can't. Wrap it in a function and call it instead. Your file serves as a valid Haskell module, and having "flying" expression is not a valid way to write it.

You seem to come from a scripting language background, but don't try treating Haskell as one of them.

Trevortrevorr answered 13/10, 2011 at 8:27 Comment(0)
A
0

If you have ghc installed, then the runhaskell command will interpret and run the main function in your file.

add x y = x + y
main = print $ add 2 3

Then on the command line

> runhaskell Add.hs
5

Not sure, but hugs probably has a similar feature to the runhaskell command. Or, if you load the file into the hugs interpreter, you can simply run it by calling main.

Archfiend answered 13/10, 2011 at 22:39 Comment(0)
F
0

I was trying to do the same thing and I just made a function that ran through all my test cases (using guards) and returned 1 if they all passed and threw an error if any failed.

test :: Num b => a->b
test x
      | sumALL [1]            /= 1 = error "test failed"
      | sumALL [0,1,2]      /= 3 = error "test failed"
      ...
      | otherwise = 1

Flabellum answered 17/4, 2020 at 21:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.