Tester ses fonctions
Comment être sûr qu'une fonction marche ? En l'essayant une fois ? Les programmeurs font mieux : ils écrivent des tests, de petits programmes qui vérifient automatiquement les résultats.
L'idée d'un test
Un test, c'est trois choses :
- un cas précis : la fonction appelée avec des valeurs choisies ;
- le résultat attendu, calculé à la main ;
- une comparaison entre ce qu'on obtient et ce qu'on attendait.
fonction doubler(n)
retourne n * 2
fin fonction
si doubler(4) = 8 alors
affiche 'Test réussi'
sinon
affiche 'Test échoué'
fin si
Une procédure pour tester
Pour ne pas réécrire le si à chaque fois, on crée une procédure qui compare et affiche le résultat en couleur :
procédure verifier(nomTest, obtenu, attendu)
si obtenu = attendu alors
couleur(#00BA7C, 'OK ' + nomTest)
sinon
couleur(#F4212E, 'ÉCHEC ' + nomTest)
affiche ' obtenu ' + obtenu + ', attendu ' + attendu
fin si
fin procédure
fonction doubler(n)
retourne n * 2
fin fonction
appelle verifier('doubler 4', doubler(4), 8)
appelle verifier('doubler 0', doubler(0), 0)
appelle verifier('doubler -3', doubler(-3), -6)
Trois lignes vertes : la fonction se comporte comme prévu. En cas d'échec, le message dit exactement quel test a raté et pourquoi.
Trouver un bug grâce aux tests
Voici une fonction qui calcule un prix après une réduction en pourcentage. Elle contient une erreur. Les tests vont la révéler :
procédure verifier(nomTest, obtenu, attendu)
si obtenu = attendu alors
couleur(#00BA7C, 'OK ' + nomTest)
sinon
couleur(#F4212E, 'ÉCHEC ' + nomTest)
affiche ' obtenu ' + obtenu + ', attendu ' + attendu
fin si
fin procédure
fonction prixReduit(prix, reduction)
retourne prix - reduction
fin fonction
appelle verifier('100 € à -0 %', prixReduit(100, 0), 100)
appelle verifier('100 € à -20 %', prixReduit(100, 20), 80)
appelle verifier('50 € à -20 %', prixReduit(50, 20), 40)
appelle verifier('80 € à -50 %', prixReduit(80, 50), 40)
Les deux premiers tests passent, les deux derniers échouent ! La fonction retire 20 euros au lieu de 20 pour cent. Avec un prix de 100, les deux calculs donnent le même résultat : un seul test n'aurait rien vu.
La correction : retourne prix - prix * reduction / 100. Remplace la ligne et relance : les quatre tests passent.
Question : Pourquoi le test « 100 € à -20 % » ne détectait-il pas l'erreur ? — Parce que, pour 100, retirer 20 ou retirer 20 % donne le même résultat. C'est un hasard des nombres choisis. D'où l'importance de tester avec plusieurs valeurs différentes.
Bien choisir ses tests
Un bon jeu de tests ne répète pas dix fois le même cas. Il explore :
- un cas normal, typique ;
- les cas limites : zéro, la plus petite et la plus grande valeur autorisées, un texte vide, un tableau d'un seul élément ;
- les cas juste autour d'une frontière : pour une mention à partir de 10, teste 9, 10 et 11.
procédure verifier(nomTest, obtenu, attendu)
si obtenu = attendu alors
couleur(#00BA7C, 'OK ' + nomTest)
sinon
couleur(#F4212E, 'ÉCHEC ' + nomTest)
affiche ' obtenu ' + obtenu + ', attendu ' + attendu
fin si
fin procédure
fonction mention(note)
si note >= 16 alors
retourne 'très bien'
fin si
si note >= 10 alors
retourne 'admis'
fin si
retourne 'refusé'
fin fonction
appelle verifier('note 0', mention(0), 'refusé')
appelle verifier('note 9', mention(9), 'refusé')
appelle verifier('note 10', mention(10), 'admis')
appelle verifier('note 15', mention(15), 'admis')
appelle verifier('note 16', mention(16), 'très bien')
appelle verifier('note 20', mention(20), 'très bien')
Les tests à 9 et 10, puis à 15 et 16, vérifient que les frontières sont au bon endroit. C'est là que se cachent la plupart des erreurs, par exemple un > écrit à la place d'un >=.
CoddyRun v4.3 propose un outil Tests unitaires : tu y décris tes cas et les résultats attendus, et il lance tous les tests d'un clic, sans écrire de procédure. Garde tes tests : après chaque modification, relance-les pour vérifier que rien n'est cassé.
En résumé
- Un test compare le résultat obtenu au résultat attendu, calculé à la main.
- Une procédure
verifier rend les tests rapides à écrire et à lire. - Plusieurs valeurs différentes : un seul test peut réussir par hasard.
- Cas normal, cas limites et frontières : c'est là que sont les bugs.