如何使用quickcheck显示测试属性失败的原因?

时间:2011-01-23 08:17:21

标签: haskell quickcheck

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

考虑例如:

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

然后a会话看起来像:

> quickCheck prop
Falsifiable, after 48 tests:
42
23

但是对于调试来说,作为quickCheck可证伪报告的一部分,显示失败的原因会非常方便。

我这样砍了它:

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

是否有更好/更好或更快速的检查方法呢?

4 个答案:

答案 0 :(得分:9)

我假设您的“reason”变量包含某些针对错误的特定于测试的数据。您可以改为返回“结果”,其中包含成功/失败/无效条件以及解释出错的字符串。返回结果的属性由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中定义的“Result”类型。

在Test.QuickCheck.P​​roperty中还定义了一些组合器,它们可以帮助您组合Result而不是直接调用构造函数,例如

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

我想这将是更好的风格。

答案 1 :(得分:2)

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

答案 2 :(得分:0)

这与保罗·约翰逊的答案一样,但对 for _, line in pairs(objects.lines) do love.graphics.line( line.x1 - Camera.x, line.y1 - Camera.y, line.x2 - Camera.x, line.y2 - Camera.y) --:getWorldPoints(block.shape:getPoints())) end 的变化更简洁,更健壮:

MkResult

答案 3 :(得分:0)

这是我的解决方案(我现在使用counterexample而不是printTestCase,因为现在不推荐使用后者):

(<?>) :: (Testable p) => p -> String -> Property
(<?>) = flip (Test.QuickCheck.counterexample . ("Extra Info: " ++))
infixl 2 <?>

用法:

main :: IO ()
main = hspec $ do
  describe "math" $ do
    prop "sum-of-square-le-square-of-sum" $ do
      \(x :: Int) (y :: Int) ->
        x * x + y * y <= (x + y) * (x + y) <?> show (x * x, y * y, x + y)

因此,当测试用例失败时,您会看到类似以下内容的

   *** Failed! Falsifiable, Falsifiable (after 2 tests):
   1
   -1
   Extra Info: (1,1,0)

您还可以将<?>.&&..||.=====>等一起使用。

  describe "math" $ do
    prop "sum-of-square-le-square-of-sum" $ do
      \(x :: Int) (y :: Int) ->
        x * x + y * y <= (x + y) * (x + y) <?> show (x * x, y * y, x + y) .||. (1==0) <?> "haha"