2013-08-23 2 views
6

I eine Funktion mit der folgenden Art Signatur habenHaskell Quick Check erzeugt Zufallsdaten für die Funktion mit vielen Eingangsvariablen

rndListIndex :: Double -> Double -> Double -> Double 
rndListIndex maxIdx r1 r2 = … 
  • der erste Eingang ein Wert kommt aus einer nicht negativen streng positiven ganzen Zahl sein sollte,
  • ist der zweite und dritte Eingang erforderlich innerhalb des geschlossenen Intervalls [0.0,1.0] sein, da sonst die Funktion macht keinen Sinn

die Funktion hat die Eigenschaft,

prop_alwaysLessThanMaxIdx idx r1 r2 = (rndListIndex idx r1 r2 <= idx) 

wie kann ich zufällige Daten für maxIdx und r1, r2 separat erzeugen; Ich kenne die Funktion choose aber weiß nicht, wie man es mit mehr als einer Eingabevariablen benutzt.

Für jetzt habe ich die Eigenschaft mit festen idx getestet, die nicht die Art ist, wie es getestet werden sollte.

+0

Kann der erste Wert 0 sein? – bennofs

+0

Nun, da ich daran denke nein sollte es nicht - ich werde die Frage bearbeiten. – epsilonhalbe

Antwort

12

Sie müssen die Funktion forAll von QuickCheck verwenden. Er hat die folgende Art:

forAll :: (Show a, Testable prop) 
     => Gen a   --^The generator to use for generating values 
     -> (a -> prop)  --^A function which returns a testable property 
     -> Property     

forAll zwei Argumente:

  • Der Generator beschreibt, wie Werte zu erzeugen. Beispiele für Generatoren sind choose, arbitrary, oneof, ...
  • Die Funktion testet die Eigenschaft für die angegebene Eingabe. Es muss einen Wert zurückgeben, der eine Instanz von Testable ist, zum Beispiel ein anderer Property, Bool oder eine Funktion.

Beispiel einer verschachtelten forAll mit wählen und Elemente Generatoren:

-- This generates a Property p for all x's in the closed interval [1,3] 
-- The property p in turn generates a property q for all y ∈ [4,5] 
-- The property q is True if x < y. 
prop_choose = forAll (choose (1,3)) $ \x -> 
       forAll (elements [4,5]) $ \y -> x < y 

Für Ihre Testeigenschaft, können Sie mit wählen für das zweite und dritte Argument verwenden forAll. Zum ersten Argumente gibt es den Positive a Typen in Quick Check, die verwendet werden können beliebige positive Werte vom Typ A zu erzeugen (es hat eine beliebige Instanz, wenn a eine Num):

prop_alwayLessThanMaxIdx :: Positive Integer -> Property 
prop_alwaysLessThanMaxIdx (Positive idx) = 
    forAll (choose (0,1)) $ \r1 -> 
    forAll (choose (0,1)) $ \r2 -> 
    (rndListIndex idx r1 r2) < idx 
1

würde ich vorschlagen, die Definition Ihres eigene Art, die Double und geben ihm eine Arbitrary Instanz umschließt, dass nur Zahlen zwischen 0 und 1. so etwas erzeugt: idx

import Test.QuickCheck 
newtype UnitInterval = Unit Double deriving Show 

instance Arbitrary UnitInterval where 
    arbitrary = fmap Unit (choose (0, 1)) 
    shrink (Unit x) = [ Unit y | y <- shrink x, 0 <= y && y <= 1 ] 

Zum Erzeugen Sie Positive Modifikator des Quick Check verwenden können, wie @bennoffs vorgeschlagen (Sie müssen zu importieren Test.QuickCheck.Modifiers). Dies ist ähnlich dem UnitInterval Typ I oben definiert sind, sondern erzeugt positive Zahlen anstelle von Zahlen zwischen 0 und 1. Ihre Immobilie wird wie dann aussehen:

prop_alwaysLessThanMaxIdx (Positive idx) (Unit r1) (Unit r2) = 
    rndListIndex idx r1 r2 <= idx