For a similar problem, but which also redirects the standard input, I am using the following code for testing a student assignment.
import Control.Applicative (liftA2)
import Control.Exception (bracket, finally)
import GHC.IO.Handle (hDuplicate, hDuplicateTo)
import System.IO (stdin, stdout, withFile, IOMode(ReadMode, WriteMode), hClose)
import System.IO.Temp (writeSystemTempFile, emptySystemTempFile)
redirect action inputFileName outputFileName = do
withFile inputFileName ReadMode $ \hIn ->
withFile outputFileName WriteMode $ \hOut ->
bracket
(liftA2 (,) (hDuplicate stdin) (hDuplicate stdout))
(\(old_stdin, old_stdout) ->
(hDuplicateTo old_stdin stdin >> hDuplicateTo old_stdout stdout)
`finally`
(hClose old_stdin >> hClose old_stdout))
(\_ ->
do
hDuplicateTo hIn stdin
hDuplicateTo hOut stdout
action)
runWithInput action input = do
inputFileName <- writeSystemTempFile "input.txt" input
outputFileName <- emptySystemTempFile "output.txt"
redirect action inputFileName outputFileName
readFile outputFileName
module Main (main) where
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck.Modifiers
import Run
import qualified StudentMainModule as T -- read a sequence of numbers and write its sum
main :: IO ()
main = hspec $ do
describe "Executando o programa" $ do
it "com quantidade negativa" $ do
let xs = []
out <- runWithInput T.main (unlines (map show (-10 : xs)))
shouldContain out ("Soma dos números digitados: " ++ show (sum xs))
prop "com quantidade não negativa" $ do
\xs -> do
out <- runWithInput T.main (unlines (map show (length xs : xs)))
shouldContain out ("Soma dos números digitados: " ++ show (sum xs))