Zoeken…


Eigendom verklaren

In het eenvoudigste geval is een eigenschap een functie die een Bool retourneert.

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

Een eigenschap verklaart een invariant op hoog niveau van een programma. De QuickCheck-testloper zal de functie evalueren met 100 willekeurige ingangen en controleren of het resultaat altijd True .

Volgens afspraak hebben functies die eigenschappen hebben namen die beginnen met prop_ .

Een enkele eigenschap controleren

De quickCheck functie test een eigenschap op 100 willekeurige ingangen.

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

Als een eigenschap mislukt voor bepaalde invoer, drukt quickCheck een tegenvoorbeeld af.

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

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

Alle eigenschappen in een bestand controleren

quickCheckAll is een Template Haskell-helper die alle definities in het huidige bestand vindt waarvan de naam begint met prop_ en deze test.

{-# 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

Merk op dat de return [] regel is vereist. Het maakt definities tekstueel boven die regel zichtbaar voor Template Haskell.

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

Willekeurig genereren van gegevens voor aangepaste typen

De klasse Arbitrary is voor typen die willekeurig door QuickCheck kunnen worden gegenereerd.

De minimale implementatie van Arbitrary is de arbitrary methode, die in de Gen monade wordt uitgevoerd om een willekeurige waarde te produceren.

Hier is een voorbeeld van Arbitrary voor het volgende gegevenstype van niet-lege lijsten.

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
        ]

Implicatie (==>) gebruiken om eigenschappen met randvoorwaarden te controleren

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

Als u wilt controleren of een eigenschap vasthoudt gegeven een voorwaarde, kunt u de operator ==> gebruiken. Let op: als het zeer onwaarschijnlijk is dat willekeurige invoer overeenkomt met de voorwaarde, kan QuickCheck vroeg opgeven.

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

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

Beperking van de grootte van testgegevens

Het kan moeilijk zijn om functies met een slechte asymptotische complexiteit te testen met behulp van quickcheck, omdat de willekeurige invoer meestal niet aan de grootte gebonden is. Door een bovengrens toe te voegen aan de grootte van de invoer, kunnen we deze dure functies nog steeds testen.

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

Door quickCheckWith met een aangepaste versie van stdArgs we de grootte van de ingangen beperken tot maximaal 10. In dit geval, omdat we lijsten genereren, betekent dit dat we lijsten tot maximaal 10 genereren. Onze permutatiefunctie werkt niet het duurt te lang voordat deze korte lijsten zijn uitgevoerd, maar we kunnen er nog steeds redelijk zeker van zijn dat onze definitie correct is.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow