Testing 如何防止QuickCheck捕获所有异常?
QuickCheck库似乎可以捕获测试属性时引发的所有异常。特别是,这种行为阻止我对整个QuickCheck计算设置时间限制。例如:Testing 如何防止QuickCheck捕获所有异常?,testing,haskell,quickcheck,Testing,Haskell,Quickcheck,QuickCheck库似乎可以捕获测试属性时引发的所有异常。特别是,这种行为阻止我对整个QuickCheck计算设置时间限制。例如: module QuickCheckTimeout where import System.Timeout (timeout) import Control.Concurrent (threadDelay) import Test.QuickCheck (quickCheck, within, Property) import Test.QuickCheck.Mo
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!"
模块快速检查超时,其中
导入系统。超时(超时)
导入控制。并发(线程延迟)
导入Test.QuickCheck(QuickCheck,内,属性)
导入Test.QuickCheck.Monadic(monadicIO、run、assert)
--使用threadDelay模拟缓慢的计算
prop\u slow\u plus\u zero\u right\u identity::Int->Property
prop\u slow\u plus\u zero\u right\u identity i=monadicIO$do
运行(线程延迟(100000*i))
断言(i+0==i)
运行测试::IO()
runTests=do
结果putStrLn“超时!”
刚刚->putStrLn“完成!”
因为QuickCheck捕获了所有异常,timeout
中断:它实际上并没有中止计算!相反,QuickCheck将属性视为已失败,并尝试收缩导致失败的输入。然后,此收缩过程不在时间范围内运行,导致计算使用的总时间超过规定的时间限制
有人可能会认为我可以在combinator中使用QuickCheck的,来限制计算时间。(
中的如果未在给定的时间限制内完成,则将属性视为已失败。)但是,
中的并不能完全满足我的要求,因为QuickCheck仍会尝试收缩导致失败的输入,这一过程可能会花费太长时间。(另一种可能对我有效的方法是
中的版本,它可以防止QuickCheck尝试将输入收缩到某个属性,该属性由于未在给定的时间限制内完成而失败。)
如何防止QuickCheck捕获所有异常?也许chasingboots
包会有用吗 由于当用户按Ctrl+C手动中断测试时,QuickCheck做的事情是正确的,因此您可以通过编写类似于超时的内容来解决此问题,但这会引发异步异常,而不是自定义异常类型
这几乎是来自系统源代码的直接复制和粘贴作业。超时
:
import Control.Concurrent
import Control.Exception
timeout' n f = do
pid <- myThreadId
bracket (forkIO (threadDelay n >> throwTo pid UserInterrupt))
(killThread)
(const f)
因为此解决方案解决了特定的用例(即对整个快速检查计算设置时间限制),所以进行了向上投票。仔细研究源代码,看起来QuickCheck是专门处理UserInterrupt异常的。不幸的是,这个解决方案并没有完全回答我的问题:除了UserInterrupt之外,QuickCheck仍然会吞噬所有内容!
> runTests
*** Failed! Exception: 'user interrupt' (after 13 tests):
16