Test actions IO avec Monadique QuickCheck
-
20-09-2019 - |
Question
Quelqu'un peut-il me donner un bref exemple de tester les actions IO en utilisant Monadique QuickCheck?
La solution
Le Test.QuickCheck Module .Monadic vous permet de tester le code monadique, même des choses qui vont dans IO
.
Un test de propriété monadique est de type PropertyM m a
, où m
est la monade le test fonctionne et a
est finalement ignoré. Dans le cas de PropertyM IO a
, vous convertissez le test monadique à un Property
en utilisant monadicIO
; pour tous les autres monades, vous utilisez monadic
à la place (qui prend une fonction à exécuter la monade, quelque chose ne IO
pas).
Dans un test monadique, la valeur return
ed de la monade est ignorée. Pour vérifier une expression, utilisez assert
; assert
ing une valeur fausse échouera le test. Utilisez run
pour exécuter le code dans la monade testé.
Il y a d'autres actions monades à votre disposition. Par exemple, pick
va générer de nouvelles entrées de test sur un Gen a
et pre
vérifiera conditions de test. Elles sont utiles si les entrées de test ou conditions préalables elles-mêmes dépendent des valeurs calculées par la monade à l'essai, auquel cas la voie normale de générer des entrées ou le contrôle precontions ne fonctionnera pas.
Voici un exemple de test du code de IO
: nous vérifions qu'après avoir écrit quelque chose à un fichier temporaire, on peut lire que les mêmes données en arrière. Pour des fins de démonstration, nous imposons la condition sine qua non pour que nous écrivions au moins un octet dans le fichier. Les deux propriétés de test font la même chose; on utilise pick
et pre
inutilement tandis que l'autre ne fonctionne pas.
import System.Directory (removeFile)
import System.IO (hGetContents, hPutStr, hSeek, openBinaryTempFile, SeekMode (..))
import Test.QuickCheck (arbitrary, Property, quickCheck, (==>))
import Test.QuickCheck.Monadic (assert, monadicIO, pick, pre, run)
-- Demonstrating pick and pre as well:
prop_writeThenRead :: Property
prop_writeThenRead = monadicIO $ do writtenData <- pick arbitrary
pre $ not (null writtenData)
readData <- run $ writeThenRead writtenData
assert $ writtenData == readData
-- A more idiomatic way to write the above:
prop_writeThenRead2 :: [Char] -> Property
prop_writeThenRead2 writtenData = not (null writtenData) ==> monadicIO test
where test = do readData <- run $ writeThenRead writtenData
assert $ writtenData == readData
writeThenRead :: [Char] -> IO [Char]
writeThenRead output = do (path, h) <- openBinaryTempFile "/tmp" "quickcheck.tmp"
removeFile path
hPutStr h output
hSeek h AbsoluteSeek 0
hGetContents h
main :: IO ()
main = do quickCheck prop_writeThenRead
quickCheck prop_writeThenRead2
Autres conseils
La référence standard pour tester le code monadique est "Test code Monadique avec QuickCheck « . Il montre diverses façons de tester dans le cadre d'une monade tels que IO.
Mais vous devriez vraiment envisager de poser une question plus concrète sur ce qu'il est que vous souhaitez tester.