首页 > 解决方案 > 如何使用任意或其他类型类定义每种数据类型的最大生成测试?

问题描述

背景

假设要测试的主题是Huge模块,并且我们正在使用带有 Test.QuickCheck(和 Test.Framework.Providers.QuickCheck2)的 Test.Framework。

module Huge
    (
        ...
    ) where

data TooHugeToTestAll = ToHuge { ra :: Int, rb :: Int, rc :: Int, rd :: Int }
    deriving (Show)

hugeProduct :: TooHugeToTestAll -> Integer
...

isAnyZeroOrNegative :: TooHugeToTestAll -> Bool
...

shiftLHuge :: TooHugeToTestAll -> TooHugeToTestAll
shiftLHuge (ToHuge a b c d) = (ToHuge b c d a)

...并假设测试由执行stack test,并编译Spec.hs以测试模块Huge

-- Spec.hs

{-# OPTIONS_GHC -fno-warn-orphans #-}

import qualified Test.Framework as TF
import qualified Test.Framework.Providers.HUnit as FHU
import qualified Test.Framework.Providers.QuickCheck2 as QC2 -- supports Test.QuickCheck with 'testProperty'
import qualified Test.HUnit as HU
import qualified Test.QuickCheck as QC

import qualified Huge as H

main :: IO ()
main = 
    TF.defaultMainWithOpts
        [
            FHU.testCase "Law #1 test case #1" ((H.hugeProduct (H.ToHuge 2 3 5 7)) HU.@?= 210), 
            FHU.testCase "Law #2 test case #1" ((H.hugeProduct (H.ToHuge 0 3 5 7)) HU.@?= 0), 
            FHU.testCase "Law #2 test case #2" ((H.hugeProduct (H.ToHuge 2 0 5 7)) HU.@?= 0), 
            FHU.testCase "Law #2 test case #3" ((H.hugeProduct (H.ToHuge 2 3 0 7)) HU.@?= 0), 
            FHU.testCase "Law #2 test case #4" ((H.hugeProduct (H.ToHuge 2 3 5 0)) HU.@?= 0), 
            (QC2.testProperty
                    "Law #1" 
                    (\huge -> 
                        (
                            (not (H.isAnyZeroOrNegative huge)) 
                            QC.==> 
                            ((H.hugeProduct huge) == ((fromIntegral (H.ra huge)) * (fromIntegral (H.rb huge)) * (fromIntegral (H.rc huge)) * (fromIntegral (H.rd huge)))) ) ) ), 
            QC2.testProperty
                "Law #2" 
                (\huge -> 
                    ( 
                        (H.isAnyZeroOrNegative huge) 
                        QC.==> 
                        ((H.hugeProduct huge) == 0) ) ), 
            QC2.testProperty
                "Law #3" 
                (\nj -> 
                    ( 
                        ((H.hugeProduct (H.ToHuge 2 3 5 nj)) /= 0) 
                        QC.==> 
                        (((H.hugeProduct (H.ToHuge 2 3 5 1)) * (fromIntegral nj)) == (H.hugeProduct (H.ToHuge 2 3 5 nj))) ) )
        ]
        mempty

instance QC.Arbitrary H.TooHugeToTestAll where
    arbitrary = 
        do
            a <- QC.frequency
                [
                    (1000, QC.choose (-2, 4)),  -- around 0
                    (1, QC.choose (3, 10000))   -- up to 10000
                ]
            b <- QC.frequency
                [
                    (1000, QC.choose (-2, 4)),  -- around 0
                    (1, QC.choose (3, 10000))   -- up to 10000
                ]
            c <- QC.frequency
                [
                    (1000, QC.choose (-2, 4)),  -- around 0
                    (1, QC.choose (3, 10000))   -- up to 10000
                ]
            d <- QC.frequency
                [
                    (1000, QC.choose (-2, 4)),  -- around 0
                    (1, QC.choose (3, 10000))   -- up to 10000
                ]
            return (H.ToHuge a b c d)

正如我们在上面看到的,我们可以控制 class 类型实例的随机分布Arbitrary

问题

据我了解,我们无法以相同的方式控制生成的最大测试数)1(通过为数据类型TooHugeToTestAll创建一个实例),可以吗?如果是,如何?

我已经为 Testable 苦恼了,但我不明白Test.Framework, 和Test.QuickCheck.


) 1最大生成测试的含义是TestOptions.

标签: haskell

解决方案


推荐阅读