web-dev-qa-db-fra.com

Est-il nécessaire de garder des tests pour des fonctions simples (autonomes)?

Considère ceci:

public function polynominal($a, $b, $c, $d)
{
    return  $a * pow($x, 3) + $b * pow($x, 2) + $c * $x + $d;
}

Supposons que vous écriviez divers tests pour la fonction ci-dessus et que vous prouviez à vous-même et aux autres que "cela fonctionne".

Pourquoi ne pas supprimer ces tests et vivre heureux pour toujours? Mon point est que certaines fonctions n'ont pas besoin d'être testées en continu une fois qu'elles ont fait leurs preuves. Je cherche des contre-points qui disent, oui ces fonctions doivent encore être testées, car: ... Ou que oui, celles-ci n'ont pas besoin d'être testées ...

36
Dennis

Les tests de régression

Il s'agit de tests de régression .

Imaginez le prochain développeur regardant votre méthode et remarquant que vous utilisez des nombres magiques. On lui a dit que les nombres magiques sont mauvais, alors il crée deux constantes, une pour le numéro deux, l'autre pour le numéro trois - il n'y a rien de mal à faire ce changement; ce n'est pas comme s'il modifiait votre implémentation déjà correcte.

Distrait, il inverse deux constantes.

Il valide le code, et tout semble fonctionner correctement, car aucun test de régression n'est exécuté après chaque validation.

Un jour (peut-être des semaines plus tard), quelque chose se brise ailleurs. Et par ailleurs, je veux dire à l'emplacement complètement opposé de la base de code, qui semble n'avoir rien à voir avec la fonction polynominal. Des heures de débogage douloureux mènent au coupable. Pendant ce temps, l'application continue d'échouer en production, causant de nombreux problèmes à vos clients.

Garder les tests originaux que vous avez écrits pourrait éviter une telle douleur. Le développeur distrait commettait le code et voyait presque immédiatement qu'il avait cassé quelque chose; un tel code n'atteindra même pas la production. Les tests unitaires seront en outre très précis sur l'emplacement de l'erreur . Le résoudre ne serait pas difficile.

Un effet secondaire ...

En fait, la plupart du refactoring est fortement basé sur des tests de régression. Faites un petit changement. Tester. Si ça passe, tout va bien.

L'effet secondaire est que si vous n'avez pas de tests, pratiquement toute refactorisation devient un énorme risque de rupture du code. Étant donné qu'il y a de nombreux cas, il est déjà difficile d'expliquer à la direction que le refactoring devrait être fait, il serait encore plus difficile de le faire après que vos précédentes tentatives de refactoring aient introduit plusieurs bogues.

En ayant une suite complète de tests, vous encouragez la refactorisation, et donc mieux, un code plus propre. Sans risque, il devient très tentant de refaçonner davantage, régulièrement.

Changements dans les exigences

Un autre aspect essentiel est que les exigences changent. On peut vous demander pour gérer des nombres complexes , et tout à coup, vous devez rechercher dans votre journal de contrôle de version pour trouver les tests précédents, les restaurer et commencer à ajouter de nouveaux tests.

Pourquoi tout ce tracas? Pourquoi supprimer des tests pour les ajouter plus tard? Vous auriez pu les garder en premier lieu.

78
Arseni Mourzenko

Parce que rien n'est si simple qu'il ne peut pas y avoir de bugs.

Votre code, à première vue, semble exempt de bogues. Il s'agit en fait d'une simple représentation programmatique d'une fonction polynomiale.

Sauf qu'il a un bug ...

public function polynominal($a, $b, $c, $d)
{
    return  $a * pow($x, 3) + $b * pow($x, 2) + $c * $x + $d;
}

$x n'est pas défini comme une entrée pour votre code, et selon la langue ou le runtime, ou la portée, votre fonction peut ne pas fonctionner, peut entraîner des résultats invalides, ou peut planter un vaisseau spatial .


Addenda:

Bien que vous puissiez considérer que votre code est exempt de bogues pour l'instant, combien de temps cela reste difficile à dire. Bien que l'on puisse affirmer que l'écriture d'un test pour un morceau de code aussi trivial n'en vaut pas la peine, ayant déjà écrit le test, le travail est terminé et le supprimer est en train de supprimer un garde tangible.

Il convient également de noter les services de couverture de code (comme coveralls.io) qui donnent une bonne indication de la couverture fournie par une suite de tests. En couvrant chaque ligne de code, vous donnez une mesure décente de la quantité (sinon de la qualité) des tests que vous effectuez. En combinaison avec de nombreux petits tests, ces services vous indiquent au moins où pas pour rechercher un bogue quand il se produit.

En fin de compte, si vous avez déjà un test écrit, conservez-le . Parce que l'espace ou le gain de temps de la suppression sera probablement beaucoup moins élevé que la dette technique plus tard si un bug survient.

44
user69037

Oui. Si nous pouvions dire avec une confiance de 100%, avec certitude: cette fonction ne sera jamais éditée et ne fonctionnera jamais dans un contexte qui pourrait entraîner son échec - si nous pouvions dire cela, nous pourrions abandonner les tests et économiser quelques millisecondes sur chaque Construction CI.

Mais nous ne pouvons pas. Ou, nous ne pouvons pas avec de nombreuses fonctions. Et il est plus simple d'avoir une règle d'exécution de tous les tests tout le temps que de s'efforcer de déterminer exactement le seuil de confiance dont nous sommes satisfaits et exactement la confiance que nous avons dans l'immuabilité et l'infaillibilité d'une fonction donnée.

Et le temps de traitement est bon marché. Ces millisecondes économisées, même multipliées plusieurs fois, ne totalisent pas assez pour justifier de prendre le temps avec chaque fonction pour demander: avons-nous suffisamment confiance pour ne plus jamais le tester?

21
Carl Manaster

Tout ce qui a été dit dans les autres réponses est correct, mais j'en ajouterai une de plus.

Documentation

Les tests unitaires, s'ils sont bien écrits, peuvent expliquer à un développeur exactement ce que fait une fonction, quelles sont ses attentes d'entrée/sortie et, plus important encore, quel comportement peut en être attendu.

Cela peut faciliter la détection d'un bug et réduire la confusion.

Tout le monde ne se souvient pas des polynômes, de la géométrie ou même de l'algèbre :) Mais un bon test unitaire enregistré dans le contrôle de version se souviendra pour moi.

Pour un exemple de son utilité en tant que documentation, consultez l'introduction de Jasmine: http://jasmine.github.io/Edge/introduction.html Donnez-lui quelques secondes pour charger, puis faites défiler vers le bas. Vous verrez l'intégralité de l'API Jasmine documentée en tant que sortie de test unitaire.

[Mise à jour basée sur les commentaires de @Warbo] Les tests sont également garantis à jour car s'ils ne le sont pas, ils échoueront, ce qui entraînera généralement un échec de génération si CI est utilisé. La documentation externe change indépendamment du code et n'est donc pas nécessairement à jour.

12
Brandon

Vérification de la réalité

J'ai été dans des environnements difficiles où les tests sont "une perte de temps" lors de la budgétisation et du calendrier, puis "une partie fondamentale de l'assurance qualité" une fois que le client a affaire à des bogues, donc mon opinion est plus fluide que d'autres.

Vous avez un budget. Votre travail consiste à obtenir le meilleur produit possible avec ce budget, quelle que soit la définition du "meilleur", vous pouvez gratter ensemble (ce n'est pas un mot facile à définir). Fin de l'histoire.

Le test est a outil dans votre inventaire. Vous devriez l'utiliser, car c'est un bon outil , avec une longue histoire d'économiser des millions, voire des milliards de dollars. Si vous en avez l'occasion, vous devez ajouter des tests à ces fonctions simples. Cela pourrait sauver votre peau un jour.

Mais dans le monde réel, avec des contraintes de budget et de calendrier, cela peut ne pas arriver. Ne vous faites pas esclave de la procédure. Les fonctions de test sont agréables, mais à un moment donné, vos heures de travail peuvent être mieux dépensées pour écrire la documentation du développeur en mots plutôt qu'en code, donc le prochain développeur n'a pas autant besoin de tests. Ou il vaut mieux dépenser la refactorisation de la base de code afin que vous n'ayez pas à rester aussi difficile qu'une bête. Ou peut-être qu'il vaut mieux passer du temps à parler à votre patron du budget et du calendrier afin qu'il comprenne mieux ce pour quoi il enchérit lorsque la prochaine ronde de financement tombera.

Le développement de logiciels est un équilibre. Comptez toujours le coût d'opportunité de tout ce que vous faites pour vous assurer qu'il n'y a pas de meilleure façon de passer votre temps.

2
Cort Ammon

Oui, continuez les tests, continuez à les faire fonctionner et continuez à les passer.

Les tests unitaires sont là pour vous protéger (et protéger les autres) de vous-même (et d'eux-mêmes).

Pourquoi garder les tests une bonne idée;

  • Valider la fonctionnalité des exigences précédentes face aux nouvelles exigences et fonctionnalités supplémentaires
  • Vérifier que les exercices de refactoring sont corrects
  • Documentation interne - c'est ainsi que le code devrait être utilisé
  • Test de régression, les choses changent
    • Les modifications cassent-elles l'ancien code?
    • Les modifications nécessitent-elles des demandes de modification supplémentaires ou des mises à jour des fonctions ou du code actuels?
  • Étant donné que les tests sont déjà écrits, conservez-les; c'est le temps et l'argent déjà dépensés qui permettront de réduire les coûts de maintenance plus tard
0
Niall