2014-02-25 33 views
3

我在这里遇到编程问题。一半的麻烦是,问题本身是非常棘手的想法,另一半是我不记得如何找到QuickCheck的方式。在QuickCheck属性中生成新的测试数据

我知道如果你编写一个函数,它带有几个带有Arbitrary实例的参数,QuickCheck将允许你使用该方法作为测试。我无法弄清楚的是如何在该方法内生成新的测试参数。我想写一些像

prop13 :: Foo -> Bar -> Bool 
prop13 foo bar = 
    if foobar foo bar 
    then fn1 foo 
    else newInput $ \ baz -> fn2 foo bar baz 

但我不知道该怎么做到这一点。

其实,不,我真的想写是

prop13 :: Foo -> Bar -> Property 
prop13 foo bar = 
    if foobar foo bar 
    then label "foobar=YES" $ fn1 foo 
    else label "foobar=NO" $ newInput $ \ baz -> fn2 foo bar baz 

只是这样我就可以检查它没有采取一个分支的时间或荒谬的东西类似的100%。

其实,如果我可以要求baz具有某些特定属性,那将是一件好事。我隐约记得QuickCheck有一个功能可以丢弃不符合给定条件的输入。 (唯一的问题是,它可能需要不合理数量的尝试来满足条件...)

有没有办法做到这一点?我盯着黑线鳕页面,但我无法弄清楚如何得到我想要的东西......

回答

4

的属性可以采用以下形式

classify <condition> <string>$ <property>

例如,

满足条件

prop_Insert x xs = ordered xs ==> classify (ordered (x:xs)) "at-head" $ classify (ordered (xs ++ [x])) "at-tail" $ ordered (insert x xs) where types = x :: Int

测试用例分配分类 给出,分类的分布报告在 测试后编辑。在这种情况下,结果是

Main> quickCheck prop_Insert OK, passed 100 tests. 58% at-head, at-tail. 22% at-tail. 4% at-head.

注意,一个测试用例可能落入一个以上的类别。

(从QuickCheck manual

为要求的输入数据中的特定属性,则可以在测试体之前添加somePredicate data ==>,因为它是在片段所示的上方。又如:

prop_max xs = (not . null xs) ==> head (sort xs) == maximum xs

你说的没错,这个组合子扔掉不合适的情况。如果这是不需要的,你可以做一个newtype包装在输入型和重新定义Arbitrary实例(参见上herePositiveNonEmpty等例子)

+0

好吧,这样很好地解释了如何处理生成正确的数据。现在如何在属性内生成新的测试数据? – MathematicalOrchid

4

我找到了答案another answer。显然,这是forAll

else forAll arbitrary $ \ baz -> fn2 foo bar baz 

我只是不记得怎么办呢?

(这也有让我指定一个特定的随机数据发生器的不错的功能。)