【问题标题】:Test.QuickCheck: speed up testing multiple properties for the same typeTest.QuickCheck:加快测试同一类型的多个属性
【发布时间】:2013-03-09 23:16:54
【问题描述】:

我正在测试一个生成我自己类型实例的随机生成器。为此,我有一个 Arbitrary 的自定义实例:

complexGenerator :: (RandomGen g) => g -> (MyType, g)

instance Arbitrary MyType where
    arbitrary = liftM (fst . complexGenerator . mkStdGen) arbitrary

这适用于Test.QuickCheck(实际上是Test.Framework),用于测试生成的值是否具有某些属性。但是,我要检查的属性有很多,而且我添加的越多,验证它们所需的时间就越长。

有没有办法使用相同的生成值来测试每个属性,而不是每次都重新生成它们?我显然仍然想看看,在失败时,哪个属性不成立,所以用and创建一个巨大的属性并不是最优的。

【问题讨论】:

    标签: testing haskell quickcheck htf


    【解决方案1】:

    我显然还是想看看,在失败时,哪个属性不成立,所以用and 制作一个巨大的属性并不是最优的。

    您可以使用printTestCase 标记每个属性,然后使用conjoin 创建一个巨大的属性。

    例如你认为这是个坏主意:

    prop_giant :: MyType -> Bool
    prop_giant x = and [prop_one x, prop_two x, prop_three x]
    

    这将同样有效,但会为您提供更好的输出:

    prop_giant :: MyType -> Property
    prop_giant x = conjoin [printTestCase "one" $ prop_one x,
                            printTestCase "two" $ prop_two x,
                            printTestCase "three" $ prop_three x]
    

    (话虽如此,我自己从未使用过这种方法,只是假设它会起作用;conjoin 可能出于某种原因在文档中被标记为实验性的。)

    【讨论】:

      【解决方案2】:

      结合投票答案,我发现使用带有 Writer monad 的 Reader 转换器很有帮助:

      type Predicate r = ReaderT r (Writer String) Bool
      

      在这种情况下,Reader“共享环境”是经过测试的输入。然后你可以像这样编写属性:

      inv_even :: Predicate Int
      inv_even = do
        lift . tell $ "this is the even invariant"
        (==) 0 . flip mod 2 <$> ask 
      
      toLabeledProp :: r -> Predicate r -> Property
      toLabeledProp cause r =
        let (effect, msg) = runWriter . (runReaderT r) $ cause in
          printTestCase ("inv: " ++ msg) . property $ effect
      

      并结合:

      fromPredicates :: [Predicate r] -> r -> Property
      fromPredicates predicates cause =
        conjoin . map (toLabeledProp cause) $ predicates
      

      我怀疑还有另一种方法涉及类似于这里的 Either 或 WriterT 的东西——它可以简洁地将不同类型的谓词组合成一个结果。但至少,这允许记录根据输入值强加不同后置条件的属性。

      编辑:这个想法催生了一个库: http://github.com/jfeltz/quickcheck-property-comb

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-06
        • 2011-06-11
        • 1970-01-01
        • 1970-01-01
        • 2012-04-22
        相关资源
        最近更新 更多