我试图在一个Test.Tasty testGroup中运行多个测试(即多个断言);但是输入一个从IO读入的"object“。
例如,我读取并解析一个文件;我想对该文件的结果进行多个断言。就像这样
tests :: [String] -> TestTree
tests ls = testGroup "tests" [ testCase "length" $ length ls @?= 2
, testCase "foo" $ ls !! 0 @?= "foo"
]
main = do
ls :: [String] <- read <$> readFile "/tmp/hunit"
defaultMain (tests ls)
但是,上面要求在调用测试之前执行IO;即使只请求了测试的一个子集(无论该子集是否实际使用IO结果),也会执行。
或者,每个testCase都可以执行自己的IO (断言毕竟只是IO () );但这可能意味着重复执行IO,这不是我想要的。
或者,testCase可以包含一个调用多个断言的do {}
块;但这意味着单个测试是不可选择的,并且不会得到详细的输出来确认运行了哪些测试。
Test.Tasty.withResource
看起来很有希望;如果它的第三个参数是a -> TestTree
,我可以使用它;然而,它不是,它是IO a -> TestTree
,我正在努力找出如何安全地提取a
以在我的测试用例中使用。
我试过了,但我担心我遗漏了一些基本的东西...
感谢您给予的任何帮助。
发布于 2019-03-15 04:12:07
您看到的是正确的
withResource
:: IO a -- ^ initialize the resource
-> (a -> IO ()) -- ^ free the resource
-> (IO a -> TestTree)
-- ^ @'IO' a@ is an action which returns the acquired resource.
-- Despite it being an 'IO' action, the resource it returns will be
-- acquired only once and shared across all the tests in the tree.
-> TestTree
这个想法是,你可以把你的场景写成:
tests :: IO String -> TestTree
tests lsIO = testGroup "tests"
[ testCase "length" $ do
ls <- lsIO
length ls @?= 2
, testCase "foo" $ do
ls <- lsIO
ls !! 0 @?= "foo"
, testCase "no io" $ do
return ()
]
main :: IO ()
main = defaultMain (withResource acquire tests)
acquire :: IO [String]
acquire = read <$> readFile "/tmp/hunit"
也就是说,看起来你已经多次读取文件,但tasty
只执行了一次操作。这就是评论所说的:)尝试将putStrLn "trace debug"
添加到acquire
,以确保它主要运行一次(即,如果您只请求no io
测试,则不运行)。
https://stackoverflow.com/questions/55165302
复制相似问题