unit testing - Prueba de unidad haskell simple
unit-testing (2)
Quiero pasar por 99 problemas de Haskell , y quiero concentrarme en la solución pero con las pruebas. Si tengo la solución al primer problema como un archivo .hs
de 3 líneas,
myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs
¿Cuál es la cantidad mínima de código que puedo agregar a esto para poder agregar pruebas en línea y ejecutarlas con runhaskell
?
hspec también es un marco de prueba para Haskell, que está inspirado en Ruby RSpec. Se integra con QuickCheck, SmallCheck y HUnit.
QuickCheck (que básicamente genera entradas de prueba para usted) es probablemente la mejor manera de probar la función pura. Y si una función en cuestión tiene un análogo de la biblioteca estándar, puede probar su función utilizando la estándar como modelo:
{-# LANGUAGE TemplateHaskell #-}
import Test.QuickCheck
import Test.QuickCheck.All
myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs
-- here we specify that ''myLast'' should return exactly the same result
-- as ''last'' for any given ''xs''
prop_myLast xs = myLast xs == last xs
return [] -- need this for GHC 7.8
-- quickCheckAll generates test cases for all ''prop_*'' properties
main = $(quickCheckAll)
Si lo ejecutas obtendrás:
=== prop_myLast on tmp3.hs:12 ===
*** Failed! Exception: ''tmp3.hs:(7,1)-(8,25): Non-exhaustive patterns in function myLast'' (after 1 test):
[]
False
porque myLast
no maneja el caso []
(debería, pero probablemente debería arrojar un error como ''last''). Pero aquí podemos simplemente ajustar nuestra prueba pero especificando que solo se deben usar cadenas no vacías (usando ==>
combinador):
prop_myLast xs = length xs > 0 ==> myLast xs == last xs
Lo que hace que todos los 100 casos de prueba generados automáticamente pasen por myLast
:
=== prop_myLast on tmp3.hs:11 ===
+++ OK, passed 100 tests.
True
PD Otra forma de especificar myLast
comportamiento puede ser:
prop_myLast2 x xs = myLast (xs++[x]) == x
O mejor:
prop_myLast3 x xs = x `notElem` xs ==> myLast (xs++[x]) == x