haskell - Prueba de acciones de IO con Monadic QuickCheck
(2)
¿Alguien puede darme un breve ejemplo de prueba de acciones de IO usando Monadic QuickCheck?
La referencia estándar para probar el código monádico es "Probando el código monádico con QuickCheck" . Muestra varias formas de prueba en el contexto de una mónada, como IO.
Pero realmente debería considerar publicar una pregunta más concreta sobre qué es lo que le gustaría probar.
El módulo Test.QuickCheck.Monadic permite probar el código monádico, incluso las cosas que se ejecutan en IO
.
Una prueba de propiedad monádica es de tipo PropertyM ma
, donde m
es la mónada en la que se ejecuta la prueba y finalmente se ignora. En el caso de PropertyM IO a
, convierta la prueba monádica a una Property
utilizando monadicIO
; para todas las otras mónadas, usas monadic
(que toma una función para ejecutar la mónada, algo que IO
no tiene).
En una prueba monádica, el valor return
ed fuera de la mónada se ignora. Para verificar una expresión, use assert
; assert
un valor falso no pasará la prueba. Use run
para ejecutar el código en la mónada que se está probando.
Hay otras acciones monádicas a su disposición. Por ejemplo, pick
generará nuevas entradas de prueba a partir de una Gen a
, y pre
comprobará las condiciones previas de la prueba. Estos son útiles si las entradas de prueba o las condiciones previas dependen de los valores calculados a través de la mónada que se está probando, en cuyo caso la forma normal de generar entradas o verificar las precondiciones no funcionará.
Aquí hay un ejemplo de prueba de algunos códigos IO
: comprobamos que después de escribir algo en un archivo temporal, podemos leer esos mismos datos. Para fines de demostración, impondremos la condición previa de que escribamos al menos un byte en el archivo. Las dos propiedades de prueba hacen lo mismo; uno usa pick
y pre
innecesariamente mientras que el otro no.
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