Je veux passer en revue 99 Problèmes Haskell , et je veux me concentrer sur la solution, mais avec des tests. Si j'ai la solution au premier problème sous forme de fichier .hs
de 3 lignes,
myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs
Quelle est la quantité minimale de code que je peux ajouter pour pouvoir ajouter des tests en ligne et les exécuter avec runhaskell
?
QuickCheck (qui génère essentiellement des entrées de test pour vous) est probablement le meilleur moyen de tester une fonction pure. Et si une fonction en question a un analogue de la bibliothèque standard, vous pouvez simplement tester votre fonction en utilisant le modèle standard comme 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
return [] -- need this for GHC 7.8
-- 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 le cas []
(il devrait mais devrait probablement renvoyer une erreur du type 'last'). Mais ici, nous pouvons simplement ajuster notre test en spécifiant que seules les chaînes non vides doivent être utilisées ==>
combinator):
prop_myLast xs = length xs > 0 ==> myLast xs == last xs
Ce qui fait que tous les 100 cas de test générés automatiquement passent avec myLast
:
=== prop_myLast on tmp3.hs:11 ===
+++ OK, passed 100 tests.
True
PS Une autre façon de spécifier un comportement myLast
peut être:
prop_myLast2 x xs = myLast (xs++[x]) == x
Ou mieux:
prop_myLast3 x xs = x `notElem` xs ==> myLast (xs++[x]) == x
hspec est également un framework de test pour Haskell, inspiré de Ruby RSpec. Il s'intègre à QuickCheck, SmallCheck et HUnit.