簡體   English   中英

如何在QuickCheck中運行特定數量的測試?

[英]How to run a specific number of tests in QuickCheck?

我正在嘗試學習Haskell,特別是QuickCheck。 雖然Haskell在網上有很多信息,但我很難用QuickCheck創建一些隨機測試。

例如,我有以下腳本:

import Test.QuickCheck

whatAge :: Int -> Int -> Int -> Int -> Bool

whatAge age1 age2 age3 age4
  | age1 + age2 + age3 + age4 == 5 = True
  | otherwise = False

main = do
    verboseCheck  whatAge

當我運行它時顯示:

*** Failed! Falsifiable (after 1 test): 
0
0
0
0

相當不錯,它顯示了一個功能錯誤的測試。

我想做的是:

  1. 即使在失敗時也會生成200個隨機測試(即使whatAge函數的輸出為false)
  2. 能夠在我的函數參數上放置一個范圍,例如:

      x1 range from 1 to 30 x2 range from 1 to 40 x3 range from 1 to 50 x4 range from 1 to 60 
  3. 能夠生成非重復測試

根據我的理解,使用QuickCheck不可能實現3,因為我必須使用smallCheck,但我不確定第1點和第2點。

對於輸入的簡單屬性,可以使用捕獲它們的適當Arbitrary實例創建newtype。 所以:

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}

import Data.Proxy
import GHC.TypeLits
import Test.QuickCheck

newtype Range (m :: Nat) (n :: Nat) a = Range { getVal :: a }
    deriving (Eq, Ord, Read, Show, Num, Real, Enum, Integral)

numVal :: forall n a. (KnownNat n, Num a) => a
numVal = fromInteger (natVal @n Proxy)

instance (KnownNat m, KnownNat n, Arbitrary a, Integral a) => Arbitrary (Range m n a) where
    arbitrary = fromInteger <$> choose (numVal @m, numVal @n)
    shrink hi = go (numVal @m) where
        go lo | lo == hi = [] | otherwise = lo : go ((lo+hi+1)`div`2) -- overflow? what's that? lmao

whatAge :: Range 1 30 Int -> Range 1 40 Int -> Range 1 50 Int -> Range 1 60 Int -> Bool
whatAge (Range age1) (Range age2) (Range age3) (Range age4)
    = age1 + age2 + age3 + age4 == 5

在ghci:

> verboseCheck whatAge
Failed:  
Range {getVal = 17}
Range {getVal = 29}
Range {getVal = 3}
Range {getVal = 16}

Failed:                                  
Range {getVal = 1}
Range {getVal = 29}
Range {getVal = 3}
Range {getVal = 16}

Failed:                                               
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 3}
Range {getVal = 16}

Failed:                                                
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 16}

Failed:                                                
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 1}

*** Failed! Falsifiable (after 1 test and 4 shrinks):  
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 1}
Range {getVal = 1}

對於更復雜的屬性,如何直接創建滿足屬性的隨機值,則可以使用QuickCheck的(==>)運算符。 例如,對於上面的范圍檢查:

> verboseCheck (\x -> (1 <= x && x <= 30) ==> x*2 < 60)
Skipped (precondition false):
0

Passed:                
1

*** Failed! Falsifiable (after 33 tests):                  
30

要進行200次測試,可以調用quickCheckWith進行一次測試,200次; 或者你可以直接generate調用你的財產的測試結果arbitrary手動。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM