2013-08-23 23 views
6

Mam funkcji z następującym podpisem typuHaskell QuickCheck generowania losowych danych dla funkcji wielu zmiennych wejściowych

rndListIndex :: Double -> Double -> Double -> Double 
rndListIndex maxIdx r1 r2 = … 
  • pierwsze wejście powinno być wartością pochodzących z nieujemnej ściśle dodatnia
  • drugi i trzeci wejściowe muszą być w zamkniętym przedziale [0.0,1.0] poza tym funkcja nie ma sensu

funkcja ma właściwość

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

jaki sposób generowania losowych danych dla maxIdx i r1, r2 oddzielnie; Wiem o funkcji choose, ale nie wiem, jak go używać z więcej niż jedną zmienną wejściową.

Na razie przetestowałem nieruchomość z ustaloną wersją idx, co nie jest metodą, którą należy przetestować.

+0

może być pierwsza wartość 0? – bennofs

+0

Teraz, gdy o tym myślę, nie, nie powinno - będę edytować pytanie. – epsilonhalbe

Odpowiedz

12

Musisz użyć funkcji forAll z QuickCheck. Posiada następujące rodzaje:

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 przyjmuje dwa argumenty:

  • Generator opisuje jak generować wartości. Przykładami generatorów są: choose, arbitrary, oneof, ...
  • Funkcja testuje właściwość dla danego wejścia. Musi zwrócić wartość, która jest instancją Testable, na przykład inną Property, Bool lub funkcję.

Przykład zagnieżdżonego forall z wyboru i elementy generatorów:

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

dla nieruchomości testowym, można użyć forall z wyboru dla drugiego i trzeciego argumentu. Na pierwszy argument, nie jest typem Positive a w QuickCheck który może być używany do generowania dowolnych dodatnich wartości typu A (Ma arbitralnej przykład gdy jest 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

Proponuję definiowania własny typ, który owija Double i nadaj instancji Arbitrary że tylko generuje liczb pomiędzy 0 a 1. coś takiego:

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 ] 

generowania idx, można użyć QuickCheck za Positive modyfikator, jak @bennoffs zasugerował (trzeba będzie zaimportować Test.QuickCheck.Modifiers). Jest to podobne do typu UnitInterval I określonym powyżej, ale generuje pozytywne numery zamiast liczb od 0 do 1. Twoja nieruchomość będzie wtedy wyglądać tak:

prop_alwaysLessThanMaxIdx (Positive idx) (Unit r1) (Unit r2) = 
    rndListIndex idx r1 r2 <= idx 
Powiązane problemy