2011-04-16 10 views
49

Quiero pasar por 99 Haskell Problems, y quiero concentrarme en la solución pero con las pruebas. Si tengo la solución al primer problema como un archivo de línea de 3 .hs,Prueba simple de la unidad haskell

myLast :: [a] -> a 
myLast [x] = x 
myLast (_:xs) = myLast xs 

¿Cuál es la cantidad mínima de código que puedo añadir a esto de modo que puedo añadir pruebas en línea y ejecutarlos con runhaskell?

Respuesta

64

QuickCheck (que basicamente 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 librería estándar sólo se puede poner a prueba su función utilizando el estándar de 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 ejecuta él se puede obtener:

=== 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 su myLast no maneja el caso [] (debería pero debería arrojar un error como 'last'). Pero aquí simplemente podemos ajustar nuestra prueba, pero especificando que sólo cadenas no vacías deben utilizarse (usando ==> combinador):

prop_myLast xs = length xs > 0 ==> myLast xs == last xs 

¿Qué hace que los 100 casos de prueba generados automáticamente para pasar por myLast:

=== prop_myLast on tmp3.hs:11 === 
+++ OK, passed 100 tests. 
True 

PS Otra forma de especificar myLast comportamiento puede ser:

prop_myLast2 x xs = myLast (xs++[x]) == x 

O Bette r:

prop_myLast3 x xs = x `notElem` xs ==> myLast (xs++[x]) == x 
+0

Cuando ejecuto mi archivo con 'runhaskell lists.hs' me da" lists.hs: 44: 8: error de análisis en la entrada '$ '" ¿Es así como se supone que debo ejecutarlo? https://gist.github.com/923814 –

+2

Intenta agregar '{- # LANGUAGE TemplateHaskell # -}' según mi ejemplo. Si su 'runhaskell' apunta a' runghc' esto debería ser el truco. También cambie el nombre 'prop_last'' por' prop_last' - de lo contrario, QuickCheck parece ignorarlo. –

+2

Para que todo funcione (¡gracias!), Pero ahora, ¿cómo hago que quickcheck capture los errores? Agregué 'last '[] = error" empty list "' –

0

hspec es también un marco de prueba para Haskell, que está inspirado en Ruby RSpec. Se integra con QuickCheck, SmallCheck y HUnit.