Suche…


Eigenschaft deklarieren

Im einfachsten Fall ist eine Eigenschaft eine Funktion, die einen Bool zurückgibt.

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

Eine Eigenschaft deklariert eine übergeordnete Invariante eines Programms. Der QuickCheck-Testläufer bewertet die Funktion mit 100 zufälligen Eingaben und prüft, ob das Ergebnis immer True .

In der Regel haben Funktionen, die Eigenschaften sind, Namen, die mit prop_ .

Überprüfung einer einzelnen Eigenschaft

Die Funktion quickCheck testet eine Eigenschaft an 100 zufälligen Eingaben.

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

Wenn eine Eigenschaft bei einigen Eingaben fehlschlägt, gibt quickCheck ein Gegenbeispiel aus.

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

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

Alle Eigenschaften in einer Datei prüfen

quickCheckAll ist ein Template-Haskell-Helfer, der alle Definitionen in der aktuellen Datei findet, deren Name mit prop_ beginnt und diese testet.

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

Beachten Sie, dass die return [] -Zeile erforderlich ist. Definitionen oberhalb dieser Linie werden für Template Haskell sichtbar.

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

Daten zufällig für benutzerdefinierte Typen generieren

Die Arbitrary Klasse ist für Typen, die von QuickCheck zufällig generiert werden können.

Die minimale Implementierung von Arbitrary ist die arbitrary Methode, die in der Gen Monade ausgeführt wird, um einen zufälligen Wert zu erzeugen.

Hier ist eine Instanz von Arbitrary für den folgenden Datentyp von nicht leeren Listen.

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
        ]

Verwenden von implication (==>) zum Prüfen von Eigenschaften mit Vorbedingungen

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

Wenn Sie prüfen möchten, ob eine Eigenschaft erfüllt ist, wenn eine Vorbedingung erfüllt ist, können Sie den Operator ==> . Wenn es sehr unwahrscheinlich ist, dass willkürliche Eingaben der Vorbedingung entsprechen, kann QuickCheck frühzeitig aufgeben.

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

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

Begrenzung der Größe der Testdaten

Es ist schwierig, Funktionen mit geringer asymptotischer Komplexität mithilfe von Quickcheck zu testen, da die zufälligen Eingaben normalerweise nicht an die Größe gebunden sind. Durch Hinzufügen einer Obergrenze für die Größe der Eingabe können wir diese teuren Funktionen noch 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

Durch die Verwendung von quickCheckWith mit einer modifizierten Version von stdArgs wir die Größe der Eingaben auf höchstens 10 begrenzen. stdArgs wir Listen erstellen, bedeutet dies, dass wir Listen bis Größe 10 generieren. Unsere Permutationsfunktion funktioniert nicht Es dauert zu lange, um für diese kurzen Listen zu rennen, aber wir können immer noch recht sicher sein, dass unsere Definition richtig ist.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow