繁体   English   中英

Haskell Tasty.HUnit:如何使用 IO 运行多个测试

[英]Haskell Tasty.HUnit : how to run multiple tests with IO

我正在尝试在 Test.Tasty testGroup 中运行多个测试(即多个断言); 但是输入从 IO 读入的单个“对象”。

例如,我读取并解析一个文件; 我想对该文件的结果进行多次断言。 就像是

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(毕竟 Assertion 就是 IO()); 但这可能意味着重复执行 IO,这不是我想要的。

或者,一个 testCase 可以包含一个调用多个断言的do {}块; 但这意味着单个测试是不可选择的,并且不会获得详细的输出来确认运行了哪些测试。

Test.Tasty.withResource看起来很有希望; 如果它的第三个参数是a -> TestTree ,我可以使用它; 然而,它不是,它是IO a -> TestTree ,我正在努力研究如何安全地提取a以在我的测试用例中使用。

我试过玩这个,但我担心我错过了一些基本的东西......

感激地收到任何帮助。

看起来应该很简单; 因为type Assertion = IO () ,这两个部分应该足够了:

(>>=) :: IO a -> (a -> Assertion) -> Assertion
testCase :: TestName -> Assertion -> TestTree

你是正确的看着

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测试则不运行)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM