使用 IO monad 的 Haskell 单元测试

ast*_*fel 5 io monads haskell ghci hunit

我正在尝试为返回 IO monad 的 haskell 函数编写 HUnit 测试,因为它们执行文件 I/O。有什么办法可以做到这一点吗?现在我正在尝试编写一个仅返回 Bool 的方法,这可以作为我的测试

\n\n
combine :: FilePath -> FilePath -> Bool\ncombine fp1 fp2 = do\n  cs <- readFile fp1\n  let (_,y,z) = strToHuff cs\n  let _ = writeToFile fp2 z y\n  (a, b) <- readFromFile fp2\n  z == a && b == y\n
Run Code Online (Sandbox Code Playgroud)\n\n

但这给了我以下错误:

\n\n
FileWriter.hs:153:3: Couldn\'t match type \xe2\x80\x98IO b0\xe2\x80\x99 with \xe2\x80\x98Bool\xe2\x80\x99 \xe2\x80\xa6\n    Expected type: IO String -> (String -> IO b0) -> Bool\n      Actual type: IO String -> (String -> IO b0) -> IO b0\n    In a stmt of a \'do\' block: cs <- readFile fp1\n    In the expression:\n      do { cs <- readFile fp1;\n           let (_, y, z) = strToHuff cs;\n           let _ = writeToFile "try1.txt" z y;\n           (a, b) <- readFromFile fp2;\n           .... }\n    In an equation for \xe2\x80\x98combine\xe2\x80\x99:\n        combine fp1 fp2\n          = do { cs <- readFile fp1;\n                 let (_, y, z) = ...;\n                 let _ = ...;\n                 .... }\nFileWriter.hs:157:3: Couldn\'t match expected type \xe2\x80\x98IO b0\xe2\x80\x99 with actual type \xe2\x80\x98Bool\xe2\x80\x99 \xe2\x80\xa6\n    In a stmt of a \'do\' block: z == a && b == y\n    In the expression:\n      do { cs <- readFile fp1;\n           let (_, y, z) = strToHuff cs;\n           let _ = writeToFile "try1.txt" z y;\n           (a, b) <- readFromFile fp2;\n           .... }\n    In an equation for \xe2\x80\x98combine\xe2\x80\x99:\n        combine fp1 fp2\n          = do { cs <- readFile fp1;\n                 let (_, y, z) = ...;\n                 let _ = ...;\n                 .... }\nCompilation failed.\n
Run Code Online (Sandbox Code Playgroud)\n

poi*_*ida 2

就像 @user2407038 在评论中所说的以及HUnit 用户手册中提到的HUnit 测试在IO monad中运行。

\n\n

这是一个例子:

\n\n
testFilesEqual = TestCase (do x <- readFile "a.txt"\n                              y <- readFile "b.txt"\n                              assertEqual "files not equal" x y)\n# a.txt == b.txt\n\xce\xbb> runTestTT testFilesEqual\nCases: 1  Tried: 0  Errors: 0  Failures: 0\nCounts {cases = 1, tried = 1, errors = 0, failures = 0}\n\n# a.txt != b.txt\n\xce\xbb> runTestTT testFilesEqual\n### Failure:\nfiles not equal\nexpected: "hello\\n"\nbut got: "world\\n"\nCases: 1  Tried: 1  Errors: 0  Failures: 1\nCounts {cases = 1, tried = 1, errors = 0, failures = 1}\n
Run Code Online (Sandbox Code Playgroud)\n