Funktionale Programmierung

Werbung
Quickcheck
Funktionale Programmierung
Fallstudie Quickcheck
D. Rösner
Institut für Wissens- und Sprachverarbeitung
Fakultät für Informatik
Otto-von-Guericke Universität Magdeburg
c
Sommer 2010, 18. Mai 2010, 2010
D.Rösner
D. Rösner FP 2010 . . .
1
Quickcheck
Gliederung
1
Quickcheck
Einführung
Generatoren
Testen
Weitere Aspekte
D. Rösner FP 2010 . . .
2
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Gliederung
1
Quickcheck
Einführung
Generatoren
Testen
Weitere Aspekte
D. Rösner FP 2010 . . .
3
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck
Quelle:
http://www.cs.chalmers.se/~rjmh/QuickCheck
D. Rösner FP 2010 . . .
4
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck
Quelle:
http://www.cs.chalmers.se/~rjmh/QuickCheck
Grundidee: Benutzer definiert Eigenschaften, die ein
Programm erfüllen soll
D. Rösner FP 2010 . . .
4
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck
Quelle:
http://www.cs.chalmers.se/~rjmh/QuickCheck
Grundidee: Benutzer definiert Eigenschaften, die ein
Programm erfüllen soll
diese Eigenschaften werden dann an einer grossen Zahl
automatisch generierter Testfälle überprüft
D. Rösner FP 2010 . . .
4
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Beispiel:
Definition einer Eigenschaft
prop_RevRev xs = reverse(reverse xs) == xs
where types = xs::[Int]
D. Rösner FP 2010 . . .
5
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Beispiel:
Definition einer Eigenschaft
prop_RevRev xs = reverse(reverse xs) == xs
where types = xs::[Int]
Testen einer Eigenschaft
QuickCheckTest> quickCheck prop_RevRev
OK, passed 100 tests.
D. Rösner FP 2010 . . .
5
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Beispiel:
Definition einer Eigenschaft
prop_RevId xs = reverse xs == xs
where types = xs::[Int]
Testen und Falsifizieren einer Eigenschaft
QuickCheckTest> quickCheck prop_RevId
Falsifiable, after 4 tests:
[-4,-3,4]
D. Rösner FP 2010 . . .
6
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Beispiel: ausführliches Ablaufprotokoll:
QuickCheckTest> verboseCheck prop_RevId
0:
[]
1:
[-1]
2:
[]
3:
[0,-4,0]
4:
[1,0]
Falsifiable, after 4 tests:
[1,0]
D. Rösner FP 2010 . . .
7
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Gliederung
1
Quickcheck
Einführung
Generatoren
Testen
Weitere Aspekte
D. Rösner FP 2010 . . .
8
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
zentral sind Generatoren für Testdaten
D. Rösner FP 2010 . . .
9
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
zentral sind Generatoren für Testdaten
Typ:
newtype Gen a
= Gen (Int -> StdGen -> a)
D. Rösner FP 2010 . . .
9
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
zentral sind Generatoren für Testdaten
Typ:
newtype Gen a
= Gen (Int -> StdGen -> a)
Typ Gen ist Funktor und Monade
D. Rösner FP 2010 . . .
9
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Definition als Funktor:
instance Functor Gen where
fmap f m = m >>= return . f
D. Rösner FP 2010 . . .
10
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Definition als Funktor:
instance Functor Gen where
fmap f m = m >>= return . f
Definition als Monade:
instance Monad Gen where
return a
= Gen (\n r -> a)
Gen m >>= k =
Gen (\n r0 -> let (r1,r2) = split r0
Gen m’ = k (m n r1)
in m’ n r2)
D. Rösner FP 2010 . . .
10
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
zentrale Funktion:
choose :: Random a => (a, a) -> Gen a
choose bounds = (fst . randomR bounds) ‘fmap‘ rand
rand :: Gen StdGen
rand = Gen (\n r -> r)
D. Rösner FP 2010 . . .
11
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Kombinatoren für Generatoren:
Auswahl aus einer Liste von Generatoren
oneof :: [Gen a] -> Gen a
oneof gens = elements gens >>= id
D. Rösner FP 2010 . . .
12
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Kombinatoren für Generatoren:
Auswahl aus einer Liste von Generatoren
oneof :: [Gen a] -> Gen a
oneof gens = elements gens >>= id
Beispiel:
oneof [return True, return False]
D. Rösner FP 2010 . . .
12
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Kombinatoren für Generatoren:
Beeinflussung der Verteilung:
frequency :: [(Int, Gen a)] -> Gen a
frequency xs = choose (1, tot) >>= (‘pick‘ xs)
where
tot = sum (map fst xs)
pick n ((k,x):xs)
| n <= k
= x
| otherwise = pick (n-k) xs
D. Rösner FP 2010 . . .
13
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
Kombinatoren für Generatoren:
Beeinflussung der Verteilung:
frequency :: [(Int, Gen a)] -> Gen a
frequency xs = choose (1, tot) >>= (‘pick‘ xs)
where
tot = sum (map fst xs)
pick n ((k,x):xs)
| n <= k
= x
| otherwise = pick (n-k) xs
Beispiel:
frequency [(2,return True), (1,return False)]
D. Rösner FP 2010 . . .
13
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
vordefinierte Generatoren für zahlreiche Typen
Überladen der Methoden der Klasse Arbitrary
class Arbitrary a where
arbitrary
:: Gen a
coarbitrary :: a -> Gen b -> Gen b
D. Rösner FP 2010 . . .
14
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
vordefinierte Generatoren für zahlreiche Typen
Überladen der Methoden der Klasse Arbitrary
class Arbitrary a where
arbitrary
:: Gen a
coarbitrary :: a -> Gen b -> Gen b
arbitrary . . . für zufällige Werte des Typs a
D. Rösner FP 2010 . . .
14
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
vordefinierte Generatoren für zahlreiche Typen
Überladen der Methoden der Klasse Arbitrary
class Arbitrary a where
arbitrary
:: Gen a
coarbitrary :: a -> Gen b -> Gen b
arbitrary . . . für zufällige Werte des Typs a
coarbitrary . . . für zufällige Funktionen des Typs a-> b
D. Rösner FP 2010 . . .
14
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
vordefinierte Generatoren für zahlreiche Typen
Beispiel: Typ Arbitrary Int
instance Arbitrary Int where
arbitrary
= sized $ \n -> choose (-n,n)
coarbitrary n
= variant (if n >= 0 then 2*n else 2*(-n) + 1)
D. Rösner FP 2010 . . .
15
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
vordefinierte Generatoren für zahlreiche Typen
Beispiel: Typ Arbitrary (a, b):
instance (Arbitrary a, Arbitrary b) => Arbitrary (a, b)
where
arbitrary
= liftM2 (,) arbitrary arbitrary
coarbitrary (a, b) = coarbitrary a . coarbitrary b
D. Rösner FP 2010 . . .
16
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: QuickCheck
vordefinierte Generatoren für zahlreiche Typen
Beispiel: Typ Arbitrary (a, b):
instance (Arbitrary a, Arbitrary b) => Arbitrary (a, b)
where
arbitrary
= liftM2 (,) arbitrary arbitrary
coarbitrary (a, b) = coarbitrary a . coarbitrary b
verwendet wird hier die monadische Funktion liftM2
liftM2 :: (Monad m) => (a -> b -> c) -> (m a -> m b -> m c)
liftM2 f = \a b -> do { a’ <- a; b’ <- b; return (f a’ b’) }
D. Rösner FP 2010 . . .
16
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Gliederung
1
Quickcheck
Einführung
Generatoren
Testen
Weitere Aspekte
D. Rösner FP 2010 . . .
17
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck erlaubt
Testen bedingter Eigenschaften
D. Rösner FP 2010 . . .
18
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck erlaubt
Testen bedingter Eigenschaften
Testen quantifizierter Eigenschaften
D. Rösner FP 2010 . . .
18
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck erlaubt
Testen bedingter Eigenschaften
Testen quantifizierter Eigenschaften
Steuerung der Verteilung der Testfälle
D. Rösner FP 2010 . . .
18
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck erlaubt
Testen bedingter Eigenschaften
Testen quantifizierter Eigenschaften
Steuerung der Verteilung der Testfälle
Klassifizieren und Zählen von Testfällen
D. Rösner FP 2010 . . .
18
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Fallstudie: Testen von Haskell-Programmen
Programm QuickCheck erlaubt
Testen bedingter Eigenschaften
Testen quantifizierter Eigenschaften
Steuerung der Verteilung der Testfälle
Klassifizieren und Zählen von Testfällen
Sammeln von Datenwerten
D. Rösner FP 2010 . . .
18
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen bedingter Eigenschaften
Eigenschaft können die Form haben
<condition> ==> <property>
D. Rösner FP 2010 . . .
19
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen bedingter Eigenschaften
Eigenschaft können die Form haben
<condition> ==> <property>
eine solche Eigenschaft gilt genau dann, wenn die
Eigenschaft nach dem ==> immer gilt, wenn die
<condition> gilt
D. Rösner FP 2010 . . .
19
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen bedingter Eigenschaften
Eigenschaft können die Form haben
<condition> ==> <property>
eine solche Eigenschaft gilt genau dann, wenn die
Eigenschaft nach dem ==> immer gilt, wenn die
<condition> gilt
beim Testen werden nur Testfälle betrachtet, welche die
<condition> erfüllen ; falls nach einer vorgegebenen
Anzahl von Versuchen (derzeit: 1000) noch keine 100
Testfälle gefunden, wird beendet und Meldung
ausgegeben wie
Arguments exhausted after 97 test.
D. Rösner FP 2010 . . .
19
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen quantifizierter Eigenschaften
Eigenschaften können die Form haben
forAll <generator> $ \<pattern> -> <property>
D. Rösner FP 2010 . . .
20
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen quantifizierter Eigenschaften
Eigenschaften können die Form haben
forAll <generator> $ \<pattern> -> <property>
Beispiel:
prop_Insert2 x
= forAll orderedList $ \xs -> ordered (insert x xs)
where types = x::Int
D. Rösner FP 2010 . . .
20
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen quantifizierter Eigenschaften
Eigenschaften können die Form haben
forAll <generator> $ \<pattern> -> <property>
Beispiel:
prop_Insert2 x
= forAll orderedList $ \xs -> ordered (insert x xs)
where types = x::Int
das erste Argument des forAll ist ein
Testdatengenerator
D. Rösner FP 2010 . . .
20
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Testen quantifizierter Eigenschaften
Eigenschaften können die Form haben
forAll <generator> $ \<pattern> -> <property>
Beispiel:
prop_Insert2 x
= forAll orderedList $ \xs -> ordered (insert x xs)
where types = x::Int
das erste Argument des forAll ist ein
Testdatengenerator
mit solchen speziellen Generatoren lässt sich die
Verteilung der Testdaten besser kontrollieren als durch
Filtern
D. Rösner FP 2010 . . .
20
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Zählen trivialer Fälle
Eigenschaften können die Form haben
<condition> ‘trivial‘ <property>
D. Rösner FP 2010 . . .
21
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Zählen trivialer Fälle
Eigenschaften können die Form haben
<condition> ‘trivial‘ <property>
Beispiel:
prop_Insert x xs = ordered xs
==> null xs ‘trivial‘ ordered (insert x xs)
where types = x::Int
D. Rösner FP 2010 . . .
21
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Zählen trivialer Fälle
Eigenschaften können die Form haben
<condition> ‘trivial‘ <property>
Beispiel:
prop_Insert x xs = ordered xs
==> null xs ‘trivial‘ ordered (insert x xs)
where types = x::Int
Testfälle, für die Bedingung zutrifft, werden als trivial
klassifiziert
D. Rösner FP 2010 . . .
21
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Zählen trivialer Fälle
Eigenschaften können die Form haben
<condition> ‘trivial‘ <property>
Beispiel:
prop_Insert x xs = ordered xs
==> null xs ‘trivial‘ ordered (insert x xs)
where types = x::Int
Testfälle, für die Bedingung zutrifft, werden als trivial
klassifiziert
der Anteil dieser Fälle wird im Gesamtergebnis angegeben
D. Rösner FP 2010 . . .
21
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Eigenschaften können die Form haben
classify <condition> <string>$ <property>
Beispiel:
prop_Insert x xs =
ordered xs ==>
classify (ordered (x:xs)) "at-head"$
classify (ordered (xs++[x])) "at-tail"$
ordered (insert x xs)
where types = x::Int
Verteilung der Testfälle (die mehreren Kategorien
angehören können) wird berichtet
D. Rösner FP 2010 . . .
22
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Eigenschaften können die Form haben
collect <expression>$ <property>
Beispiel:
prop_Insert x xs =
ordered xs ==> collect (length xs)$
ordered (insert x xs)
where types = x::Int
die Verteilung der Werte des Arguments von collect
wird berichtet
D. Rösner FP 2010 . . .
23
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
Kombinatoren, die Generatoren produzieren:
elements . . . erzeuge zu einem aus einer Liste zufällig
ausgewählten Element einen Generator
elements :: [a] -> Gen a
elements xs
= (xs !!) ‘fmap‘ choose (0, length xs - 1)
D. Rösner FP 2010 . . .
24
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
Kombinatoren, die Generatoren produzieren:
elements . . . erzeuge zu einem aus einer Liste zufällig
ausgewählten Element einen Generator
elements :: [a] -> Gen a
elements xs
= (xs !!) ‘fmap‘ choose (0, length xs - 1)
Beispiele:
QuickCheck> [generate 5 (mkStdGen i)
(choose (’a’,’f’))|i<-[0..30]]
"edccbaffedccbaffedccbaffedccbaf"
QuickCheck> [generate 5 (mkStdGen i)
(elements [’a’..’z’])|i<-[0..30]]
"bktdcluedmvfenwgfoxhgpyihqzjira"
D. Rösner FP 2010 . . .
24
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
Kombinatoren, die Generatoren produzieren:
vector . . . produziere einen Generator für Listen mit n
zufälligen Elementen
vector :: Arbitrary a => Int -> Gen [a]
vector n = sequence [ arbitrary | i <- [1..n] ]
D. Rösner FP 2010 . . .
25
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
Kombinatoren, die Generatoren produzieren:
vector . . . produziere einen Generator für Listen mit n
zufälligen Elementen
vector :: Arbitrary a => Int -> Gen [a]
vector n = sequence [ arbitrary | i <- [1..n] ]
Beispiele:
QuickCheck> generate 10 (mkStdGen 3) ( vector 10)::[[Int]]
[[-2,5,5,1,-3],[-1,-3],[-6,-6],[-2,-6,0,-6,-1],[4,1,-4,-5],
[2,-3,-3],[-3],[],[-2,5,3,2,5,2],[]]
QuickCheck> generate 10 (mkStdGen 9) ( vector 12)::[Float]
[-4.75,1.333333,-1.0,-5.333333,3.2,-3.2,4.0,-5.0,3.333333,
3.0,0.4,0.0]
D. Rösner FP 2010 . . .
25
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
die Definition von vector verwendet die allgemeine
monadische Funktion sequence, die aus einer Liste von
Monadeninstanzen eine Monadeninstanz für eine Liste
produziert
D. Rösner FP 2010 . . .
26
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
die Definition von vector verwendet die allgemeine
monadische Funktion sequence, die aus einer Liste von
Monadeninstanzen eine Monadeninstanz für eine Liste
produziert
im Prelude.hs:
sequence
:: Monad m => [m a] -> m [a]
sequence []
= return []
sequence (c:cs) = do x <- c
xs <- sequence cs
return (x:xs)
D. Rösner FP 2010 . . .
26
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
generate . . . Funktion, um Testgeneratoren zur
Ausführung zu bringen
generate :: Int -> StdGen -> Gen a -> a
generate n rnd (Gen m) = m size rnd’
where
(size, rnd’) = randomR (0, n) rnd
Erläuterung:
mit Hilfe des Zufallsgenerators rnd wird im Bereich von 0
bis n ein Wert für size bestimmt
der Testdatengenerator wird dann mit size und der
Fortschreibung rnd’ von rnd angewendet
D. Rösner FP 2010 . . .
27
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
einige Anwendungen von generate:
QuickCheck> (generate 20 (mkStdGen 2) (variant 5 arbitrary))::[Float]
[3.4,-3.0,1.166667,-5.4,8.3,-3.0,1.0,-9.2,7.222222]
QuickCheck> (generate 20 (mkStdGen 2) (variant 6 arbitrary))::[Float]
[]
QuickCheck> (generate 20 (mkStdGen 2) (variant 7 arbitrary))::[Float]
[-4.0,-3.916667,11.2,-1.166667,4.0,11.8,4.333333,-7.625]
QuickCheck> generate 10 (mkStdGen 3) ( vector 10)::[Float]
[-4.666667,-1.166667,-3.5,4.0,6.666667,0.2857143,-5.6,2.0,1.333333,-2.
D. Rösner FP 2010 . . .
28
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
variant . . . Kombinator, um zu Generator gezielt
Varianten erzeugen zu können
D. Rösner FP 2010 . . .
29
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
variant . . . Kombinator, um zu Generator gezielt
Varianten erzeugen zu können
variant :: Int -> Gen a -> Gen a
variant v (Gen m) = Gen (\n r -> m n (rands r !! (v+1)))
where
rands r0 = r1 : rands r2 where (r1, r2) = split r0
D. Rösner FP 2010 . . .
29
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Implementation
variant . . . Kombinator, um zu Generator gezielt
Varianten erzeugen zu können
variant :: Int -> Gen a -> Gen a
variant v (Gen m) = Gen (\n r -> m n (rands r !! (v+1)))
where
rands r0 = r1 : rands r2 where (r1, r2) = split r0
durch wiederholtes Anwenden von split wird aus dem
übergebenen Zufallsgenerator eine Liste von
Zufallsgeneratoren erzeugt, aus der dann das (v+1)-te
Element entnommen und dann im Testgenerator
verwendet wird
D. Rösner FP 2010 . . .
29
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Gliederung
1
Quickcheck
Einführung
Generatoren
Testen
Weitere Aspekte
D. Rösner FP 2010 . . .
30
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: weitere Aspekte der Implementation
Konfigurationen als Daten
data Config
{ maxTest
, maxFail
, size
, every
}
= Config
:: Int
:: Int
:: Int -> Int
:: Int -> [String] -> String
D. Rösner FP 2010 . . .
31
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Konfigurationen als Daten
Beispiel:
quick :: Config
quick = Config
{ maxTest = 100
, maxFail = 1000
, size
= (+ 3) . (‘div‘ 2)
, every
= \n args -> let s = show n
in s ++ [ ’\b’ | _ <- s ]
}
D. Rösner FP 2010 . . .
32
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Konfigurationen als Daten
Spezialisierung
verbose :: Config
verbose = quick
{ every = \n args -> show n ++ ":\n"
++ unlines args
}
D. Rösner FP 2010 . . .
33
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Konfigurationen als Daten
Spezialisierung
verbose :: Config
verbose = quick
{ every = \n args -> show n ++ ":\n"
++ unlines args
}
die vordefinierten Toplevel-Funktionen
test, quickCheck, verboseCheck
:: Testable a => a -> IO ()
test
= check quick
quickCheck
= check quick
verboseCheck = check verbose
D. Rösner FP 2010 . . .
33
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: die Funktion check
check :: Testable a => Config -> a -> IO ()
check config a =
do rnd <- newStdGen
tests config (evaluate a) rnd 0 0 []
D. Rösner FP 2010 . . .
34
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: die Funktion check
check :: Testable a => Config -> a -> IO ()
check config a =
do rnd <- newStdGen
tests config (evaluate a) rnd 0 0 []
aus Random.hs:
newStdGen
newStdGen
:: IO StdGen
= do rng <- getStdGen
let (a,b) = split rng
setStdGen a
return b
D. Rösner FP 2010 . . .
34
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: die Funktion tests
tests :: Config -> Gen Result -> StdGen -> Int -> Int -> [[String]] -> IO ()
tests config gen rnd0 ntest nfail stamps
| ntest == maxTest config = do done "OK, passed" ntest stamps
| nfail == maxFail config = do done "Arguments exhausted after" ntest stamps
| otherwise
=
do putStr (every config ntest (arguments result))
case ok result of
Nothing
->
tests config gen rnd1 ntest (nfail+1) stamps
Just True ->
tests config gen rnd1 (ntest+1) nfail (stamp result:stamps)
Just False ->
putStr ( "Falsifiable, after "
++ show ntest
++ " tests:\n"
++ unlines (arguments result)
)
where
result
= generate (size config ntest) rnd2 gen
(rnd1,rnd2) = split rnd0
D. Rösner FP 2010 . . .
35
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: der Datentyp Result
Definition:
data Result
= Result { ok :: Maybe Bool,
stamp :: [String],
arguments :: [String] }
D. Rösner FP 2010 . . .
36
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: der Datentyp Result
Definition:
data Result
= Result { ok :: Maybe Bool,
stamp :: [String],
arguments :: [String] }
Beispiel:
nothing :: Result
nothing = Result{ ok = Nothing,
stamp = [],
arguments = [] }
D. Rösner FP 2010 . . .
36
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Repräsentation testbarer Prädikate
Typ Property
newtype Property = Prop (Gen Result)
D. Rösner FP 2010 . . .
37
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Repräsentation testbarer Prädikate
Typ Property
newtype Property = Prop (Gen Result)
Klasse Testable
class Testable a where
property :: a -> Property
D. Rösner FP 2010 . . .
37
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck: Repräsentation testbarer Prädikate
zugehörige Funktionen:
result :: Result -> Property
result res = Prop (return res)
evaluate :: Testable a => a -> Gen Result
evaluate a = gen
where Prop gen = property a
D. Rösner FP 2010 . . .
38
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Elemente der Sprache für testbare Spezifikationen
forAll
forAll :: (Show a, Testable b)
=> Gen a -> (a -> b) -> Property
forAll gen body = Prop $
do a
<- gen
res <- evaluate (body a)
return (argument a res)
where
argument a res
= res{ arguments = show a : arguments res }
D. Rösner FP 2010 . . .
39
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Elemente der Sprache für testbare Spezifikationen
(==>)
(==>) :: Testable a => Bool -> a -> Property
True ==> a = property a
False ==> a = property ()
D. Rösner FP 2010 . . .
40
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Elemente der Sprache für testbare Spezifikationen
(==>)
(==>) :: Testable a => Bool -> a -> Property
True ==> a = property a
False ==> a = property ()
label
label :: Testable a
=> String -> a -> Property
label s a = Prop (add ‘fmap‘ evaluate a)
where
add res = res{ stamp = s : stamp res }
D. Rösner FP 2010 . . .
40
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Elemente der Sprache für testbare Spezifikationen
classify
classify :: Testable a
=> Bool -> String -> a -> Property
classify True name = label name
classify False _
= property
D. Rösner FP 2010 . . .
41
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
QuickCheck
Elemente der Sprache für testbare Spezifikationen
classify
classify :: Testable a
=> Bool -> String -> a -> Property
classify True name = label name
classify False _
= property
trivial
trivial :: Testable a
=> Bool -> a -> Property
trivial = (‘classify‘ "trivial")
D. Rösner FP 2010 . . .
41
Quickcheck
Einführung Generatoren Testen Weitere Aspekte
Literatur: I
Paul Hudak.
The Haskell School of Expression – Learning Functional
Programming through Multimedia.
Cambridge University Press, Cambridge, UK, 2000.
ISBN 0-521-64338-4.
Simon Thompson.
Haskell - The Craft of Functional Programming.
Addison Wesley Longman Ltd., Essex, 1999.
2nd edition, ISBN 0-201-34275-8; Accompanying Web site:
http://www.cs.ukc.ac.uk/people/staff/sjt/craft2e.
D. Rösner FP 2010 . . .
42
Herunterladen