QuickCheck库似乎捕获测试属性时引发的所有异常。特别是,这种行为使我无法对整个QuickCheck计算设置时间限制。例如:如何防止QuickCheck捕获所有异常?
module QuickCheckTimeout where
import System.Timeout (timeout)
import Control.Concurrent (threadDelay)
import Test.QuickCheck (quickCheck, within, Property)
import Test.QuickCheck.Monadic (monadicIO, run, assert)
-- use threadDelay to simulate a slow computation
prop_slow_plus_zero_right_identity :: Int -> Property
prop_slow_plus_zero_right_identity i = monadicIO $ do
run (threadDelay (100000 * i))
assert (i + 0 == i)
runTests :: IO()
runTests = do
result <- timeout 3000000 (quickCheck prop_slow_plus_zero_right_identity)
case result of
Nothing -> putStrLn "timed out!"
Just _ -> putStrLn "completed!"
因为快速检查捕获所有的异常,timeout
游:它实际上并没有中止计算!相反,QuickCheck将该属性视为失败,并尝试缩小导致失败的输入。这个缩小的过程不会随时间限制运行,导致计算所用的总时间超过规定的时间限制。
有人可能会认为我可以使用QuickCheck的within
组合器来限制计算时间。 (within
如果一个属性在给定的时间限制内没有完成,则将其视为失败)。但是,within
并不完全符合我的要求,因为QuickCheck仍会尝试缩小导致失败的输入,这个过程可以需要太长时间。 (对我来说可以替代的一个版本是within
,它可以防止QuickCheck将输入收缩到一个因为它没有在给定的时间限制内完成而失败的属性。)
如何防止QuickCheck捕捉所有例外?
Upvoted,因为这个解决方案解决了特定的使用情况(即对整个QuickCheck计算的时间限制)。仔细研究源代码,它看起来像QuickCheck是硬连线来专门处理UserInterrupt异常。 不幸的是,这个解决方案并不能完全回答我的问题:QuickCheck仍然会吞噬除UserInterrupt之外的所有内容! – 2012-03-10 03:08:47