显示QuickCheck属性失败的原因并处理测试函数中的异常

时间:2012-12-04 20:22:48

标签: haskell quickcheck

我有一个测试函数f的QuickCheck属性。该属性将函数f映射到某个列表xs,并检查结果的某些元素属性。在失败的情况下,我想显示与此失败相关的xs元素。考虑以下属性:

prop x =
    printTestCase ("Failed for value " ++ show failure) $ isNothing failure
  where
    failure = fmap fst $ find (not . snd) $ map (\n -> (n, f x n == n)) [10..20]

这适用于实现

f = (+)

quickcheck prop输出

*** Failed! Falsifiable (after 2 tests):                  
1
Failed for value Just 10

但是,如果f抛出异常,即

f = undefined

然后quickcheck prop输出

*** Failed! Exception: 'Prelude.undefined' (after 1 test): 
()
Failed for value Exception thrown by generator: 'Prelude.undefined'

如何编写捕获第二个异常并返回“Just 0”的属性 至于上一个例子?我想,可以使用whenFailwhenFail',但我还没有理解QuickCheck内部。

1 个答案:

答案 0 :(得分:0)

感谢#haskell频道的aavogt,我找到了模块Control.Spoon,它提供了勺子和茶匙的功能,可以用来解决这个问题。但是,我不知道使用这个包(使用unsafePerformIO internally)是多么安全。

无论如何,使用Control.Spoonprop可以通过以下方式重写:

prop x =
    printTestCase ("Failed for value " ++ show pureFailure) $ isNothing excFailure
  where
    pureFailure = failure (fromMaybe True . teaspoon)
    excFailure = failure id
    failure g = fmap fst $ find (g . not . snd) $ map (\n -> (n, f x n == n)) [10..20]

fromMaybe True . teaspoon包装查找谓词会产生查找返回的效果 第一个元素要么满足谓词要么抛出异常。

由于teaspoon只能用于查看发生的异常,而不是我使用的异常 excFailure这里,以便QuickCheck仍然可以看到异常。缺点是找到了 需要进行两次评估。 teaspoon仅评估为WHNF,如果您需要深入评估以触发异常,请改用spoon

teaspoon只捕获一些选择的异常,这对我来说很好,因为我只关心未定义和无穷无尽的模式匹配。