Einführende Beispiele QuickCheck


... [ Seminar "Haskell" ] ... [ Inhaltsverzeichnis ] ... [ zurück ] ... [ weiter ] ...

Übersicht: Einführende Beispiele QuickCheck


Testqualität - Quantified Properties

Die folgenden Beispiele zur Testqualität baerreciht sieren alle auf dem in vorangegangen Abschnitt eingeführten Beispiels insertOrdered.
Es werden stückweise neue Kombinatoren vorgestellt. Der besseren Lesbarkeit wegen sind Teile der Beispiele doppelt aufgeführt.

Über den Kombinator forAll ist es möglich die Generierung der Testdaten zu steuern.

01 forAll <generator> $ \<pattern> -> <property>
quantified_properties.hs

Codebeispiel 8

01 import QuickCheck
02 
03 insertOrdered :: (Ord a) => a -> [a] -> [a] -> [a]
04 insertOrdered a [] ys = ys++[a] 
05 insertOrdered a (x:xs) ys
06 	| a <= x = ys ++ a:[x] ++ xs
07 	| a > x = insertOrdered a xs (ys ++ [x]) 
08 	
09 ordered :: (Ord a) => [a] -> Bool
10 ordered [] = True
11 ordered [x] = True
12 ordered (x1:x2:xs)
13 	| x1 <= x2 = True && ordered (x2:xs)
14 	| x1 > x2 = False
15 
16 prop_InsertOrderedInt :: Integer -> Property 
17 prop_InsertOrderedInt x = forAll orderedList $ \xs -> ordered (insertOrdered x xs [])
18 
19 orderedList :: (Ord a, Arbitrary a) => Gen [a]
20 orderedList = 
21  frequency [(1,return []),
22 	    (4,do xs <- orderedList
23 	          n <- arbitrary
24 	          return ((case xs of
25 	      	     	  [] -> n 
26 	      	     	  x:_ -> n `min` x)
27 		          :xs))]
complexProp3.hs

Codebeispiel 9

In diesem Beispiel wird der forAll Kombinator mit dem Generator orderedList verwendet. Dieser sorgt für die Erzeugung der Listen.

Main> quickCheck prop_InsertOrderedInt
OK, passed 100 tests. (451382 reductions, 954722 cells, 4 garbage collections)


[ nach oben ]

Testqualität - Classifying Test Cases

Als weiterer Kombinator steht der classify Kombinator zur Verfügung. Mit ihm ist es möglich bezüglich der Testdatenverteilung ein Einteilung in folgender Form vorzunehmen:

01 classify <condition> <string>$ <property>
classify_properties.hs

Codebeispiel 10

01 import QuickCheck
02 
03 insertOrdered :: (Ord a) => a -> [a] -> [a] -> [a]
04 insertOrdered a [] ys = ys++[a] 
05 insertOrdered a (x:xs) ys
06 	| a <= x = ys ++ a:[x] ++ xs
07 	| a > x = insertOrdered a xs (ys ++ [x]) 
08 	
09 ordered :: (Ord a) => [a] -> Bool
10 ordered [] = True
11 ordered [x] = True
12 ordered (x1:x2:xs)
13 	| x1 <= x2 = True && ordered (x2:xs)
14 	| x1 > x2 = False
15 
16 prop_InsertOrderedInt :: Integer -> [Integer] -> Property 
17 prop_InsertOrderedInt x xs = ordered xs ==>
18 	 	classify (ordered (x:xs)) "at-head"$
19  		classify (ordered (xs++[x])) "at-tail"$
20 	 	ordered (insertOrdered x xs [])
21 
testQual2.hs

Codebeispiel 11

In Zeile 18 wird der Fall, dass das Element als Kopf der Liste angefügt wird und in Zeile 19 der Fall, dass das Element am Ende der Liste angefügt wird, klassifiziert und die jeweiligen Namen für die Ausgabe definiert.

Main> quickCheck prop_InsertOrderedInt
OK, passed 100 tests.
48% at-head, at-tail.
25% at-head.
20% at-tail. (555980 reductions, 1328383 cells, 5 garbage collections)


[ nach oben ]

Testqualität - Observing Test Case Distribution

Eine weitere Möglichkeit der an spezifische Bedürfnisse anpassbare Kontrolle der Testdaten ist die folgende: Über den Kombinator condition ist die Auszeichnung der Fälle mit entsprechenden Namen möglich.

01 <condition> `trivial` <property>
observing_test_cases.hs

Codebeispiel 12

01 import QuickCheck
02 
03 insertOrdered :: (Ord a) => a -> [a] -> [a] -> [a]
04 insertOrdered a [] ys = ys++[a] 
05 insertOrdered a (x:xs) ys
06 	| a <= x = ys ++ a:[x] ++ xs
07 	| a > x = insertOrdered a xs (ys ++ [x]) 
08 	
09 ordered :: (Ord a) => [a] -> Bool
10 ordered [] = True
11 ordered [x] = True
12 ordered (x1:x2:xs)
13 	| x1 <= x2 = True && ordered (x2:xs)
14 	| x1 > x2 = False
15 
16 prop_InsertOrderedInt :: Integer -> [Integer] -> Property 
17 prop_InsertOrderedInt x xs = ordered xs ==>
18 	 	null xs `trivial` 
19 	 	ordered (insertOrdered x xs [])
20 
21 orderedList :: (Ord a, Arbitrary a) => Gen [a]
22 orderedList = 
23  frequency [(1,return []),
24 	    (4,do xs <- orderedList
25 	          n <- arbitrary
26 	          return ((case xs of
27 	      	     	  [] -> n 
28 	      	     	  x:_ -> n `min` x)
29 		          :xs))]
testQual3.hs

Codebeispiel 13

Die Ausführung des Tests prop_InsertOrderedInt und prop_InsertOrderedInt2 liefert folgende Ergebnisse. Der Vergleich zwischen den gefilterten automatisch, zufallstbedingt erzeugten Listen und die über den Generator orderedList erzeugten Listen ist interessant:

Main> quickCheck prop_InsertOrderedInt
OK, passed 100 tests (53% trivial).
Main> quickCheck prop_InsertOrderedInt2
OK, passed 100 tests (19% trivial)


[ nach oben ]

Testqualität - Collecting Data Values

Über den collect Kombinator ist es möglich, die Verteilung auf Basis der Ausprägungen eines Merkmales zu kontrollieren.

01 collect <expression>$ <property>
collecting_data_values.hs

Codebeispiel 14

01 import QuickCheck
02 
03 insertOrdered :: (Ord a) => a -> [a] -> [a] -> [a]
04 insertOrdered a [] ys = ys++[a] 
05 insertOrdered a (x:xs) ys
06 	| a <= x = ys ++ a:[x] ++ xs
07 	| a > x = insertOrdered a xs (ys ++ [x]) 
08 	
09 ordered :: (Ord a) => [a] -> Bool
10 ordered [] = True
11 ordered [x] = True
12 ordered (x1:x2:xs)
13 	| x1 <= x2 = True && ordered (x2:xs)
14 	| x1 > x2 = False
15 	
16 
17 prop_InsertOrderedInt :: Integer -> [Integer] -> Property 
18 prop_InsertOrderedInt x xs = ordered xs ==>
19 	 	collect (length xs)$  
20 	 	ordered (insertOrdered x xs [])
21 	 	
22 prop_InsertOrderedInt2 :: Integer -> Property 
23 prop_InsertOrderedInt2 x = forAll orderedList $ \ xs ->
24 	 	collect (length xs)$  
25 	 	ordered (insertOrdered x xs [])
26 
27 orderedList :: (Ord a, Arbitrary a) => Gen [a]
28 orderedList = 
29  frequency [(1,return []),
30 	    (4,do xs <- orderedList
31 	          n <- arbitrary
32 	          return ((case xs of
33 	      	     	  [] -> n 
34 	      	     	  x:_ -> n `min` x)
35 		          :xs))]
36 
37 	 	
testQual4.hs

Codebeispiel 15

Die Ausführung des Tests prop_InsertOrderedInt und prop_InsertOrderedInt2 liefert folgende Ergebnisse: Auch hier ist der Vergleich zwischen den gefilterten automatisch, zufallstbedingt erzeugten Listen und die über den Generator orderedList erzeugten Listen interessant. Durch diesen Kombinator erhalten wir deutlich mehr Informationen über die Verteilung der Testfälle:

Main> quickCheck prop_InsertOrderedInt
OK, passed 100 tests.
54% 0.
28% 1.
13% 2.
3% 3.
1% 5.
1% 4.

Main> quickCheck prop_InsertOrderedInt2
OK, passed 100 tests.
27% 0.
16% 1.
9% 4.
9% 3.
7% 2.
6% 8.
5% 5.
5% 12.
4% 7.
4% 6.
3% 11.
2% 9.
1% 22.
1% 18.
1% 13.


[ nach oben ]

Testqualität - Combining Observations

Die bis jetzt kennengelernten Kombinatoren ermöglichen eine beliebige Kombination untereinander.
Die soll folgendes Besipiel zeigen:

01 import QuickCheck
02 
03 insertOrdered :: (Ord a) => a -> [a] -> [a] -> [a]
04 insertOrdered a [] ys = ys++[a] 
05 insertOrdered a (x:xs) ys
06 	| a <= x = ys ++ a:[x] ++ xs
07 	| a > x = insertOrdered a xs (ys ++ [x]) 
08 	
09 ordered :: (Ord a) => [a] -> Bool
10 ordered [] = True
11 ordered [x] = True
12 ordered (x1:x2:xs)
13 	| x1 <= x2 = True && ordered (x2:xs)
14 	| x1 > x2 = False
15 
16 prop_InsertOrderedInt :: Integer -> [Integer] -> Property 
17 prop_InsertOrderedInt x xs = ordered xs ==>
18 	 		collect (length xs)$
19 			classify (ordered (x:xs)) "at-head"$
20  			classify (ordered (xs++[x])) "at-tail"$
21 			ordered (insertOrdered x xs [])
22 						
23   		
testQual5.hs

Codebeispiel 16

Die Ausführung des Tests prop_InsertOrderedInt liefert folgendes Ergebnis:

Main> quickCheck prop_InsertOrderedInt
OK, passed 100 tests.
45% 0, at-head, at-tail.
17% 1, at-tail.
17% 1, at-head.
6% 1, at-head, at-tail.
5% 2, at-tail.
5% 2, at-head.
2% 3, at-head.
1% 3, at-tail.
1% 2, at-head, at-tail.
1% 2.

... [ Seminar "Haskell" ] ... [ Inhaltsverzeichnis ] ... [ zurück ] ... [ weiter ] ... [ nach oben ] ...

valid html4 logo Code generated with AusarbeitungGenerator Version 1.1, weblink