Mettre en œuvre des tests unitaires dans une entreprise qui ne le fait pas

19

Le responsable du développement logiciel de mon entreprise vient de "démissionner" (c'est-à-dire d'être licencié) et nous cherchons maintenant à améliorer les pratiques de développement de notre entreprise. Nous voulons implémenter les tests unitaires dans tous les logiciels créés à partir d'ici.

Les commentaires des développeurs sont les suivants:

  • Nous savons que les tests sont précieux
  • Mais, vous changez toujours les spécifications donc ce serait une perte de temps
  • Et, vos délais sont si serrés que nous n'avons pas assez de temps pour tester de toute façon

Voici les commentaires du PDG:

  • J'aimerais que notre entreprise ait des tests automatisés, mais je ne sais pas comment y arriver
  • Nous n'avons pas le temps d'écrire de grands documents de spécifications

Comment les développeurs obtiennent-ils les spécifications maintenant? Bouche à oreille ou diapositive PowerPoint. De toute évidence, c'est un gros problème. Ma suggestion est la suivante:

  • Donnons également aux développeurs un ensemble de données de test et de tests unitaires
  • Voilà la spécification. C'est à la direction d'être claire et quantitative sur ce qu'elle veut.
  • Les développeurs peuvent mettre toute autre fonctionnalité qu'ils jugent nécessaire et qui n'a pas besoin d'être couverte par des tests

Eh bien, si vous avez déjà été dans une entreprise dans cette situation, comment avez-vous résolu le problème? Cette approche semble-t-elle raisonnable?

Pete SupportMonica
la source
1
Cela me semble une cause perdue. Les tests unitaires prouvent que vous êtes conforme à la spécification, mais cela change constamment en fonction des développeurs (il ne s'agit donc pas vraiment d'une spécification, mais plutôt d'une liste de souhaits) et votre PDG n'a aucune idée.
James
@James - Les entreprises ont besoin de changer, autant que tout ce qui concerne l'ingénierie logicielle concerne la gestion de ce changement. Pour moi, ce que le PDG a dit est parfaitement raisonnable.
Mark Booth
@MarkBooth Il y a du changement et il y a un état constant de flux. Relisez la question. Cette entreprise se rattrape au fur et à mesure.
James
@James Vous portez un jugement de valeur sans fondement réel. Ce n'est pas parce que les développeurs se plaignent que l'entreprise invente au fur et à mesure . Certains d'entre nous ne travaillent pas dans de beaux environnements planifiés et faciles à spécifier. J'ai de nouveaux utilisateurs chaque semaine, qui veulent tous faire quelque chose de légèrement différent des utilisateurs précédents. Ils découvrent souvent, au milieu du temps qui leur est alloué, que le logiciel ne fait pas ce dont ils ont besoin. Je n'aime peut-être pas être appelé un samedi pour mettre en œuvre quelque chose dont ils ignoraient avoir besoin, mais cela fait souvent partie du travail dans un endroit agile.
Mark Booth

Réponses:

17

Il semble que vous mélangez deux types de tests différents: les tests unitaires et les tests système / d'acceptation . Les premiers opèrent à un niveau inférieur, testant de petits morceaux de code (généralement des méthodes individuelles), qui résident généralement profondément dans le programme, non directement visibles par les utilisateurs. Ce dernier teste l'ensemble du programme vu par ses utilisateurs, à un niveau de granularité beaucoup plus élevé. Ainsi, seul ce dernier peut être basé sur n'importe quelle forme de spécification du système.

La séparation des deux problèmes facilite le passage à un processus de développement amélioré. Commencez à écrire des tests unitaires dès que possible , quelle que soit la façon dont le logiciel est (non) spécifié à haut niveau. Chaque fois qu'un développeur crée ou modifie une méthode, il fait quelque chose de concret, qui peut (et devrait) être testé unitaire. D'après mon expérience, même la modification des exigences de haut niveau n'affecte généralement pas ces blocs de code de niveau inférieur de manière spectaculaire: le code doit principalement être réorganisé, plutôt que jeté ou réécrit complètement. Par conséquent, la plupart des tests unitaires existants continueront de fonctionner correctement.

Une condition importante pour permettre les tests unitaires est: les délais ne devraient pas être décidés par la direction à l'avance, mais devraient plutôt être basés sur des estimations de travail par les développeurs (qui à leur tour devraient inclure dans leur estimation le temps nécessaire pour écrire les tests unitaires appropriés). Ou, si le délai est fixé, le volume de livraison doit être négociable. Aucune (mauvaise) gestion ne peut changer la vérité fondamentale selon laquelle un nombre donné de développeurs ne peuvent fournir qu'une certaine quantité de travail de qualité dans un laps de temps donné.

Parallèlement à cela, commencez à discuter de la meilleure façon de clarifier et de documenter les exigences et de les transformer en tests d'acceptation de haut niveau. Il s'agit d'un processus de raffinement successif plus long, qui peut facilement prendre des années pour atteindre un état meilleur et stable dans toute une organisation. Une chose semble assez sûre dans votre description: essayer de corriger des exigences en constante évolution en écrivant des documents de spécifications volumineuses à l'avance ne fonctionnera tout simplement pas . Au lieu de cela, il est recommandé d' aller vers une approche plus agile, avec des versions de logiciels et des démonstrations fréquentes pour les utilisateurs, et de nombreuses discussions sur ce qu'ils veulent réellement. L'utilisateur a le droit de changer d'avis à tout moment sur les exigences - cependant, chaque changement a son coût (en temps et en argent). Les développeurs peuvent estimer le coût de chaque demande de modification, ce qui permet à l'utilisateur / propriétaire du produit de prendre des décisions éclairées. "Sûrement, ce changement de fonctionnalité serait bien ... mais s'il retarde la sortie de cette autre fonctionnalité cruciale et coûte si cher, mettons-le dans le backlog pour l'instant".

Amener les utilisateurs à définir des cas de test d'acceptation et à créer des données de test est un excellent moyen de les impliquer davantage et de renforcer la confiance mutuelle entre les utilisateurs et les développeurs. Cela oblige les deux parties à se concentrer sur des critères d'acceptation concrets, mesurables et testables, et à réfléchir aux cas d'utilisation de manière beaucoup plus détaillée que typique. En conséquence, les utilisateurs peuvent vérifier de première main l'état actuel du développement à chaque version, et les développeurs obtiennent des commentaires de mesure plus concrets et tangibles sur l'état du projet. Notez cependant que cela nécessite un plus grand engagement des utilisateurs et de nouveaux modes de fonctionnement, ce qui peut être difficile à accepter et à apprendre.

Péter Török
la source
1
Et la raison du downvote est ...?
Péter Török
1
+1 pour "évoluer vers une approche plus agile", cela me rappelle "Marcher sur l'eau et développer des logiciels à partir d'une spécification sont faciles si les deux sont figés". - Edward V Berard
Mark Booth
@Peter Torok Merci ... avez-vous des liens vers des informations pertinentes sur les tests d'acceptation?
Pete SupportMonica
@Pete, il est difficile d'être plus précis sans en savoir plus sur vos projets, les types d'applications, etc. La recherche rapide sur Google montre cependant des liens prometteurs.
Péter Török
8

Mon expérience de la transition

Pendant de nombreuses années, je pensais à tort que je n'avais pas assez de temps pour écrire des tests unitaires pour mon code. Quand j'ai fait des tests, ils étaient gonflés, des choses lourdes qui ne m'ont encouragé à penser que je ne devrais jamais écrire des tests unitaires que lorsque je savais qu'ils étaient nécessaires.

Récemment, j'ai été encouragé à utiliser le développement piloté par les tests et j'ai trouvé que c'était une révélation complète. Je suis maintenant fermement convaincu que je n'ai pas le temps non pas écrire de tests unitaires .

D'après mon expérience, en développant en gardant à l'esprit les tests, vous vous retrouvez avec des interfaces plus propres, des classes et des modules plus ciblés et généralement plus SOLIDES code et testable.

Chaque fois que je travaille avec du code hérité qui n'a pas de tests unitaires et que je dois tester manuellement quelque chose, je continue de penser "ce serait tellement plus rapide si ce code avait déjà des tests unitaires". Chaque fois que je dois essayer d'ajouter une fonctionnalité de test unitaire au code avec un couplage élevé, je continue de penser "ce serait tellement plus facile s'il avait été écrit de manière découplée".

Comparaison et contraste des deux stations expérimentales que je soutiens. L'un existe depuis un certain temps et a beaucoup de code hérité, tandis que l'autre est relativement nouveau.

Lors de l'ajout de fonctionnalités à l'ancien laboratoire, il s'agit souvent de se rendre au laboratoire et de passer de nombreuses heures à travailler sur les implications des fonctionnalités dont ils ont besoin et comment je peux ajouter cette fonctionnalité sans affecter aucune des autres fonctionnalités. Le code n'est tout simplement pas configuré pour permettre des tests hors ligne, donc presque tout doit être développé en ligne. Si j'essayais de développer hors ligne, je me retrouverais avec plus de faux objets qu'il ne serait raisonnable.

Dans le laboratoire plus récent, je peux généralement ajouter des fonctionnalités en les développant hors ligne sur mon bureau, en se moquant uniquement des choses qui sont immédiatement nécessaires, puis en ne passant que peu de temps dans le laboratoire, en résolvant les problèmes restants non résolus -ligne.

Mon conseil

Il semble que vous ayez bien commencé, chaque fois que vous allez apporter de grands changements à votre flux de travail de développement, vous devez vous assurer que tout le monde est impliqué dans la prise de cette décision, et idéalement que la plupart des gens y ont adhéré. D'après votre question, il semble que vous ayez bien compris. Si les gens ne sont pas enthousiastes à l'idée, elle est vouée à l'échec ou à générer de la mauvaise volonté.

À moins que vous ne puissiez présenter une analyse de rentabilisation convaincante, je ne recommanderais pas une implémentation de base des tests unitaires et des spécifications pour l'ensemble de votre système. Comme je l'ai mentionné ci-dessus, si un système n'est pas conçu avec des tests à l'esprit, il peut être très difficile d'écrire des tests automatisés pour lui.

Au lieu de cela, je recommanderais de commencer petit et d'utiliser la règle du boy-scout :

Laissez toujours le terrain de camping plus propre que vous ne l'avez trouvé.

Si, pendant que vous implémentez quelque chose sur cette base de code, vous pouvez identifier les tests spécifiques requis pour tester le comportement existant et la transition de l'ancien comportement au nouveau, vous avez à la fois documenté le changement de spécification et commencé à implémenter des tests d'unités pour votre système.

Les modules que vous ne touchez pas ne reçoivent pas de tests unitaires, mais si vous ne les touchez pas, c'est probablement parce qu'ils sont déjà testés en profondeur et ne nécessitent aucune modification, ou qu'ils ne sont jamais utilisés.

Ce que vous voulez éviter, c'est gaspiller une charge entière de tests d'écriture d'efforts de développeur qui ne seront jamais nécessaires ( YAGNI fonctionne aussi bien pour le code de test que pour le code de production * 8 '), ne sera plus jamais utilisé et démoralisera les gens en pensant que les tests sont inutiles après tout.

Sommaire

Commencez petit, renforcez progressivement la confiance dans les tests et gagnez de la valeur commerciale en développant des tests quand et où ils profitent le plus à votre équipe.

Mark Booth
la source
2

La première chose à faire n'est pas de se concentrer sur les tests, mais sur le bon déroulement du processus global. Inutile de tester quoi que ce soit si vous ne comprenez pas bien ce qu'il est censé faire!

Donc .. spécifications d'abord et spécifications documentées qui ne changent pas (enfin, pas immédiatement). Vous devez chercher à les faire. Je recommanderais un site Web où les utilisateurs peuvent télécharger les spécifications ou les saisir directement. Vous pouvez également le lier à un outil de suivi des bogues et à un guide sur l'avancement du projet.

Les chances sont, c'est tout ce dont vous avez vraiment besoin. Vous pouvez ajouter des tests unitaires à cela en interne et la direction n'a jamais besoin de savoir que les développeurs effectuent des tests unitaires. D'une certaine manière, c'est comme ça que ça devrait être.

Vous devrez toujours faire des tests du système, mais cela aussi peut être lié au site Web de gestion de projet, une fois publié, l'équipe de test (même s'il s'agit d'un autre développeur chanceux en rotation) peut le mettre à jour avec des tests qu'ils ont utilisés pour voir si le tout est solidaire.

Honnêtement, je ne pense pas que cela va changer du jour au lendemain, si vous avez l'habitude d'obtenir des spécifications de `` bouche à oreille '', alors la bataille va presque entièrement changer ce comportement - et vous allez vous opposer à cela. Un utilisateur (ou BA ou PM ou qui que ce soit) qui a l'habitude de dire "juste faire faire x" et qui a maintenant besoin de tout écrire ne va pas bien répondre, il y a de fortes chances qu'il écrive des documents techniques vagues puis les clarifie avec des mises à jour de bouche à oreille. Alors oubliez les tests unitaires et commencez par le gros problème que vous rencontrez avec le cycle de vie du développement.

gbjbaanb
la source
1

Premier problème: afin de "donner aux développeurs un ensemble de données de test et de tests unitaires", vous devez d'abord écrire ces tests unitaires, qui est un travail de développeurs. Les tests unitaires ne remplacent pas non plus la spécification: la spécification est destinée à avoir un niveau d'abstraction supérieur aux tests unitaires.

Deuxième problème: il semble que vous souhaitiez la couverture maximale des tests unitaires. Dans ce cas, oui, cela coûtera trop de temps et d'argent pour écrire des tests et du code dans un contexte où les exigences changent constamment. Au lieu de cela, décidez quelles parties du code sont critiques et testez à l'unité uniquement ces parties. Dans de nombreux cas, les exigences qui changent n'affectent pas les parties critiques du produit. Un client (ou PDG, ou autre) demande généralement de déplacer ce panneau vers la droite, ou de changer la couleur de ce titre du rouge au vert: des choses dont personne ne se soucie et qui ne nécessitent pas de tests intensifs. D'un autre côté, un client ne demandera jamais de changer l'algorithme de hachage de SHA512 à SHA256 ou de changer la façon dont vous stockez les sessions, alors que ce sont les parties qui nécessiteront le plus de tests.

Arseni Mourzenko
la source