Ho visto come QuickCheck può essere utilizzato per testare il codice monadico e non monadico, ma come posso usarlo per testare il codice che gestisce gli errori, cioè stampa un messaggio e poi chiama exitWith
?Utilizzo di QuickCheck per testare condizioni di errore intenzionali
risposta
Prima una dichiarazione di non responsabilità: non sono un esperto di QuickCheck e non avevo esperienza con il controllo monadico prima della domanda, ma vedo lo stackoverflow come un'opportunità per imparare cose nuove. Se c'è una risposta da esperti che dice che questo può essere fatto meglio, rimuoverò il mio.
Supponiamo di avere una funzione test
che può generare eccezioni utilizzando exitWith
. Ecco come penso che puoi provarlo. La funzione chiave è protect
, che rileva l'eccezione e la converte in qualcosa su cui è possibile testare.
import System.Exit
import Test.QuickCheck
import Test.QuickCheck.Property
import Test.QuickCheck.Monadic
test :: Int -> IO Int
test n | n > 100 = do exitWith $ ExitFailure 1
| otherwise = do print n
return n
purifyException :: (a -> IO b) -> a -> IO (Maybe b)
purifyException f x = protect (const Nothing) $ return . Just =<< f x
testProp :: Property
testProp = monadicIO $ do
input <- pick arbitrary
result <- run $ purifyException test $ input
assert $ if input <= 100 then result == Just input
else result == Nothing
Ci sono due svantaggi in questo, per quanto posso vedere, ma non ho trovato alcun modo su di loro.
ho trovato alcun modo per estrarre l'eccezione
ExitCode
dalAnException
cheprotect
in grado di gestire. Pertanto, tutti i codici di uscita sono trattati nello stesso modo (sono mappati suNothing
). Mi sarebbe piaciuto avere:purifyException :: (a -> IO b) -> a -> IO (Either a ExitCode)
ho trovato alcun modo per testare il comportamento di I/O di test. Supponiamo
test
era:test :: IO() test = do n <- readLn if n > 100 then exitWith $ ExitFailure 1 else print n
Allora come è possibile provarlo?
Apprezzerei anche le risposte più esperte.
La funzione QuickCheck expectFailure
può essere utilizzata per gestire questo tipo di cose. Prendete questo semplice (e non raccomandato) framework di gestione degli errori:
import System.Exit
import Test.QuickCheck
import Test.QuickCheck.Monadic
handle :: Either a b -> IO b
handle (Left _) = putStrLn "exception!" >> exitWith (ExitFailure 1)
handle (Right x) = return x
e montare un paio di funzioni fittizie:
positive :: Int -> Either String Int
positive x | x > 0 = Right x
| otherwise = Left "not positive"
negative :: Int -> Either String Int
negative x | x < 0 = Right x
| otherwise = Left "not negative"
Ora possiamo testare alcune proprietà della gestione degli errori. In primo luogo, Right
valori non dovrebbero risultare in eccezioni:
prop_returnsHandledProperly (Positive x) = monadicIO $ do
noErr <- run $ handle (positive x)
assert $ noErr == x
-- Main*> quickCheck prop_returnsHandledProperly
-- +++ OK, passed 100 tests.
Lefts
dovrebbe risultato eccezioni. Notare
- 1. Utilizzo di quickCheck
- 2. Come posso testare una funzione di ordine superiore usando QuickCheck?
- 3. Utilizzo di SUDS per testare WSDL
- 4. Pro/contro di diversi metodi per testare le condizioni preliminari?
- 5. Utilizzo di Mockito per testare classi astratte
- 6. Quickcheck per test non booleani
- 7. Correzione rapida di tutti gli errori intenzionali
- 8. Haskell: Come testare un FSM (reattivo) con quickcheck?
- 9. Mancanza di extra intenzionali all'avvio dell'attività
- 10. QuickCheck per Javascript
- 11. Novità di QuickCheck 2?
- 12. Haskell Cabal QuickCheck Integration
- 13. Utilizzo di Moq per testare una classe astratta
- 14. Utilizzo di Espresso per testare le modifiche estraibili
- 15. Utilizzo di Moq.It.IsAny per testare una stringa inizia con qualcosa
- 16. Condizioni di errore e tentativi in gearman?
- 17. GHC: errore di segmentazione in condizioni strane
- 18. Errore di clang durante l'installazione di QuickCheck per GHC 7.8.3 su OS X Yosemite 10.10 (14A389)
- 19. annotazione @Cache errore di utilizzo
- 20. Errore nell'uso di Robolectric per testare una ActionBarActivity
- 21. Creazione di un AlarmManager finto per testare
- 22. utilizzo delle condizioni nel layout di Magento xml
- 23. Haskell - Test Parsec con l'aiuto di QuickCheck
- 24. Utilizzo dell'operatore NOT in condizioni IF
- 25. QuickCheck 2 elaborazione batch
- 26. verboseCheck in QuickCheck 2?
- 27. Test delle proprietà di QuickCheck contro più tipi?
- 28. proprietà condizionale QuickCheck
- 29. Haskell QuickCheck minimo contatore esempio
- 30. Utilizzo di H.323 per testare un sistema di posta vocale legacy
Giusto, ma questo sembra aspettarsi tutti i tipi di guasti. Possiamo isolare quelli generati dalle chiamate 'exitWith'? Possiamo affermare quale sarà il codice di errore? – nickie
@nickie È possibile aggiungere un po 'di tubature aggiuntive all'errore che si gestisce se si desidera testare le proprietà sui codici di uscita. Cioè avere una funzione 'verifyCode :: O a b -> ExitCode' che' exitWith' chiama, e fare asserzioni sul comportamento di quello. Non so se è possibile andare oltre. – jtobin
'expectFailure' sembra passare se un test fallisce, al contrario se tutti i test falliscono, che è più quello che sto cercando. – Dan