QuickCheck (qui fondamentalement génère test des entrées pour vous) est probablement le meilleur moyen de tester la fonction pure. Et si une fonction en question est un analogue de la bibliothèque standard, vous pouvez tester la qualité de votre fonction à l'aide de la norme d'un modèle:
{-# 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
-- quickCheckAll generates test cases for all 'prop_*' properties
main = $(quickCheckAll)
Si vous l'exécutez, vous obtiendrez:
=== prop_myLast on tmp3.hs:12 ===
*** Failed! Exception: 'tmp3.hs:(7,1)-(8,25): Non-exhaustive patterns in function myLast' (after 1 test):
[]
False
parce que votre myLast
ne gère pas les []
des cas (il faut mais devrait probablement jeter une erreur comme "dernier").
Mais ici, nous pouvons tout simplement d'ajuster notre test mais en précisant que seules les chaînes non-vides doivent être utilisés (à l'aide d' ==>
combinator):
prop_myLast xs = length xs > 0 ==> myLast xs == last xs
Ce qui rend tous les 100 auto-générer les cas de test à passer pour myLast
:
=== prop_myLast on tmp3.hs:11 ===
+++ OK, passed 100 tests.
True
PS Autre façon de spécifier myLast
comportement peut être:
prop_myLast2 x xs = myLast (xs++[x]) == x
Ou mieux:
prop_myLast3 x xs = x `notElem` xs ==> myLast (xs++[x]) == x