使用Monadic QuickCheck测试IO操作 [英] Testing IO actions with Monadic QuickCheck

查看:152
本文介绍了使用Monadic QuickCheck测试IO操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以给我一个使用Monadic QuickCheck测试IO操作的简单例子吗? Test.QuickCheck.Monadic 模块让您测试一元代码,甚至是运行在 IO 中的东西。



一元属性测试类型为 PropertyM ma ,其中 m 是测试运行的单子, a 最终忽略。在 PropertyM IO a 的情况下,您可以使用将单子测试转换为 Property monadicIO ;对于所有其他monad,您可以使用 monadic 来代替(这需要一个函数来运行monad, IO 不会)在一次性测试中,忽略monad中的值 return 。要检查表达式,请使用 assert ; assert 一个错误的值将会使测试失败。使用 run 来执行正在测试的monad中的代码。

还有其他一些monadic操作可供您使用。例如, pick 会从 Gen a pre 将检查测试前置条件。如果测试输入或前提条件本身依赖于通过被测单子计算得到的值,那么这很有用,在这种情况下,生成输入或检查预条件的正常方式将不起作用。

<下面是测试一些 IO 代码的例子:我们检查在写入临时文件之后,我们可以读取相同的数据。出于演示的目的,我们将强加一个先决条件,即我们至少向文件写入一个字节。这两个测试属性做同样的事情;一个不必要地使用 pick pre ,而另一个不会。

  import System.Directory(removeFile)
import System.IO(hGetContents,hPutStr,hSeek,openBinaryTempFile,SeekMode(..))
import Test.QuickCheck (任意的,Property,quickCheck,(==>))
导入Test.QuickCheck.Monadic(assert,monadicIO,pick,pre,run)

- 演示pick和pre well:
prop_writeThenRead :: Property
prop_writeThenRead = monadicIO $ do writtenData< - pick any
pre $ not(null writtenData)
readData< - run $ writeThenRead writtenData
assert $ writtenData == readData

- 一种比较习惯的写法:
prop_writeThenRead2 :: [Char] - >属性
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/ tmpquickcheck.tmp
removeFile路径
hPutStr h输出
hSeek h AbsoluteSeek 0
hGetContents h

main :: IO()
main = do quickCheck prop_writeThenRead
quickCheck prop_writeThenRead2


Can anyone give me a brief example of testing IO actions using Monadic QuickCheck?

解决方案

The Test.QuickCheck.Monadic module lets you test monadic code, even things that run in IO.

A monadic property test is of type PropertyM m a, where m is the monad the test runs in and a is ultimately ignored. In the case of PropertyM IO a, you convert the monadic test to a Property by using monadicIO; for all other monads, you use monadic instead (which takes a function to run the monad, something IO doesn't have).

In a monadic test, the value returned out of the monad is ignored. To check an expression, use assert; asserting a false value will fail the test. Use run to execute the code in the monad being tested.

There are other monadic actions at your disposal. For example, pick will generate new test inputs out of a Gen a, and pre will check test preconditions. These are useful if the test inputs or preconditions themselves depend on values computed via the monad being tested, in which case the normal way of generating inputs or checking precontions won't work.

Here's an example of testing some IO code: we check that after writing something to a temporary file, we can read that same data back. For demonstration purposes, we'll impose the precondition that we write at least one byte to the file. The two test properties do the same thing; one uses pick and pre unnecessarily while the other does not.

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

这篇关于使用Monadic QuickCheck测试IO操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆