使用IO单子的Haskell单元测试

5

我正在尝试编写Haskell函数的HUnit测试,这些函数返回IO monad,因为它们执行文件I/O。是否有任何方法可以做到这一点?现在我正在尝试编写一个仅返回Bool的方法,这可以成为我的测试。

combine :: FilePath -> FilePath -> Bool
combine fp1 fp2 = do
  cs <- readFile fp1
  let (_,y,z) = strToHuff cs
  let _ = writeToFile fp2 z y
  (a, b) <- readFromFile fp2
  z == a && b == y

但是这给我带来了以下错误:
FileWriter.hs:153:3: Couldn't match typeIO b0’ withBool’ …
    Expected type: IO String -> (String -> IO b0) -> Bool
      Actual type: IO String -> (String -> IO b0) -> IO b0
    In a stmt of a 'do' block: cs <- readFile fp1
    In the expression:
      do { cs <- readFile fp1;
           let (_, y, z) = strToHuff cs;
           let _ = writeToFile "try1.txt" z y;
           (a, b) <- readFromFile fp2;
           .... }
    In an equation for ‘combine’:
        combine fp1 fp2
          = do { cs <- readFile fp1;
                 let (_, y, z) = ...;
                 let _ = ...;
                 .... }
FileWriter.hs:157:3: Couldn't match expected typeIO b0’ with actual typeBool’ …
    In a stmt of a 'do' block: z == a && b == y
    In the expression:
      do { cs <- readFile fp1;
           let (_, y, z) = strToHuff cs;
           let _ = writeToFile "try1.txt" z y;
           (a, b) <- readFromFile fp2;
           .... }
    In an equation for ‘combine’:
        combine fp1 fp2
          = do { cs <- readFile fp1;
                 let (_, y, z) = ...;
                 let _ = ...;
                 .... }
Compilation failed.

类型是很好的单元测试起点!尝试使用 return (z == a && b == y) - luqui
有没有一种方法可以将其包装在一个单元测试中? - astiefel
2
@astiefel,一个 HUnit 的 Assertion 只是一个 IO (),所以你可以这样做。正确的方法可能是这样的:assertEqual "..." z a; assertEqual "..." b y - 这样你可以说明为什么它们必须相等,当测试失败时,你将更容易找出原因。 - user2407038
1个回答

2

正如@user2407038在评论中所说,并且在HUnit用户手册中提到的,HUnit测试在IO单子中运行。

这里有一个例子:

testFilesEqual = TestCase (do x <- readFile "a.txt"
                              y <- readFile "b.txt"
                              assertEqual "files not equal" x y)
# a.txt == b.txt
λ> runTestTT testFilesEqual
Cases: 1  Tried: 0  Errors: 0  Failures: 0
Counts {cases = 1, tried = 1, errors = 0, failures = 0}

# a.txt != b.txt
λ> runTestTT testFilesEqual
### Failure:
files not equal
expected: "hello\n"
but got: "world\n"
Cases: 1  Tried: 1  Errors: 0  Failures: 1
Counts {cases = 1, tried = 1, errors = 0, failures = 1}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接