这个
Test.QuickCheck.Monadic
IO
.
一元属性测试属于
PropertyM m a
m
是测试运行的单子
a
PropertyM IO a
,将一元测试转换为
Property
通过使用
monadicIO
; 对于所有其他单子,你使用
monadic
相反(它需要一个函数来运行monad,或者
木卫一
没有)。
在一元测试中,值
return
从单子中提取的信息被忽略。要检查表达式,请使用
assert
断言
输入一个假值将使测试失败。使用
run
在被测单子中执行代码。
pick
将从
Gen a
,和
pre
将检查测试前提条件。如果测试输入或预条件本身依赖于通过被测试的monad计算出的值,那么这些是有用的,在这种情况下,生成输入或检查预条件的常规方法将不起作用。
木卫一
代码:我们检查在将某些内容写入临时文件后,是否可以读回相同的数据。出于演示的目的,我们将施加一个先决条件,即至少向文件写入一个字节。两个测试属性做相同的事情;使用
挑选
和
之前
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