unit-testing - paramétré - test unitaire php




Qu'est-ce qu'un test unitaire? (14)

J'ai vu de nombreuses questions demandant «comment» tester un test dans une langue spécifique, mais aucune question ne demandait «quoi», «pourquoi» et «quand».

  • Qu'Est-ce que c'est?
  • Que fait-il pour moi?
  • Pourquoi devrais-je l'utiliser?
  • Quand devrais-je l'utiliser (aussi quand non)?
  • Quels sont les pièges les plus courants et les idées fausses?

Que faites-vous si on vous donne une pile de merde et que vous semblez être bloqué dans un état de nettoyage perpétuel que vous savez avec l’ajout de toute nouvelle fonctionnalité ou code peut casser l’ensemble actuel car le logiciel actuel est comme une maison de cartes?

Comment pouvons-nous faire des tests unitaires alors?

Vous commencez petit. Le projet dans lequel je me suis lancé ne comportait pas de tests unitaires jusqu'à il y a quelques mois. Lorsque la couverture était aussi basse, nous choisissions simplement un fichier sans couverture et cliquez sur "ajouter des tests".

À l'heure actuelle, nous en sommes à plus de 40% et nous avons réussi à récolter l'essentiel des résultats les plus faciles.

(La meilleure partie est que même avec ce faible niveau de couverture, nous avons déjà rencontré de nombreuses erreurs de code, et les tests l'ont bien compris. C'est un facteur de motivation énorme pour pousser les gens à ajouter plus de tests.)


À l'université, on ne m'avait jamais enseigné les tests unitaires, et il m'a fallu un certain temps pour le "comprendre". J'ai lu des articles à ce sujet et j'ai dit: «ah, oui, des tests automatisés, ça pourrait être cool, je suppose», puis j'ai oublié tout ça.

Cela a pris un peu plus de temps avant que je comprenne vraiment le point: disons que vous travaillez sur un grand système et que vous écrivez un petit module. Il compile, vous le mettez à l'épreuve, cela fonctionne très bien, vous passez à la tâche suivante. Neuf mois plus tard et deux versions plus tard, une autre personne modifie une partie du programme qui n’a apparemment pas de lien, et cela casse le module. Pire encore, ils testent leurs modifications et leur code fonctionne, mais ils ne testent pas votre module; diable, ils ne savent peut-être même pas que votre module existe .

Et maintenant, vous avez un problème: le code erroné est dans le coffre et personne ne le sait même. Le meilleur des cas est qu'un testeur interne le trouve avant l'expédition, mais corriger le code tard dans le jeu coûte cher. Et si aucun testeur interne ne le trouve ... eh bien, cela peut coûter très cher.

La solution est des tests unitaires. Ils attraperont des problèmes lorsque vous écrivez du code - ce qui est bien - mais vous auriez pu le faire à la main. Le véritable avantage, c'est qu'ils vont régler les problèmes neuf mois plus tard, alors que vous travaillez maintenant sur un projet complètement différent, mais un stagiaire d'été pense que les paramètres seraient mieux rangés si ces paramètres étaient classés par ordre alphabétique - puis le test unitaire. vous avez écrit que le chemin du retour a échoué et que quelqu'un jette des objets à l'interne jusqu'à ce qu'il change l'ordre des paramètres. C'est le "pourquoi" des tests unitaires. :-)


Cela répond à pourquoi vous devriez faire des tests unitaires.

Les 3 vidéos ci-dessous couvrent les tests unitaires en javascript, mais les principes généraux s'appliquent dans la plupart des langues.

Tests unitaires: les minutes gagneront des heures plus tard - Eric Mann - https://www.youtube.com/watch?v=_UmmaPe8Bzc

Test d'unité JS (très bon) - https://www.youtube.com/watch?v=-IYqgx8JxlU

Écriture de JavaScript testable - https://www.youtube.com/watch?v=OzjogCFO4Zo

Maintenant, je suis juste en train d’apprendre sur le sujet, donc je ne suis peut-être pas tout à fait correct. C’est plus que ce que je décris ici, mais ma compréhension de base du test unitaire est que vous écrivez du code de test (qui est séparé de votre code principal) qui appelle une fonction dans votre code principal avec les entrées (arguments) requises par la fonction et le code vérifie ensuite si elle renvoie une valeur de retour valide. S'il récupère une valeur valide, la structure de test unitaire que vous utilisez pour exécuter les tests affiche un voyant vert (si tout va bien). Si la valeur est invalide, vous obtenez un voyant rouge et vous pouvez alors résoudre le problème immédiatement avant de vous publiez le nouveau code en production, sans test, il est possible que l'erreur n'ait pas été détectée.

Donc, vous écrivez des tests pour votre code actuel et créez le code pour qu'il passe le test. Des mois plus tard, vous ou une autre personne devez modifier la fonction dans votre code principal, car vous aviez déjà écrit le code de test pour cette fonction que vous exécutez à nouveau et le test peut échouer car le codeur a introduit une erreur de logique dans la fonction ou a renvoyé quelque chose complètement. différent de ce que cette fonction est supposée retourner. Encore une fois sans le test en place, cette erreur pourrait être difficile à localiser car elle pourrait également affecter d’autres codes et resterait inaperçue.

De plus, le fait que vous ayez un programme informatique qui parcourt votre code et le teste au lieu de le faire manuellement dans le navigateur page par page vous fait gagner du temps (tests unitaires pour javascript). Supposons que vous modifiiez une fonction utilisée par un script sur une page Web et qu'elle fonctionne parfaitement pour son nouvel objectif. Mais disons aussi, à des fins d’argumentation, qu’il existe une autre fonction dans votre code qui dépend de cette fonction nouvellement modifiée pour qu’elle fonctionne correctement. Cette fonction dépendante peut maintenant cesser de fonctionner en raison des modifications que vous avez apportées à la première fonction. Toutefois, sans tests en place exécutés automatiquement par votre ordinateur, vous ne remarquerez pas qu'il y a un problème avec cette fonction tant qu'elle n'est pas réellement exécutée. vous devrez naviguer manuellement vers une page Web contenant le script exécutant la fonction dépendante. À ce moment-là, vous remarquerez qu'il y a un bogue en raison de la modification apportée à la première fonction.

Pour rappel, avoir des tests exécutés lors du développement de votre application détectera ce type de problèmes lors de la programmation. N'ayant pas les tests en place, vous devez parcourir manuellement votre application dans son ensemble et même dans ce cas, il peut être difficile de repérer le bogue, vous l'envoyez naïvement en production et, au bout d'un moment, un gentil utilisateur vous envoie un rapport de bogue (qui ne sera pas aussi bon que vos messages d'erreur dans un framework de test).

C'est assez déroutant quand vous entendez parler du sujet pour la première fois et que vous vous dites que je ne teste pas déjà mon code? Et le code que vous avez écrit fonctionne comme il est supposé déjà, "pourquoi ai-je besoin d'un autre framework?" ... Oui, vous testez déjà votre code, mais un ordinateur le fait mieux. Il vous suffit d'écrire une fois suffisamment de tests pour une fonction / unité de code et le reste est pris en charge par le puissant processeur, au lieu que vous ayez à vérifier manuellement que tout votre code fonctionne toujours lorsque vous modifiez votre code.

En outre, vous n'avez pas besoin de tester votre code à l'unité si vous ne le souhaitez pas, mais cela rapporte dès que votre base de projet / code commence à grossir à mesure que les chances d'introduire des bogues augmentent.


Des bibliothèques telles que NUnit , xUnit ou JUnit sont simplement obligatoires si vous souhaitez développer vos projets en utilisant l’approche TDD popularisée par Kent Beck:

Vous pouvez lire Introduction au développement piloté par les tests (TDD) ou le livre de Kent Beck intitulé Test Driven Development: By Example .

Ensuite, si vous voulez être sûr que vos tests couvrent une "bonne" partie de votre code, vous pouvez utiliser un logiciel comme NCover , JCover , PartCover ou autre. Ils vous diront le pourcentage de couverture de votre code. En fonction de votre niveau d'expérience chez TDD, vous saurez si vous l'avez déjà bien pratiqué :)


J'utilise des tests unitaires pour gagner du temps.

Lors de la création d'une logique métier (ou d'accès aux données), la fonctionnalité de test peut souvent impliquer de taper des éléments dans de nombreux écrans qui peuvent être terminés ou non. L'automatisation de ces tests permet de gagner du temps.

Pour moi, les tests unitaires sont une sorte de faisceau de tests modulaire. Il y a généralement au moins un test par fonction publique. J'écris des tests supplémentaires pour couvrir divers comportements.

Tous les cas particuliers auxquels vous avez pensé lors de l'élaboration du code peuvent être enregistrés dans le code des tests unitaires. Les tests unitaires deviennent également une source d’exemples sur l’utilisation du code.

Il est beaucoup plus rapide pour moi de découvrir que mon nouveau code casse quelque chose dans mes tests unitaires, puis de l'archiver dans le code et de laisser un développeur front-end trouver un problème.

Pour les tests d'accès aux données, j'essaie d'écrire des tests qui ne changent pas ou qui nettoient après eux-mêmes.

Les tests unitaires ne seront pas en mesure de résoudre toutes les exigences de test. Ils seront en mesure de gagner du temps de développement et de tester des composants essentiels de l'application.


Je ne suis pas en désaccord avec Dan (bien qu'un meilleur choix puisse être simplement de ne pas répondre) ... mais ...

Le test unitaire consiste à écrire du code pour tester le comportement et les fonctionnalités de votre système.

Évidemment, les tests améliorent la qualité de votre code, mais ce n'est qu'un avantage superficiel des tests unitaires. Les avantages réels sont les suivants:

  1. Facilitez la modification de la mise en œuvre technique tout en veillant à ne pas modifier le comportement (refactoring). Un code correctement testé par unité peut être remanié / nettoyé de manière agressive avec peu de chance de casser quoi que ce soit sans le remarquer.
  2. Donnez aux développeurs l'assurance nécessaire pour ajouter un comportement ou apporter des correctifs.
  3. Documentez votre code
  4. Indiquez les zones de votre code qui sont étroitement associées. Il est difficile de code de test unitaire qui est étroitement couplé
  5. Fournissez un moyen d'utiliser votre API et recherchez les difficultés dès le début
  6. Indique des méthodes et des classes peu cohésives.

Vous devez effectuer des tests unitaires car il est dans votre intérêt de fournir un produit maintenable et de qualité à votre client.

Je suggérerais que vous l'utilisiez pour n'importe quel système, ou partie d'un système, qui modélise le comportement du monde réel. En d'autres termes, il convient particulièrement au développement d'entreprise. Je ne l'emploierais pas pour des programmes jetables / utilitaires. Je ne l'utiliserais pas pour les parties d'un système qui sont problématiques à tester (l'interface utilisateur est un exemple courant, mais ce n'est pas toujours le cas)

Le principal inconvénient est que les développeurs testent une unité trop grande ou considèrent une méthode comme une unité. Cela est particulièrement vrai si vous ne comprenez pas Inversion of Control . Dans ce cas, vos tests unitaires deviendront toujours des tests d'intégration de bout en bout. Le test unitaire doit tester les comportements individuels - et la plupart des méthodes ont de nombreux comportements.

La plus grande idée fausse est que les programmeurs ne devraient pas tester. Seuls les programmeurs mauvais ou paresseux le croient. Le gars qui construit votre toit ne devrait-il pas le tester? Le médecin qui remplace une valve cardiaque ne devrait-il pas tester la nouvelle valve? Seul un programmeur peut vérifier que son code fonctionne comme il le souhaitait (le contrôle qualité peut tester les cas extrêmes): comment le code se comporte-t-il quand il demande aux programmeurs de faire des choses que le programmeur n’a pas prévues et le client peut effectuer des tests d’acceptation? ce que le client a payé pour le faire)


La principale différence entre les tests unitaires, par opposition à "ouvrir simplement un nouveau projet et tester ce code spécifique", est qu'il est automatisé , donc reproductible .

Si vous testez votre code manuellement, il peut vous convaincre que le code fonctionne parfaitement - dans son état actuel . Mais qu'en est-il une semaine plus tard, lorsque vous y avez apporté une légère modification? Souhaitez-vous le tester à nouveau manuellement chaque fois que quelque chose change dans votre code? Très probablement pas :-(

Mais si vous pouvez exécuter vos tests à tout moment, en un seul clic, exactement de la même manière, en quelques secondes , ils vous montreront immédiatement si quelque chose est cassé. Et si vous intégrez également les tests unitaires dans votre processus de génération automatisé, ils vous alerteront des bogues, même dans les cas où une modification apparemment sans lien a brisé quelque chose dans une partie éloignée de la base de code - alors qu'il ne vous arrivait même pas qu'il y ait un besoin de retester cette fonctionnalité particulière.

C'est le principal avantage des tests unitaires par rapport aux tests manuels. Mais attendez, il y a plus:

  • Les tests unitaires raccourcissent considérablement la boucle de rétroaction de développement : avec un service de test séparé, il peut vous falloir des semaines pour savoir qu’il ya un bogue dans votre code. À ce stade, vous avez déjà oublié une bonne partie du contexte. trouvez et corrigez le bogue; OTOH avec les tests unitaires, le cycle de feedback est mesuré en secondes et le processus de correction de bogue suit généralement les lignes suivantes: "oh sh * t, j'ai oublié de vérifier cette condition ici" :-)
  • les tests unitaires documentent efficacement (votre compréhension du comportement) votre code
  • les tests unitaires vous obligent à réévaluer vos choix de conception, ce qui se traduit par une conception plus simple et plus propre

Les frameworks de tests unitaires, à leur tour, facilitent l'écriture et l'exécution de vos tests.


Le test unitaire consiste à écrire du code qui teste le code de votre application.

La partie Unit du nom concerne l’intention de tester de petites unités de code (une méthode par exemple) à la fois.

xUnit est là pour vous aider avec ces tests - ce sont des frameworks qui vous aident avec cela. Les lanceurs de tests automatisés vous indiquent notamment quels tests ont échoué et lesquels ont réussi.

Ils ont également la possibilité de configurer le code commun dont vous avez besoin avant chaque test et de le supprimer lorsque tous les tests sont terminés.

Vous pouvez avoir un test pour vérifier qu'une exception attendue a été levée, sans avoir à écrire vous-même le bloc catch catch catch.


Le test unitaire est le test d'une unité de code (par exemple, une seule fonction) sans qu'il soit nécessaire de disposer de l'infrastructure sur laquelle repose cette unité de code. c'est-à-dire le tester isolément.

Si, par exemple, la fonction que vous testez se connecte à une base de données et effectue une mise à jour, vous ne souhaitez peut-être pas effectuer cette mise à jour dans un test unitaire. Vous le feriez s'il s'agissait d'un test d'intégration, mais dans ce cas ce n'est pas le cas.

Ainsi, un test unitaire permettrait d’exercer les fonctionnalités incluses dans la "fonction" que vous testez sans les effets secondaires de la mise à jour de la base de données.

Supposons que votre fonction récupère des nombres dans une base de données et effectue ensuite un calcul d'écart-type. Qu'essayez-vous de tester ici? Que l'écart type est calculé correctement ou que les données sont renvoyées de la base de données?

Dans un test unitaire, vous voulez simplement vérifier que l'écart type est calculé correctement. Dans un test d'intégration, vous voulez tester le calcul de l'écart type et l'extraction de la base de données.


Les tests unitaires et TDD en général vous permettent d'avoir des cycles de retour plus courts sur le logiciel que vous écrivez. Au lieu d'avoir une grande phase de test à la toute fin de l'implémentation, vous testez de manière incrémentielle tout ce que vous écrivez. Cela augmente beaucoup la qualité du code, comme vous le voyez tout de suite, là où vous pourriez avoir des bogues.


Pour en savoir plus sur les avantages philosophiques des tests unitaires et du TDD, voici quelques-unes de leurs observations clés, qui m'ont frappé lors de mes premiers pas hésitants sur la voie de l'illumination du TDD (aucun original ou nécessairement nouveau) ...

  1. TDD ne signifie PAS écrire deux fois plus de code. Le code de test est en général assez rapide et facile à écrire et constitue un élément essentiel de votre processus de conception.

  2. TDD vous aide à comprendre quand arrêter de coder! Vos tests vous donnent l’assurance que vous en avez fait assez pour le moment et que vous pouvez cesser d’affiner et passer à la prochaine étape.

  3. Les tests et le code fonctionnent ensemble pour obtenir un meilleur code. Votre code pourrait être mauvais / buggy. Votre test pourrait être mauvais / buggy. En TDD, vous misez sur les chances que les DEUX soient mauvais / buggy assez faibles. C’est souvent le test qui doit être corrigé, mais c’est toujours un bon résultat.

  4. TDD aide à coder la constipation. Vous savez que vous avez tellement de choses à faire que vous savez à peine par où commencer? Nous sommes vendredi après-midi, si vous ne faites que tergiverser quelques heures de plus ... TDD vous permet de préciser très rapidement ce que vous pensez devoir faire et de faire en sorte que le codage progresse rapidement. De plus, à l'instar des rats de laboratoire, je pense que nous répondons tous à ce grand feu vert et travaillons plus fort pour le revoir!

  5. Dans le même esprit, ces types de concepteurs peuvent voir ce sur quoi ils travaillent. Ils peuvent s'égarer pour une pause jus / cigarette / iphone et revenir à un moniteur qui leur donne immédiatement une indication visuelle de l'endroit où ils se sont rendus. TDD nous donne quelque chose de similaire. Il est plus facile de voir où nous en sommes quand la vie intervient ...

  6. Je pense que c'est Fowler qui a déclaré: "Les tests imparfaits, effectués fréquemment, sont bien meilleurs que les tests parfaits qui ne sont jamais écrits". J'interprète cela comme une permission de rédiger des tests là où je pense qu'ils seront plus utiles même si le reste de la couverture de code que je propose est terriblement incomplet.

  7. TDD apporte son aide de nombreuses manières surprenantes. De bons tests unitaires peuvent aider à documenter ce que quelque chose est censé faire, ils peuvent vous aider à faire migrer le code d'un projet à un autre et vous donner un sentiment de supériorité injustifié par rapport à vos collègues non-testeurs :)

Cette présentation est une excellente introduction à tous les tests de qualité.


Test Driven Development a en quelque sorte repris le terme de test unitaire. En tant que vieux chronométreur, je mentionnerai une définition plus générique.

Le test unitaire signifie également le test d'un seul composant dans un système plus grand. Ce composant unique pourrait être une dll, un exe, une bibliothèque de classes, etc. Il pourrait même s'agir d'un système unique dans une application multi-système. Donc, finalement, le test unitaire finit par être le test de ce que vous voulez appeler une seule partie d'un système plus grand.

Vous pouvez ensuite passer aux tests intégrés ou aux tests de système en testant la manière dont tous les composants fonctionnent ensemble.


Utilisez Testivus . Tout ce que vous avez besoin de savoir se trouve juste là :)


Je pense que le point que vous ne comprenez pas, c'est que les frameworks de tests unitaires tels que NUnit (et autres) vous aideront à automatiser les tests de petite à moyenne taille. Habituellement, vous pouvez exécuter les tests dans une interface utilisateur graphique (c'est le cas de NUnit , par exemple) en cliquant simplement sur un bouton, puis, espérons-le, que la barre de progression reste verte. Si elle devient rouge, la structure vous indique quel test a échoué et ce qui a mal tourné. Dans un test unitaire normal, vous utilisez souvent des assertions, par exemple Assert.AreEqual(expectedValue, actualValue, "some description") - ainsi, si les deux valeurs ne sont pas Assert.AreEqual(expectedValue, actualValue, "some description") vous verrez une erreur disant "une description: attendu <attendValue> mais était < actualValue> ".

En conclusion, les tests unitaires rendront les tests plus rapides et beaucoup plus confortables pour les développeurs. Vous pouvez exécuter tous les tests unitaires avant de valider le nouveau code afin de ne pas interrompre le processus de construction d'autres développeurs sur le même projet.





glossary