在QuickCheck属性测试中使用IO



我目前正在编写一个Haskell库来替换一个封闭源代码的第三方命令行应用程序。这个第三方CLI有一个我复制过的规范,但实际上二进制比规范允许更多的允许输入

我希望能够使用QuickCheck生成输入,然后将库中函数的结果与第三方CLI应用程序的stdout进行比较。我陷入困境的部分是如何在属性测试中引入IO。

这是我迄今为止的代码:

{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text as T
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.QuickCheck
-- This function lives in my library, this is just a sample
-- the actual function does things but is still pure, and has the type Text -> Int
exampleCountFuncInModule :: T.Text -> Int
exampleCountFuncInModule t = T.length t
-- contrived example generator
genSmallString :: Gen T.Text
genSmallString = do 
smallList <- T.pack <$> resize 2 (listOf1 arbitraryASCIIChar)
pure ("^" `T.append` smallList)
main :: IO ()
main = do
hspec $ do
prop "some property" $ do
verbose $ forAll genSmallString $ xs -> (not . T.null) xs ==> do
let myCount = exampleCountFuncInModule xs
-- Want to run external program here, and read the result as an Int
let otherProgramCount = 2
myCount == otherProgramCount

我发现QuickCheck有一个ioProperty,这似乎正是我想要的,我只是不确定如何将其融入我现有的内容中。

我想我已经明白了,我使用了这个:

test :: Text -> IO Bool 
test t = do
(exitCode, stdOut, stdErr) <- callCmd $ "bin/cliTool" :| [Text.unpack t]
let cliCount = read stdOut :: Int
let myCount = countOfThingsInString t
return $ cliCount == myCount

然后在我的hspec测试中:

main :: IO ()
main = do
hspec $ do
describe "tests" $ do
prop "test IO" $ do
verbose $ forAll arbitrarySmallSpecifier (ioProperty . test)

相关内容

  • 没有找到相关文章

最新更新