谁能给我一个使用 Monadic QuickCheck 测试 IO 操作的简短示例?
2 回答
Test.QuickCheck.Monadic模块让您可以测试一元代码,甚至是在IO
.
一元属性测试的类型为 ,测试运行的单子在PropertyM m a
哪里,最终被忽略。在 的情况下,您可以使用;将一元测试转换为 a 对于所有其他 monad,您可以改用(它需要一个函数来运行 monad,有些东西没有)。m
a
PropertyM IO a
Property
monadicIO
monadic
IO
在单子测试中,return
单子中的 ed 值被忽略。要检查表达式,请使用assert
; assert
输入错误值将导致测试失败。用于run
在被测试的 monad 中执行代码。
您可以使用其他单子操作。例如,pick
将从 a 中生成新的测试输入Gen a
,并pre
检查测试前提条件。如果测试输入或前置条件本身依赖于通过被测试的 monad 计算的值,这些是有用的,在这种情况下,生成输入或检查前置条件的正常方法将不起作用。
这是测试一些代码的示例IO
:我们检查在将某些内容写入临时文件后,我们是否可以读回相同的数据。出于演示目的,我们将强加一个先决条件,即我们将至少一个字节写入文件。这两个测试属性做同样的事情;一个使用pick
并且pre
不必要,而另一个没有。
import System.Directory (removeFile)
import System.IO (hGetContents, hPutStr, hSeek, openBinaryTempFile, SeekMode (..))
import Test.QuickCheck (arbitrary, Property, quickCheck, (==>))
import Test.QuickCheck.Monadic (assert, monadicIO, pick, pre, run)
-- Demonstrating pick and pre as well:
prop_writeThenRead :: Property
prop_writeThenRead = monadicIO $ do writtenData <- pick arbitrary
pre $ not (null writtenData)
readData <- run $ writeThenRead writtenData
assert $ writtenData == readData
-- A more idiomatic way to write the above:
prop_writeThenRead2 :: [Char] -> Property
prop_writeThenRead2 writtenData = not (null writtenData) ==> monadicIO test
where test = do readData <- run $ writeThenRead writtenData
assert $ writtenData == readData
writeThenRead :: [Char] -> IO [Char]
writeThenRead output = do (path, h) <- openBinaryTempFile "/tmp" "quickcheck.tmp"
removeFile path
hPutStr h output
hSeek h AbsoluteSeek 0
hGetContents h
main :: IO ()
main = do quickCheck prop_writeThenRead
quickCheck prop_writeThenRead2
测试单子代码的标准参考是“使用 QuickCheck 测试单子代码”。它显示了在 IO 等 monad 的上下文中进行测试的各种方法。
但是你真的应该考虑发布一个更具体的问题,关于你想要测试的是什么。