我有一个测试函数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”的属性
至于上一个例子?我想,可以使用whenFail
或whenFail'
,但我还没有理解QuickCheck内部。
答案 0 :(得分:0)
感谢#haskell频道的aavogt,我找到了模块Control.Spoon
,它提供了勺子和茶匙的功能,可以用来解决这个问题。但是,我不知道使用这个包(使用unsafePerformIO internally
)是多么安全。
无论如何,使用Control.Spoon
,prop
可以通过以下方式重写:
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
只捕获一些选择的异常,这对我来说很好,因为我只关心未定义和无穷无尽的模式匹配。