2012-10-14 7 views
9

ho scritto una proprietà QuickCheck per una funzione che unisce due ingressi ordinate in un output ordinato:proprietà condizionale QuickCheck

prop_merge xs ys = 
    if (sorted xs && sorted ys) then (sorted (merge xs ys)) else True 

Cioè, quando gli ingressi sono ordinati, l'uscita viene ordinato pure. Può anche essere scritto come:

Ma non mi piace tanto nessuna delle due versioni. C'è una sintassi migliore per "proprietà condizionali" in QuickCheck?

risposta

27

È possibile utilizzare l'operatore ==> di allegare una condizione booleana alle proprietà:

prop_merge xs ys = (sorted xs && sorted ys) ==> sorted (merge xs ys) 

Questa non è solo una sintassi più bello, ma permette QuickCheck distinguere tra casi di test in cui il test ha avuto successo e casi di test che non ha soddisfatto la condizione preliminare. In quest'ultimo caso, il test non viene conteggiato e QuickCheck genera nuovi input.

Tuttavia, nei casi in cui la maggior parte degli ingressi non soddisfano la condizione, i test potrebbero essere eseguiti più lentamente oppure, se vengono scaricati abbastanza input, QuickCheck alla fine si arrenderà. Dal momento che un elenco casuale è improbabile che possa essere ordinato, questo è molto probabile che accada con l'esempio precedente:

> quickCheck (prop_merge :: [Int] -> [Int] -> Property) 
*** Gave up! Passed only 15 tests. 

(Si noti che con gli operatori booleani standard, invece di utilizzare ==>, QuickCheck amplificherà su tutte le prove di essere passati, quando la maggior parte di essi era inutile a causa di una precondizione fallita)

Per questo motivo, in genere è molto meglio generare direttamente solo i casi di test necessari. Per i casi più semplici, il modulo Test.QuickCheck.Modifiers contiene diversi newtype utili che modificano il modo in cui vengono generati gli input. Ad esempio, il modificatore OrderedList solo generare liste ordinate, in modo che possiamo scrivere la vostra proprietà semplicemente come:

prop_merge (Ordered xs) (Ordered ys) = sorted (merge xs ys) 
+0

Ah, che sembra molto meglio! – fredoverflow

+2

Penso che sarebbe utile notare esplicitamente che '==>' non è solo una sintassi più gradevole, ma consente a QuickCheck di distinguere tra i casi di test in cui il test ha avuto esito positivo e i casi di test che non hanno soddisfatto la condizione preliminare. In quest'ultimo caso, il test non viene conteggiato e QuickCheck genera nuovi input. Questo è ciò che consente a QuickCheck di darti "*** Gave up! Passato solo 15 test". messaggio. "Se la precondizione viene espressa tramite gli operatori booleani standard, QuickCheck aumenterà il numero di test superati, quando la maggior parte di essi non è più utilizzabile a causa di una precondizione fallita –

+0

@cebewee: Grazie per i suggerimenti. manualmente poiché sono stati respinti dai revisori. – hammar