Cet article n'est pas un guide théorique pour écrire des tests et non pas comment utiliser les outils dans une pile spécifique, mais une série de questions courantes, parfois même nombreuses qui n'ont pas été formées, auxquelles j'essaierai de donner des réponses. La source de ces questions est les collègues, les personnes des deux côtés dans les entretiens et les connaissances, et les réponses seront subjectives, courtes et non exhaustives, basées sur le matériel des autres et leur expérience. Le public cible de l'article est les développeurs qui écrivent avec un certain succès, ou du moins essaient d'écrire des tests, mais éprouvent certaines difficultés à les écrire.
J'ai essayé de ne pas être attaché à un langage spécifique afin d'augmenter la portée des lecteurs, mais je ferai une réserve tout de suite que je travaille dans l'écosystème PHP en utilisant PHPUnit, et donc certaines de mes conclusions peuvent ne pas convenir à d'autres écosystèmes. Lors de la sélection des questions et de la rédaction, je me suis concentré sur de nombreux rapports et articles et je les ai utilisés comme référence.
La raison de l'écriture était le récent article « PHPUnit. Wretting the Doctrine Entity Manager "par chalut , dont je vais également discuter certains.
Liste de questions:
- Pour écrire ou ne pas écrire des tests?
- Et si le temps n'est pas alloué aux tests?
- Types de tests, comment choisir?
- Pourquoi est-il difficile pour moi de passer des tests pendant longtemps?
- Comment tester des méthodes privées?
- Comment écrire des tests d'intégration? Comment tester la base?
- Comment: intégration ou fonctionnel?
- Que faire des dépendances externes?
- Comment simplifier la navigation entre les tests et le sujet du test?
- Dois-je utiliser TDD?
- Quoi d'autre peut être utilisé pour améliorer le code?
Pour écrire ou ne pas écrire des tests?
J'ai vu beaucoup d'opinions à ce sujet, mais je me suis exprimé: j'ai besoin de me concentrer sur les besoins de l'entreprise.
Pour un morceau de code fait en quelques heures sur le genou, les tests ne sont pas nécessaires. D'un autre côté, pour un grand projet d'entreprise pour des centaines de main-d'œuvre, tous les types de tests populaires sont requis. Et tout ce qui se trouve entre ces pôles doit être considéré comme un cas particulier, en évaluant le coût de certains types de tests: avec des tests, cela devrait être moins que sans eux. Personnellement, j'écris des tests de fumée même pour un petit projet CRUD d'une durée de quelques semaines, car déjà à une telle distance, ils apportent des avantages et réduisent les coûts de développement.
Avantages des tests, brièvement et abstraitement:
- Une réduction significative du coût de correction d'un bogue grâce à une détection précoce.
- Fixation des contrats.
- Documentation de bas niveau.
- Détection de problèmes architecturaux.
Donc, si vos projets ne sont pas des scripts uniques à partir de plusieurs fichiers, je vous recommande vivement d'écrire des tests. Par conséquent, la question du titre devrait être reformulée: "Dans quelle mesure les tests doivent-ils être écrits et lesquels?" À ce sujet plus loin.
Et si le temps n'est pas alloué aux tests?
Ceci est une question très controversée, donc je ferai une fois de plus une réserve que je parle exclusivement de mon opinion subjective, tout en essayant de le faire le plus délicatement possible.
L'écriture de tests est tout autant une tâche que la réflexion, le codage ou le débogage. Les tests sont le même code que la logique métier ou les contrôleurs. Mais avez-vous des questions à leur sujet? Vous ne définissez pas de tâche distincte pour l'écriture d'un contrôleur et ne le coordonnez pas avec les gestionnaires?
Il n'est pas nécessaire de consacrer plus de temps à l'écriture des tests unitaires et d'intégration. Les tests sont écrits dans le cadre de la tâche principale. Le chef technique du projet, en tant que propriétaire du référentiel du projet et personne compétente, décide comment, quoi et avec quels tests de couverture écrire, en se concentrant sur les tâches de l'entreprise, pas en gonflant, mais en réduisant les coûts de développement.
Cependant, il peut arriver que le client ne croie pas aux tests et pense qu'avec son aide, vous n'économisez pas, mais perdez seulement du temps. Il paie de l'argent et fixe des conditions, avec le même succès, il peut vous interdire d'utiliser un thème sombre dans votre IDE ou ordonner d'utiliser cinq espaces en retrait. Et si les conditions ne sont pas discutées ou si la discussion est dans une impasse, alors votre choix est d'accepter ces conditions ou de refuser. Avec des conséquences avisées.
Je ferai une réserve que ce dernier n'est vrai que si vous pouvez passer des tests, en évaluer correctement les coûts et le retour sur investissement estimé. Si vous voulez apprendre à les écrire au détriment de l'employeur sur un projet à court terme, et il est contre, alors je suis de son côté.
Types de tests, comment choisir?

Vous pouvez regarder la pyramide des tests de Mike Cohen: en tant que développeurs, nous nous intéressons aux deux niveaux de test les plus bas. L'effort maximal doit être donné aux tests unitaires, c'est le moins cher (par bon marché, je veux dire le temps consacré au développement et au support), ces tests sont très simples à mettre en œuvre, très simples à exécuter, ils fonctionnent rapidement.
Mais les tests unitaires sont-ils toujours applicables ou recommandés? Je crois que pour les CRUD primitifs, de tels tests prendront trop de temps avec peu d'impact et ne garantissent rien. Essayez de tester le référentiel (référentiel dans DataMapper) puis répondez à la question, qu'est-ce que cela nous a donné. Mais pour une variété de calculatrices, cette approche sera idéale.
Essayez toujours d'écrire des tests unitaires lorsque cela est possible, mais ne testez pas ce qui est inutile à tester.
Comment tester le travail conjoint du backend et du frontend, s'il s'agit de projets différents sur des piles différentes? Tout comme le backend et l'application mobile: il s'agit de tests système, et cela devrait intéresser les ingénieurs QA et DevOps, pas les développeurs (enfin, seulement si vous n'avez pas une vraie mêlée impitoyable, où le seul rôle disponible est un développeur full stack).
De plus, les tests système sont les plus coûteux en termes de développement et de support, à la fois en temps et en infrastructure. La solution des problèmes liés à cela est déjà hors de la compétence des développeurs «linéaires» et la question de son application et des volumes doit être tranchée par le directeur technique et les responsables des domaines en collaboration avec l'entreprise.
Pourquoi est-il difficile pour moi de passer des tests pendant longtemps?
Parfois, il est difficile d'écrire des tests car le code n'est pas prêt pour eux. Une pile de foules, où certains en donnent d'autres, sont également une conséquence.
N'utilisez pas de registres, de singletones, de localisateurs, vous compliquez grandement votre vie avec cela. C'était la principale revendication de l'article auquel j'ai fait référence ci-dessus. Utilisez DI et implémentez immédiatement les référentiels nécessaires dans les services. Observez la loi de Déméter pour éviter les chaînes de mokas. Essayez un peu de travail en utilisant la méthodologie TDD.
Traitez les tests comme du code de première classe, en respectant le même code de haute qualité que dans la logique métier. Une mauvaise qualité du code de test réduira la productivité au fil du temps.
Comment tester des méthodes privées?
Pas question. Nous testons un contrat - l'interface fournie par le module aux autres modules. Nous n'avons pas besoin de tester l'implémentation interne, cela peut changer.
Que se passe-t-il s'il y a une logique compliquée à l'intérieur du test et que le test du contrat se transforme en une grande quantité d'entrée, où quelque chose d'étrange se produit à l'intérieur? Il est nécessaire de refactoriser le code, de le distribuer dans différentes classes, où ces méthodes privées deviendront publiques, elles écrivent déjà des tests unitaires. Et s'il n'y avait pas de tests, de tels endroits seraient difficiles à détecter, ce qui augmenterait le coût de la prise en charge d'un tel code.
Comment écrire des tests d'intégration? Comment tester la base?
Utilisez des appareils. Explorez les outils populaires de votre pile.
N'écrivez pas de grands packs universels de luminaires, utilisez leur nombre minimum. Si vous avez besoin d'un certain état d'objets pour vos tests, ne réutilisez pas de tels appareils dans d'autres endroits où un tel état n'est pas requis, sinon le support de test deviendra plus compliqué: les changer pour certains tests en cassera d'autres et prendra plus de temps.
Il existe des tests d'intégration qui ne passent pas par un cycle complet de la demande à la réponse, et l'interaction des classes n'est vérifiée qu'à l'intérieur du composant. S'ils n'ont pas de travail direct avec la base de données, vous pouvez créer un ensemble de données et / ou de mok qui iront dans l'entrée. Dans de tels cas, vous pouvez éviter l'utilisation de luminaires et réduire la complexité et le temps d'exécution de ces tests d'intégration au niveau modulaire.
Comment: intégration ou fonctionnel?
Les tests d'intégration sont l'un des niveaux de test en termes d'isolement. Tests fonctionnels - tests de conformité. Ces définitions se situent sur des plans différents, et vous ne pouvez pas mettre un signe égal entre elles, mais dans la pratique dans les conversations entre développeurs, elles signifient la même chose, bien que ce ne soit pas correct.
Que faire des dépendances externes?
Nous remplaçons les dépendances externes par moki. Non seulement pour les tests unitaires, mais aussi pour les tests d'intégration.
Par exemple, nous utilisons le client HTTPS pour accéder à certaines API via la classe Guzzle. Si vous créez une instance d'une telle classe à l'intérieur de la classe testée, il sera difficile de la remplacer, mais la solution sera très simple: nous implémentons un tel client dans le constructeur, et pendant les tests nous le remplacerons par un moch.
Comment simplifier la navigation entre les tests et le sujet du test?
Les outils de développement modernes peuvent suivre l'emplacement des tests ou des classes de test si vous utilisez des normes de dénomination. Pour faciliter la navigation, vous pouvez utiliser le raccourci clavier Ctrl + Maj + T dans les produits JetBrains, en outre, si le test n'existe pas, vous serez invité à le créer et à créer un filaire.
Parfois, vous avez besoin de plusieurs classes ou méthodes de test différentes pour le sujet du test, dans ce cas, vous devez aider l'IDE, par exemple, ajouter l'annotation @covers dans le cas de PHPUnit.
Dois-je utiliser TDD?
TDD est l'une des méthodologies de développement dans lesquelles écrire de manière itérative et nécessairement des tests d'abord, puis du code. L'essayer en vaut vraiment la peine, il vous apprendra à écrire du code bien testé. Cependant, cette approche n'a pas été largement utilisée, elle a des problèmes. L'un de ces problèmes est que vous écrivez des tests que vous n'écririez pas avec l'approche classique. Et ces tests doivent également être pris en charge, y consacrer du temps, et les avantages qui en découlent sont minimes. Par exemple, des tests pour les setters ou des tests pour les classes où rien ne se passe, sauf les appels de dépendance. Ces emplacements sont mieux vérifiés par des tests d'intégration.
Quoi d'autre peut être utilisé pour améliorer le code?
Les outils d'analyse statique sont un autre moyen d'améliorer la qualité de votre code. Ils se chevauchent partiellement avec les tests par le résultat, mais ils trouvent souvent que les tests n'ont pas été trouvés, en particulier avec une faible couverture. Leur avantage incontestable - vous voyez le résultat immédiatement dans l'IDE et obtenez des commentaires instantanément.
Cela ne signifie pas qu'il suffit de les laisser uniquement sur l'IDE, je recommande fortement de les utiliser également sur le CI pour voir les erreurs potentielles et ne pas gâcher un tel code.
Je recommande également d'ajouter la prise en charge de l'outil de vérification du style de code à l'IDE et au CI. Les erreurs sont souvent cachées dans le code imprudemment écrit, et ces outils vous permettent de trouver de telles zones.
Matériaux pour étude ultérieure