Sök…


Förklara en fastighet

På det enklaste är en egenskap en funktion som returnerar en Bool .

prop_reverseDoesNotChangeLength xs = length (reverse xs) == length xs

En egendom förklarar en hög nivå invariant av ett program. QuickCheck-testlöparen utvärderar funktionen med 100 slumpmässiga ingångar och kontrollerar att resultatet alltid är True .

Enligt konvention har funktioner som är egenskaper namn som börjar med prop_ .

Kontrollerar en enda egendom

Funktionen quickCheck testar en egenskap på 100 slumpmässiga ingångar.

ghci> quickCheck prop_reverseDoesNotChangeLength
+++ OK, passed 100 tests.

Om en egenskap misslyckas med viss inmatning, skriver quickCheck ut ett motexempel.

prop_reverseIsAlwaysEmpty xs = reverse xs == []  -- plainly not true for all xs

ghci> quickCheck prop_reverseIsAlwaysEmpty
*** Failed! Falsifiable (after 2 tests):                  
[()]

Kontrollera alla egenskaper i en fil

quickCheckAll är en mall Haskell-hjälper som hittar alla definitioner i den aktuella filen vars namn börjar med prop_ och testar dem.

{-# LANGUAGE TemplateHaskell #-}

import Test.QuickCheck (quickCheckAll)
import Data.List (sort)

idempotent :: Eq a => (a -> a) -> a -> Bool
idempotent f x = f (f x) == f x

prop_sortIdempotent = idempotent sort

-- does not begin with prop_, will not be picked up by the test runner
sortDoesNotChangeLength xs = length (sort xs) == length xs


return []
main = $quickCheckAll

Observera att return [] är obligatorisk. Det gör definitioner textuellt ovanför den raden synliga för Mall Haskell.

$ runhaskell QuickCheckAllExample.hs
=== prop_sortIdempotent from tree.hs:7 ===
+++ OK, passed 100 tests.

Slumpmässigt generera data för anpassade typer

Klassen Arbitrary är för typer som kan skapas slumpmässigt av QuickCheck.

Den minimala implementeringen av Arbitrary är den arbitrary metoden, som körs i Gen monaden för att producera ett slumpmässigt värde.

Här är ett exempel på Arbitrary för följande datatyp av icke-tomma listor.

import Test.QuickCheck.Arbitrary (Arbitrary(..))
import Test.QuickCheck.Gen (oneof)
import Control.Applicative ((<$>), (<*>))

data NonEmpty a = End a | Cons a (NonEmpty a)

instance Arbitrary a => Arbitrary (NonEmpty a) where
    arbitrary = oneof [  -- randomly select one of the cases from the list
        End <$> arbitrary,  -- call a's instance of Arbitrary
        Cons <$>
            arbitrary <*>  -- call a's instance of Arbitrary
            arbitrary  -- recursively call NonEmpty's instance of Arbitrary
        ]

Använd implikation (==>) för att kontrollera egenskaper med förutsättningar

prop_evenNumberPlusOneIsOdd :: Integer -> Property
prop_evenNumberPlusOneIsOdd x = even x ==> odd (x + 1)

Om du vill kontrollera att en fastighet rymmer med tanke på att en förutsättning gäller, kan du använda operatören ==> . Observera att om det är mycket osannolikt att godtyckliga ingångar matchar förutsättningen kan QuickCheck ge upp tidigt.

prop_overlySpecific x y = x == 0 ==> x * y == 0

ghci> quickCheck prop_overlySpecific
*** Gave up! Passed only 31 tests.

Begränsar storleken på testdata

Det kan vara svårt att testa funktioner med dålig asymptotisk komplexitet med snabbcheck eftersom slumpmässiga ingångar vanligtvis inte är avgränsade till storlek. Genom att lägga till en övre gräns på ingångens storlek kan vi fortfarande testa dessa dyra funktioner.

import Data.List(permutations)
import Test.QuickCheck

longRunningFunction :: [a] -> Int
longRunningFunction xs = length (permutations xs)

factorial :: Integral a => a -> a
factorial n = product [1..n]

prop_numberOfPermutations xs =
    longRunningFunction xs == factorial (length xs)

ghci> quickCheckWith (stdArgs { maxSize = 10}) prop_numberOfPermutations

Genom att använda quickCheckWith med en modifierad version av stdArgs vi begränsa storleken på ingångarna till högst 10. I detta fall, eftersom vi genererar listor, betyder det att vi genererar listor med upp till storlek 10. Vår permutationsfunktion gör inte tar för lång tid att köra för dessa kortlistor men vi kan fortfarande vara rimligt säkra på att vår definition är korrekt.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow