Is it possible to skip tests in HSpec test suite? - haskell

In most programming languages it is easy to skip a test in some circumstances. Is there a proper way to do that in haskell HSpec based test suite?

"Changing it to xit marks the corresponding spec item as pending."
source:
http://hackage.haskell.org/package/hspec-2.7.8/docs/Test-Hspec.html

If I understand correctly, Core of HSpec doesn't have a special solution for this case. But you can skip tests without verbosity about it. For example:
main = hspec $ do
...
when isDatabaseServerRunning $ do
describe "database" $ do
it "test some one" $ do
...
Another solution maybe to use the function like mapSpecItem_ for changing result of test to Pending with a message about why was skipped. For example:
skip :: String -> Bool -> SpecWith a -> SpecWith a
skip _ False = id
skip why True = mapSpecItem_ updateItem
where
updateItem x = x{itemExample = \_ _ _ -> return . Pending . Just $ why}

Related

Conduit Exception

I couldn't figure out how to make sourceDirectory and catchC work.
src = (sourceDirectory "/does/not/exist/input.txt" $$ C.print) `catchC` \e ->
yield (pack $ "Could not read input file: " ++ show (e :: IOException))
The idea is that I use sourceDirectory to walk a directory tree and in case of failure I want the program to continue and not stop.
The catchC function works on individual components of a pipeline, like sourceDirectory "somedir" (in other words, things of type ConduitM). You've applied it to a completely run pipeline, which is just a normal action, and therefore catchC won't work. Your choices are:
Apply catchC to the individual component, e.g. (sourceDirectory "foo" `catchC` handler) $$ printC
Use a non-conduit-specific catch function (such as from safe-exceptions), e.g. (sourceDirectory "foo" $$ printC) `catch` handler.
Also, a recommendation for the future: it's a good idea to include the compiler error when some code won't build.

PutText in haskell HUnit

I have recently been using the HUnit testing framework to run unit
tests in haskell.
I came across this function PutText and runTestText which takes
PutText st as its first argument.
However i am not sure how to use this and would like some help in understanding how to use this?
A PutText value allows you to customize the way to messages generated from running a test are reported.
A simple way to create one is use putTextToHandle stdout True to output messages to standard out. The True parameter means to also emit progress messages.
The PutText protocol allows you to maintain state. This is an example of one that keeps track of the number of messages emitted. The final value
of this state is also returned by runTestText as the second component
of the returned tuple.
reportMsg :: String -> Bool -> Int -> IO Int
reportMsg message isProgress count = do
putStrLn $ "#" ++ show (count+1) ++ ": " ++ message
return (count+1)
myPutText = PutText reportMsg 0 :: PutText Int
And then you can use it like this:
(testCounts, msgCount) <- runTestText myPutText tests
putStrLn $ "Messages emitted: " ++ show msgCount
Here testCounts is a tally of the number of tests which were run / passed / failed / etc. The msgCount is the value returned by the last call to the PutText function.

How can QuickCheck test all properties for each sample

...instead of generating 100 new random samples for each property?
My testsuite contains the TemplateHaskell hack explained here [1] to
test all functions named prop_*. Running the test program prints
=== prop_foo from tests/lala.lhs:20 ===
+++ OK, passed 100 tests.
=== prop_bar from tests/lala.lhs:28 ===
+++ OK, passed 100 tests.
and it looks like going through 100 random samples for each of the
properties.
Problemis: Generating the samples is quite expensive, checking the
properties is not. So I'd like to have a means to pass each random
sample to each of the prop_* functions instead of creating new
(#properties * 100) many samples.
Is there anything like that built in? Actually, I think I'd need a
replacement for the splice
$(forAllProperties)
in
main :: IO ()
main
= do args <- parseArgs <$> getArgs
s <- $(forAllProperties) $ quickCheckWithResult args
s ? return () $ exitFailure
where
parseArgs as
= null as ? stdArgs $ stdArgs{ maxSuccess = read $ head as }
[1] Simple haskell unit testing, and
QuickCheck exit status on failures, and cabal integration
In this post you can see how to group tests
Stackoverflow post
That user provides a very simple example of use Test.Tasty.QuickCheck
Using testProperty and testGroup you can pass each random sample to each property
In the next link you can check the hackage of this package
Test.Tasty.QuickCheck

unreadable quickcheck log file after a test routine

I made a test routine for a Haskell program with quickcheck. I declared it in my cabal file with :
Test-Suite routine_de_test
Type: exitcode-stdio-1.0
Hs-Source-Dirs: test
Main-is: Tests.hs
and launched it with :
cabal configure --enable-tests
cabal buil
cabal test
The tests are processed correctly and I was expecting to see details about the random value used for each test in the log file dist/test/ but when I open it, the file looks like this :
I tried to open the file with several encoding (UTF8, ISO-8859-15, ...) but nothing is changed.
Is it normal? Or is there something wrong?
Is it possible when performing quickcheck test from cabal to get the complete list of random values used for each tests?
It looks like the funny characters are simply backspaces, and quickcheck is simply reporting the number of tests it has performed so far by overwriting (0 tests) with (1 test) and then (2 tests) and then with (3 tests), etc.
Visually it will look fine when displayed to a terminal.
Update:
To report the random values used for a test the only way I know of is to write your test to explicitly display (or save to a file) the values used.
If your test is a pure function you can use the trace function from Debug.Trace. For instance, if you have this property:
prop_commutes :: Int -> Int -> Bool
prop_commutes a b = a + b == b + a
You can trace each invocation of prop_commutes by modifying like this:
import Debug.Trace
prop_commutes :: Int -> Int -> Bool
prop_commutes x y = a + b == b + a
where (a,b) = trace ("(a,b) = " ++ show (x,y)) (x,y)
and then quickCheck prop_commutes will emit lines like:
(x,y) = (20,-73)
(x,y) = (71,-36)
(x,y) = (2,-11)
...
in addition to its normal output.

Unsafe IO Or: Haskeline and Directories

DISCLAIMER: I am somewhat new to Haskell.
I am writing an interpreter, or, in this context, a REPL. For that purpose I am using haskeline, which is nice for REPLs. It has the capability of storing the command line history within a file, which is also nice.
One problem I came across while working with it, though, is that it does not seem to expand "~" to the home directory, which means that I have to retrieve the home directory manually.
I could do it like this (and currently do):
-- | returns a fresh settings variable
addSettings :: Env -> Settings IO
addSettings env = Settings { historyFile = Just getDir
, complete = completeWord Nothing " \t" $
return . completionSearch env
, autoAddHistory = True
}
where
getDir :: FilePath
getDir = unsafePerformIO getHomeDirectory ++ "/.zepto_history"
But that uses unsafePerformIO, which makes me cringe. Do you know of a good and clean workaround that does not involve rewriting the whole function? This can be a haskeline feature I do not know of or something I just did not see.
Telling me there is no way around rewriting and rethinking it all is fine, too.
EDIT:
I know unsafePerformIO is bad, that's why it makes me cringe. If you are new to Haskell and reading this question right now: Just pretend it is not there.
A better approach would be to generate the Settings object inside IO, instead of the other way around, so to speak:
addSettings :: Env -> IO (Settings IO)
addSettings = do
getDir <- fmap (++ "/.zepto_history") getHomeDirectory
return $ Settings
{ historyFile = Just getDir
, complete = completeWord Nothing " \t" $ return . completionSearch env
, autoAddHistory = True
}
This will no doubt require some changes in your current software, but this would be considered the "right" way to go about this.

Resources