Index
Documentation Générale Qualité
Documentation Classes Metier
Documentation Liste Qualité Code Review
Documentation Liste Qualité Guideline Development
Documentation Bugs Defaults
Documentation Tests Unitaires
Documentation i18n
Documentation SQL Indexation
Documentation Timeframe
Tests unitaires
Date |
Par |
Quoi |
Version |
31/08/2023 |
MB |
Création |
0.0.1 |
27/09/2023 |
Nam |
Ajout section création d’un nouveau test |
0.0.2 |
27/09/2023 |
MD |
Restructuration |
0.0.3 |
09/10/2023 |
MD |
Ajout section Quoi tester et Nommage des fonctions de test unitaires |
0.0.4 |
13/10/2023 |
MD |
Ajout de précision concernant les annotations @cover |
0.0.5 |
26/10/2023 |
NC |
Vérifications, mise en page et ajout de précisions |
0.0.6 |
27/10/2023 |
MD |
Correction de petites coquilles |
0.0.7 |
Pourquoi faire des tests unitaires 2
Lancement des tests unitaires 2
Erreurs possibles au lancement du script 2
Préparation des données de test 2
Création de la classe de test 3
Création des fonctions de test unitaires 4
Nommage des fonctions de test unitaires 5
Je lance mes tests unitaires et je trouve un bug, que faire? 6
Je suis en phase de test >= Q3 6
Je rédige des tests unitaires pour des méthodes qui sont sur master 6
Le but des tests unitaires est de valider le bon fonctionnement des méthodes que l’on écrit. Si une méthode est correctement testée, alors on a l’assurance qu’elle fait bien ce que l’on veut et on minimise les erreurs qui pourraient survenir avec des données que l’on a pas imaginé.
De plus, si un jour on change le fonctionnement de cette méthode et qu’on introduit des bugs, on devrait s'apercevoir immédiatement qu’il y a des bugs car les tests unitaires ne vont plus passer, donc on minimise les risques de régression dans le code.
Pour l'intégralité de la documentation, voir le document dans **tests/doc/Unit Tests -******** - **.docx**
Si le script ne fonctionne pas il faut commencer par vérifier que les fichiers “tests/script/ini-file-parser.sh” et “tests/run.sh” aient les saut de ligne au format UNIX (line separator LF).
Il faut aussi penser à déployer son fichier de configuration.
Les données de test vont être versionnées. Il faut donc qu’elles soient anonymisées ! On peut en revanche mettre des données publiques comme les coordonnées d’entreprises par exemple. Sinon, pour les consultants ou les utilisateurs par exemple, il faudra changer les noms, les dates, les IDs, etc..
Les tests unitaires doivent hériter de la classe PHPUnit\Framework\TestCase\TestCase.
Pour les tests qui ont besoin d’interagir avec la base de données, nous avons créé une classe générique parente TestUnitaireWithDbImport dans tests/unit/src/TestUnitaireWithDbImport.php qui hérite déjà de TestCase. Ce fichier va faire les actions génériques pour la fonction setUpBeforeClass : require du fichier config.inc.php, instanciation de DbConnect, vidage de la bd Test et import du fichier Hightekers.sql.
Lors de la création de la classe ne pas oublier de rajouter l’annotation @covers tel que recommandé par la documentation de PHPUnit 9 (voir : 2. Annotations — PHPUnit 9.6 Manual)
Pour les classes qui héritent de TestUnitaireWithDbImport, on peut ajouter les actions suivantes dans la fonction setUpBeforeClass avant l’appel de la fonction parente parent::setUpBeforeClass :
Exemple :
public static function setUpBeforeClass(): void { |
Exemple :
public static function setUpBeforeClass(): void { |
Les classes sont regroupées par “section”, par exemple “Internationalisation” dans un fichier de configuration : “test/conf/app.conf”.
Une section peut faire référence à plusieurs tests unitaires s’ils sont de la même catégorie, par exemple “Internationalisation” et “InternationalisationDyn”.
Un test peut apparaître dans plusieurs catégories : Il est possible de tester un set de fonctionnalités qui sont en rapport les unes avec les autres.
Un nouveau test unitaire doit obligatoirement faire partie d’une section. Si la section n'existe pas, en créer une. Les sections doivent apparaître dans l’ordre alphabétique pour plus de visibilité (option -G) et commencer par une majuscule. (les tests seront exécutés dans l’ordre indiqué).
A noter que le test global (option -a) ne fait pas appel à ce fichier.
Il faut tester toutes les fonctions présentes dans l’objet sur lequel les tests portent.
Exemple : un test qui porte sur la ClassMetierManagementCalculs.php devra tester toutes les fonctions présentes dans cette classe métier.
Dans l’idéal, il faut même prévoir plusieurs tests pour une même fonction.
Il faut tester ce qui doit fonctionner, mais aussi (et surtout !) ce qui ne devrait pas fonctionner : Le but principal des test unitaire est de s'assurer de la stabilité d’une API
Le classe à 18 methodes, simple, mais fait 43 tests !
On teste bien sur les formats de données attendus mais aussi le passage de dates erronés, mal formatés, langue inexistantes, etc...
Pour chaque fonction, il faut tester le plus de cas possibles. En pensant surtout, mais pas uniquement, aux cas extrêmes susceptibles de faire planter la fonction. Il faut aussi tester des cas pour lesquels on sait que la fonction va planter et donc vérifier qu’elle plante bien comme attendu.
Exemple : On souhaite réaliser des tests sur une fonction qui fait la division de deux nombres à virgule. On imagine que l’on a la fonction division(float a, float b) : float. On va donc tester au minimum :
Dans ce cas là il va falloir faire au moins 2 tests, un avec une valeur correcte en entrée et une avec nulle, et tester que la fonction réagit comme on veut dans les deux cas.
Tester au moins 2 configurations de tableau en entrée, par exemple des données correctes et un tableau vide.
Tester avec une date normale et avec une chaîne de caractères qui ne correspond pas à une date. Ou une date formatée dans une autre langue.
Lors de la création de la fonction ne pas oublier de rajouter l’annotation @covers tel que recommandé par la documentation de PHPUnit 9 (voir : 2. Annotations — PHPUnit 9.6 Manual)
Chaque fonction de test unitaire doit respecter la nomenclature de nommage suivante en camelCase :
test<Nom fonction testée><description des conditions de test de la fonction>
Exemples :
Nom d’une fonction de test de division nommé division() avec deux float : testDivisionTwoFloat()
Nom d’une fonction de test de division nommé division() avec un float et un entier : testDivisionFloatInteger()
Nom d’une fonction de test de division nommé division() avec deux entier : testDivisionTwoInteger()
Nom d’une fonction de test de division nommé division() avec zéro : testDivisionByZero()
En cas de doute, toujours prévenir un lead dev ou un chef de projet.
Si c’est dans le périmètre du projet, faire les corrections dans la méthode de la classe métier. Les tests servent à découvrir des bugs, c’est normal.
Si c’est hors du périmètre du projet, prévenir un lead dev ou un chef de projet, ce sera géré au cas par cas en fonction de la sévérité du bug.
Si c’est dans le périmètre du projet, préparer un ticket de bugfix. Informer un chef de projet pour qu’il assigne le ticket.
Si c’est hors du périmètre du projet, prévenir un lead dev ou un chef de projet, se sera géré au cas par cas en fonction de la sévérité du bug.
Prévenir un lead dev ou un chef de projet, se sera géré au cas par cas en fonction de la sévérité du bug.