My impure functions are defined as follows:
module HangmanImpure (HangmanImpure.getLine, HangmanImpure.putStr, HangmanImpure.putStrLn, HangmanImpure.strlen) where
import qualified System.IO as Sys
getLine :: IO String
getLine = do x <- Sys.getChar
if x == '\n' then
return []
else
do xs <- HangmanImpure.getLine
return (x:xs)
putStr :: String -> IO ()
putStr [] = return ()
putStr (x:xs) = do Sys.putChar x
HangmanImpure.putStr xs
I want to test these functions using Tasty, like e.g. so:
module TestHangmanImpure (scProps) where
import qualified Test.Tasty as T
import qualified Test.Tasty.SmallCheck as SC
import qualified HangmanImpure as HI (getLine, putStr, putStrLn, strlen)
scProps :: T.TestTree
scProps = T.testGroup "checked by SmallCheck"
[
SC.testProperty "getLine should return what is written to stdin" $
"Placeholder to get the test to run" == "Placeholder to get the test to run" -- HI.getLine == IO "Hello" -- PLEASE, HELP ME WITH SOME CONTENT HERE
, SC.testProperty "putStr should write to stdout what it gets in as an argument" $
"Placeholder to get the test to run" == "Placeholder to get the test to run" -- HI.putStr "Nice day!" -- PLEASE, HELP ME WITH SOME CONTENT HERE
]
I would be very thankful if anybody could fill in the body in the two simple tests I have indicated.
EDIT:
I think [In haskell, how can I interact with stdin of an IO ()?][1] could lead me to a solution. I can get that solution to work on my Win10 with HSpec. So this question is almost a duplicate. But I cannot get it to work using Tasty.HUnit. My tentative code runs as follows:
module TestUtilImpure (scProps, qcProps, uTests, properties) where
import qualified Test.Tasty as T
import qualified Test.Tasty.HUnit as HU
import StdInStdOutUtil as IOU (captureStdout, provideStdin)
import UtilImpure as UI (getLine)
properties :: T.TestTree
properties = T.testGroup "TestUtilImpure tests" [
uTests
]
uTests :: T.TestTree
uTests = T.testGroup "Checked by HUnit"
[
HU.testCase "UI.getLine reading from stdin should return what was provided" $ do
let line = "Hello, echo!\n"
let capturedIOString = IOU.captureStdout (provideStdin line echo)
capturedString <- capturedIOString
HU.assertBool "The String returned from UI.getLine differs from the one provided for StdIn" $ capturedString == line
]
echo :: IO ()
echo = UI.getLine >>= Prelude.putStrLn
(I have put the solution from [1]: In haskell, how can I interact with stdin of an `IO ()`? into its own file referred by
import StdInStdOutUtil as IOU (captureStdout, provideStdin)
My test fails:
The String returned from UI.getLine differs from the one provided for StdIn
I get the same error message whether I test Prelude.getLine or my own UI.getLine. So I guess that there's some syntax I have not understood using Tasty that fails.
I am using Test.Tasty.HIOUnit to test IO functions.
At the moment, HIOUnit is only available as source code at https://github.com/JoergBrueggmann/tasty-hiounit.
A test spec with HIOUnit looks like this: