2011-01-23 49 views
8

当通过QuickCheck测试失败的属性测试时,显示原因的最佳做法是什么?如何使用quickcheck显示失败测试属性的原因?

考虑例如:

prop a b = res /= [] 
    where 
     (res, reason) = checkCode a b 

然后会话可能看起来像:

> quickCheck prop 
Falsifiable, after 48 tests: 
42 
23 

但对于调试这将是非常方便的,以示对失败原因的快速检查falsifable的一部分报告。

我已经破解这样的:

prop a b = if res /= [] then traceShow reason False else True 
    where 
     (res, reason) = checkCode a b 

是否有更好的/更好以上quickcheckish办法做到这一点?

回答

9

我假设你的“原因”变量包含某些特定于测试的数据。您可以返回一个“结果”,其中包含成功/失败/无效条件和解释错误的字符串。返回结果的属性由QuickCheck以与返回Bool的属性完全相同的方式处理。

(编辑)所示:

module QtTest where 

import Test.QuickCheck 
import Test.QuickCheck.Property as P 


-- Always return success 
prop_one :: Integer -> P.Result 
prop_one _ = MkResult (Just True) True "always succeeds" False [] [] 


-- Always return failure 
prop_two :: Integer -> P.Result 
prop_two n = MkResult (Just False) True ("always fails: n = " ++ show n) False [] [] 

请注意,这是在Test.QuickCheck.P​​roperty定义你想要的 “结果” 的类型。

也有Test.QuickCheck.P​​roperty定义了一些组合程序,帮助您撰写的结果,而不是直接调用构造函数,如

prop_three :: Integer -> Property 
prop_three n = printTestCase ("always fails: n = " ++ show n) False 

我想这将是更好的风格来使用的。

2

由于QuickCheck为您提供了函数的输入,并且由于被测试的代码是纯的(它是正确的?),您可以将这些输入提供给函数并获得结果。这更加灵活,因为通过这些输入,您还可以重复测试原始功能,直到它正确为止。

+2

那么,问题的关键是方便。成功的测试都是关于尽可能的自动化。不得不打开一个ghci会话并重新计算一个潜在的昂贵函数是没有意义的。我的意思是,QuickCheck已经提供`collect`,`classify`来丰富*非失败*属性测试的输出。这种富集是可选的,并不会降低灵活性。 – maxschlepzig 2011-01-23 12:33:23

+1

我的意思是,这里还有一个实际的原因:QuickCheck属性可以是任意复杂的,所以任何给定测试的“输出”都不一定是明显的:你需要将你的代码按照“嘿” ,这里是我感兴趣的中间值!“假设你愿意做这个重写,虽然没有理由不提供这种功能,但是IIRC QuickCheck没有为此目的而烘焙的东西。 – 2011-01-23 12:52:18

相关问题