Il fut un temps où les programmeurs étaient payés en fonction du nombre de lignes de code qu'ils écrivaient. Ils ont été traités comme des machines produisant du code source fonctionnant dans des cellules et, en retour, ils considéraient la programmation comme un travail qu’ils faisaient huit heures par jour, puis ils l’oubliaient, pour le reste de la journée..
Mais les temps ont changé. La plupart des postes de travail de cubicules ont disparu et les programmeurs ont commencé à aimer leur métier. Avec l'avènement des techniques Agiles et le mouvement Software Craftsmanship, de nombreux nouveaux outils ont vu le jour pour aider le programmeur et le processus. TDD est en train de devenir lentement la manière de facto d’écrire du code et les secrets de SCRUM ou de Kanban ont été révélés même aux programmeurs des coins les plus sombres du monde des cubicules..
Les tests automatisés et le développement piloté par les tests (TDD) font partie des techniques essentielles fournies par Agile aux programmeurs. Et un outil fourni avec ces méthodologies est utilisé pour produire une couverture de code de test, qui est le sujet de cet article..
"En informatique, la couverture de code est une mesure utilisée pour décrire le degré de test du code source d'un programme avec une suite de tests particulière." ~ Wikipedia
La définition ci-dessus, tirée de Wikipedia, est l’un des moyens les plus simples de décrire la définition de la couverture de code. En gros, dans votre projet, vous avez un tas de code de production ainsi qu'un tas de code de test. Le code de test exerce le code de production et la couverture de test vous indique combien de votre code de production a été exercé par les tests..
Les informations peuvent être présentées de différentes manières, allant de simples pourcentages à de jolis graphiques ou même à une mise en évidence en temps réel dans votre IDE préféré..
Nous utiliserons PHP comme langage pour illustrer notre code. De plus, nous aurons besoin de PHPUnit et XDebug pour tester notre code et rassembler les données de couverture..
Voici le code source que nous allons utiliser. Vous pouvez également le trouver dans les archives ci-jointes..
Classe WordWrap fonction publique wrap ($ string = ", $ cols) $ string = trim ($ chaîne); if (strlen ($ chaîne)> $ cols) $ lastSpaceIndex = strrpos (substr ($ chaîne, 0, $ cols), "); if ($ lastSpaceIndex! == false && substr ($ chaîne, $ cols, 1)! = ") retourne substr ($ chaîne, 0, $ dernierSpaceIndex)." \ n ". $ this-> wrap (substr ($ string, $ lastSpaceIndex), $ cols); else return substr ($ string, 0, $ cols). "\ n". $ this-> wrap (substr ($ string, $ cols), $ cols); return $ string;
Le code ci-dessus contient une fonction simple qui encapsule le texte avec un nombre spécifié de caractères, par ligne..
Nous avons écrit ce code en utilisant TDD (Test Driven Development) et nous en avons une couverture à 100%. Cela signifie qu'en exécutant notre test, nous exerçons chaque ligne du code source.
require_once __DIR__. '/… /WordWrap.php'; La classe WordWrapTest étend PHPUnit_Framework_TestCase function testItCanWrap () $ w = new WordWrap (); $ this-> assertEquals (", $ w-> wrap (null, 0)); $ this-> assertEquals (", $ w-> wrap (", 0)); $ this-> assertEquals ('a', $ w-> wrap ('a', 1)); $ this-> assertEquals ("a \ nb", $ w-> wrap ('a b', 1)); $ this-> assertEquals ("ab \ nc ", $ w-> wrap ('ab c', 3)); $ this-> assertEquals (" a \ nbc \ nd ", $ w-> wrap ('a bc d', 3));
Une façon d'obtenir des données de couverture consiste à exécuter nos tests dans l'interface de ligne de commande (CLI) et à analyser le résultat. Pour cet exemple, supposons un système d’exploitation de type UNIX (Linux, MacOS, FreeBSD, etc.). Les utilisateurs Windows devront légèrement adapter les chemins et les noms des exécutables, mais cela devrait être assez similaire.
Ouvrons une console et changeons de répertoires dans votre tester
dossier. Puis courir phpunit
avec une option pour générer des données de couverture en texte brut.
phpunit --coverage-text =. / coverage.txt ./WordWrapTest.php
Cela devrait fonctionner immédiatement avec la plupart des systèmes si XDebug est installé. Toutefois, dans certains cas, vous pouvez rencontrer une erreur liée aux fuseaux horaires..
Avertissement PHP: date (): Il est dangereux de se fier aux paramètres de fuseau horaire du système. Vous êtes * obligé * d'utiliser le paramètre date.timezone ou la fonction date_default_timezone_set (). Si vous utilisez l'une de ces méthodes et que vous recevez toujours cet avertissement, vous avez probablement mal orthographié l'identificateur de fuseau horaire. Nous avons sélectionné le fuseau horaire 'UTC' pour l'instant, mais veuillez définir date.timezone pour choisir votre fuseau horaire. dans phar: ///usr/share/php/phpunit/phpunit.phar/ PHP_CodeCoverage-1.2.10 / PHP / CodeCoverage / Report / Text.php à la ligne 124
Ceci peut être facilement corrigé en spécifiant le réglage suggéré dans votre php.ini
fichier. Vous pouvez trouver le moyen de spécifier votre fuseau horaire dans cette liste. Je viens de Roumanie, je vais donc utiliser le réglage suivant:
date.timezone = Europe / Bucarest
Maintenant, si vous exécutez le phpunit
commande encore, vous ne devriez voir aucun message d'erreur. Au lieu de cela, les résultats du test seront affichés.
PHPUnit 3.7.20 de Sebastian Bergmann… Temps: 0 secondes, Mémoire: 5.00Mb OK (2 tests, 7 assertions)
Et les données de couverture seront dans le fichier texte spécifié.
$ cat ./coverage.txt Rapport de couverture de code 2014-03-02 13:48:11 Résumé: Classes: 100.00% (1/1) Méthodes: 100.00% (1/1) Lignes: 2.68% (14/522) WordWrap Méthodes: 100,00% (1/1) Lignes: 100,00% (7/7)
Analysons cela un peu.
WordWrap
est notre seule classe.emballage()
méthode, rien d'autre.WordWrap
. Chaque section a ses propres méthodes et détails de ligne. Sur la base de ces observations, nous pouvons conclure que notre code est couvert à 100% par des tests. Exactement comme nous l’avions prévu avant d’analyser les données de couverture.
En modifiant simplement un paramètre simple pour PHPUnit, nous pouvons générer une belle sortie HTML.
$ mkdir ./coverage $ phpunit --coverage-html ./coverage ./WordWrapTest.php
Si vous vérifiez votre ./couverture
répertoire, vous y trouverez beaucoup de fichiers. Je ne vais pas coller la liste ici car elle est assez longue. Au lieu de cela, je vais vous montrer à quoi ça ressemble dans un navigateur Web.
Ceci est l'équivalent du résumé de la version textuelle ci-dessus. Nous pouvons zoomer en suivant les liens proposés et voir plus de détails.
Les exemples précédents étaient intéressants et très utiles, si votre code est construit sur un serveur distant auquel vous avez uniquement accès à SHH ou à Internet. Mais ne serait-il pas agréable d'avoir toutes ces informations, vivre dans votre IDE?
Si vous utilisez PHPStorm, tout est à la distance d'un clic! Sélectionnez pour exécuter vos tests avec une couverture et toutes les informations apparaîtront simplement, comme par magie.
Les informations de couverture seront présentes dans votre IDE, de plusieurs manières et à plusieurs endroits:
Avec un outil aussi puissant entre les mains du développeur et sous le nez de la direction, il était inévitable que certains mythes fassent surface. Après que les programmeurs aient refusé de payer en fonction du nombre de lignes de code qu'ils écrivaient, ou que les responsables aient réalisé à quel point il était facile de jouer au système, certains d'entre eux ont commencé à les payer en fonction du pourcentage de couverture de code. Une plus grande couverture de code signifie que le programmeur était plus prudent, non? C'est un mythe La couverture de code n'est pas une mesure de votre capacité à écrire du code.
Parfois, les programmeurs ont tendance à penser que le code avec une couverture de 100% n'a pas de bugs. Un autre mythe. La couverture de code indique simplement que vous avez testé chaque ligne de code. C'est une mesure du nombre de lignes exercées. Ce n'est pas une mesure du nombre de lignes correctement implémentées. Par exemple, les algorithmes à moitié écrits avec seulement des tests à moitié définis auront toujours une couverture de 100%. Cela ne signifie pas que l'algorithme est terminé ou qu'il fonctionne correctement.
Enfin, jouer au système est très facile. Bien sûr, si vous utilisez TDD, vous avez naturellement une valeur de couverture élevée. Sur des projets entiers, 100% est impossible. Mais sur de petits modules ou de petites classes, obtenir une couverture à 100% est très facile. Prenons l'exemple de notre code source et imaginons que vous n'avez aucun test. Quel serait le test le plus simple pour exercer tout le code?
fonction testItCanWrap () $ w = new WordWrap (); $ this-> assertEquals ("a b \ nc", $ w-> wrap ('a b c', 3)); $ this-> assertEquals ("a \ nbc \ nd", $ w-> wrap ("a bc d", 3));
C'est tout. Deux affirmations et une couverture complète. Ce n'est pas ce que nous voulons. Ce test est si loin d'être descriptif et complet qu'il est ridicule.
La couverture de code est un indicateur d'état et non une unité permettant de mesurer les performances ou l'exactitude.
La couverture de code est destinée aux programmeurs, pas aux gestionnaires. C'est un moyen de détecter les problèmes dans notre code. Un moyen de trouver des classes anciennes non testées. Un moyen de trouver des chemins non utilisés par les tests qui pourraient poser problème.
Sur des projets réels, la couverture de code sera toujours inférieure à 100%. Il n’est pas possible d’obtenir une couverture parfaite. Sinon, c’est rarement indispensable. Cependant, pour avoir 98% de la couverture, vous devez viser 100%. Avoir autre chose que votre cible est non-sens.
Voici la couverture de code sur l'application de configuration StorageOS de Syneto.
Le total n’est que d’environ 35%, mais les résultats doivent être interprétés. La plupart des modules sont dans le vert, avec une couverture de plus de 70%. Cependant, il y a un seul dossier, Vmware
, qui abaisse la moyenne. C'est un module avec beaucoup de classes contenant uniquement des définitions pour l'API de communication. Il n'y a aucune raison de tester ces classes. Ils ont été générés automatiquement par un code de confiance. Les programmeurs le sauront et sauront interpréter les résultats. Un responsable peut insister pour le tester car il s’agit d’une barre rouge et il semble suspect de ne pas connaître les détails internes du projet. Cela aurait-il un sens de le tester? Pas du tout! Ce serait un test inutile, qui prendrait de précieuses dizaines de secondes de temps de construction sans aucun avantage.
Voici donc où nous en sommes avec la couverture de code: c'est un excellent outil pour les programmeurs, une source d'informations permettant de mettre en évidence les problèmes possibles, une réalité mal comprise pour la plupart des gestionnaires et un autre outil pour forcer et mesurer les activités des programmeurs. Comme avec n'importe quel autre outil, c'est un outil qui peut être utilisé correctement et mal utilisé facilement.