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!"
因为 QuickCheck 捕获了所有异常,timeout
所以中断:它实际上并没有中止计算!相反,QuickCheck 将属性视为失败,并尝试缩小导致失败的输入。然后,这个收缩过程不以时间限制运行,导致计算使用的总时间超过规定的时间限制。
有人可能认为我可以使用 QuickCheck 的within
组合器来限制计算时间。(within
如果属性没有在给定的时间限制内完成,则将其视为失败。)但是,within
并不能完全满足我的要求,因为 QuickCheck 仍会尝试缩小导致失败的输入,这个过程可能需要很长时间太长。(或者对我有用的是一个版本,within
它可以防止 QuickCheck 尝试将输入缩小到一个失败的属性,因为它没有在给定的时间限制内完成。)
如何防止 QuickCheck 捕获所有异常?