Ne serait-il pas avantageux d'écrire des tests lors de la révision du code?

24

Un de mes collègues a eu une idée que j'ai trouvée intéressante.

Ne serait-il pas avantageux d'écrire des tests lors de la révision du code, par la personne qui effectue la révision en supposant que nous ne faisons pas TDD?

Pour cette question, supposons qu'il s'agit d'un projet purement académique donc il n'y a pas de vie en jeu. De plus l'équipe est composée de 4 personnes. Tout le monde connaît le langage et connaît tous les outils / bibliothèques / frameworks utilisés et peut écrire des tests. Donc, fondamentalement, les gens qui ne sont pas des ingénieurs ninja fullstack principaux mais des codeurs décents.

Avantages que j'ai trouvés:

  1. Encourage une meilleure compréhension du code lors de la révision pour écrire des tests significatifs.
  2. Vous pouvez ensuite ajouter un examen du code de ces tests effectués par l'auteur du code testé.

J'ai trouvé:

  1. La boucle de rétroaction entre l'écriture de code et les tests se développe.

EDIT: Je sais que cela ne fonctionnera pas bien sur les applications Web "normales". Ce que j'avais à l'esprit était un cas d'angle où vous implémentez des algorithmes scientifiques complexes qui nécessitent une attention aux détails. Supposons quelque chose comme l'implémentation de ma propre bibliothèque de graphes, NLP etc. Je me demande si le code que nous écrivons est isolé des bases de données et tel mais très difficile à comprendre ne serait pas le niveau de contrôle supplémentaire, l'autre personne qui a besoin de comprendre la source coder et faire des tests significatifs, rendre l'ensemble du processus moins sujet à ces bogues moins évidents qui ne plantent pas l'application mais rendent finalement vos résultats inutiles?

Sok Pomaranczowy
la source
3
Vous ne mentionnez pas si cette série de tests irait au-delà des tests qui devraient avoir lieu pendant le développement ou à la place de.
Robbie Dee
3
Il serait avantageux mais plutôt difficile d'écrire unittest (tests-in isolotaion) si "nous ne faisons pas TDD" car le code non tdd est généralement difficile à isoler. L'écriture de tests d'acceptation et / ou de test d'intégration sera également difficile et / ou fragile si vous ne disposez pas d'une couche d'abstraction de base de données (api du référentiel) qui vous permet de définir des conditions préalables reproductibles et non fragiles.
k3b
4
@JoulinRouge: TDD aide à cela. Puisqu'il n'y a pas de code, vous ne pouvez pas adapter le test à votre code.
Jörg W Mittag
6
Cela ressemble à un examen de code VRAIMENT long.
David dit de réintégrer Monica
2
J'ai travaillé dans des endroits où un examen par les pairs impliquait un collègue programmeur examinant chaque ligne que vous avez écrite, les comparant aux directives de style et aux meilleures pratiques, et écrivant les tests unitaires que vous ne pensiez pas écrire.
candied_orange

Réponses:

7

Ne serait-il pas avantageux d'écrire des tests lors de la révision du code, par la personne qui effectue la révision?

J'ai trouvé qu'un bon moment pour écrire des tests, c'est quand vous réalisez que vous avez besoin d'un test pour une situation.

Le changement de tâche pour les ordinateurs coûte cher - encore plus pour les humains.

À ce stade, vous avez généralement une bonne compréhension des exigences et des dépendances du test. Tirez donc parti de l'immersion de votre équipe dans le problème. Si vous devez affiner votre nouveau test à l'avenir, tant mieux, vous avez déjà le cadre / les montages de test en place, et tout ce que vous avez à faire est de changer la partie qui doit être améliorée.

Si cela se produit lors de la révision du code, pourquoi ne pas continuer? Je l'ai déjà fait auparavant. J'ai trouvé que c'était mieux qu'improbable, surtout si vous pouvez le faire rapidement, et encore mieux si vous ne l'auriez pas fait autrement.

En supposant que nous ne faisons pas de TDD?

Même si vous pratiquez TDD, si vous réalisez que vous avez besoin d'un test lors de la révision du code, un que vous n'avez pas, pourquoi ne pas écrire le test sur place?

Avantages

  • Vous tirez parti de votre concentration sur le code examiné.
  • Parfois, la révision du code devient un lieu de rencontre et de conversation lorsque les gens ne s'y intéressent pas. La rédaction d'un test encourage chacun à réfléchir plus activement au code en cours de révision.
  • Les membres plus juniors de l'équipe auront l'occasion d'apprendre de l'expérience de rédaction de tests.
  • Vous pouvez identifier les talents de votre équipe que vous ne saviez pas avoir.

Est-ce vraiment un con que plus de tests peuvent conduire à plus de code? Si le test était nécessaire, et le code était nécessaire pour le test, et maintenant vous l'avez, alors c'est une bonne chose.

Avertissements

Peut-être qu'une partie de l'équipe doit se concentrer sur d'autres choses. Si cela dérange les priorités ou si votre révision de code dépasse le calendrier, vous devez limiter ou couper l'écriture réelle du test. Cependant, la révision du code peut certainement identifier les tests qui doivent être écrits, et peut-être qu'ils peuvent au moins être repoussés pour que le rédacteur les termine plus tard.

Aaron Hall
la source
22

C'est une merveilleuse idée, avec une mise en garde. Ne remplacez pas les tests écrits par le développeur par des tests écrits par le réviseur. Demandez à vos examinateurs de rechercher les cas d'angle et les entrées qui briseront le code. En d'autres termes, demandez-leur d'essayer d'écrire de nouveaux tests que le développeur d'origine n'a pas pensé à écrire.

L'écriture de tests de caractérisation est un moyen absolument merveilleux de comprendre un morceau de code que vous n'avez pas écrit. Le fait que vos réviseurs effectuent des tests supplémentaires sur le code leur permet de mieux comprendre comment le code fonctionne, comment il peut être rompu et comment il peut être amélioré. Pendant tout ce temps, augmentez la couverture de votre code.

Ce sont toutes des victoires dans mon livre.

Canard en caoutchouc
la source
5
C'est presque comme si vous aviez de l'expérience en révisant le code ...
syb0rg
Vous ne savez pas de quoi vous parlez @ syb0rg ... Vous ne pouvez pas le prouver. =;) -
RubberDuck
2
toux ;-)
Mathieu Guindon
2
De plus, un cas de test est à peu près la façon la moins ambiguë de décrire une faille découverte dans la revue :-)
Steve Jessop
1
@ syb0rg Rubber Duck a aidé des milliers ou des millions de programmeurs à corriger leur code . Qui est mieux qualifié pour réviser le code que celui qui en a tant vu?
jpmc26
18

Je ne pense pas que l'idée soit totalement sans fondement - cependant, le principal avantage du TDD et al est que les problèmes sont décelés tôt . Le développeur est également le mieux placé pour repérer les cas d'angle qui nécessitent une attention particulière. Si cela est laissé jusqu'à la révision du code, il existe un risque de perte de ces connaissances.

L'écriture de tests lors de la révision du code souffrirait du même problème que les tests manuels traditionnels - la compréhension des règles métier peut varier d'un développeur à l'autre, tout comme la diligence.

Il y a aussi une discussion séculaire qui se déroulera pour savoir si les développeurs testeraient si bien leur code s'ils savaient qu'il y avait une fonction de test plus en amont qui devrait détecter les bogues les plus graves.

Robbie Dee
la source
Très bonne réponse. Mais que se passe-t-il si nous ne faisons pas de TDD parce que les gens ne le veulent pas et que je n'ai aucun effet de levier sur eux, mais nous devons nous assurer que les résultats que nous obtenons ne sont pas de faux positifs parce qu'une erreur a faussé nos résultats? Le principal risque est que les gens se précipitent pour implémenter quelque chose sans une bonne compréhension, écrivent des tests avec cette mauvaise compréhension en tête, ce qui fait que les tests passent mais produisent finalement du code incorrect. Peut-être que la programmation par paire résoudrait le problème? Mais là encore, il est facile de forcer les gens à comprendre quelque chose sur quelqu'un.
Sok Pomaranczowy
Je pense que peut-être aussi bien que quelqu'un d'autre qui écrit les tests, ceux-ci pourraient être exécutés contre le code de développement pendant que le développement est en cours. Les développeurs en question devraient être sur la même page que l'endroit où se trouve le code, sinon le développeur qui écrit le code pourrait constamment lutter contre les incendies des tests plutôt que de faire fonctionner la chose.
Robbie Dee
Le problème est appelé "biais conformationnel".
ArTs
En fait, je le dirais, distrait du processus de révision du code et le code affecterait le processus de test, ce qui n'est pas ce que vous voulez, ce qui enlève l'avantage clé d'avoir un testeur et un codeur séparés.
ArTs
1
@RobbieDee Si le récepteur du blâme compte vraiment, vous avez un environnement de développement malsain. C'est bien pire que de manquer quelques tests qui auraient été utiles.
jpmc26
5

Je suis d'accord avec la réponse de @ RobbieDee mais j'ai un peu plus à ajouter.

Si vous aimez vraiment cette idée, pourquoi ne pas demander aux mêmes personnes d'écrire les tests avant le code comme critères d'acceptation exécutables pour la user story?

Cela ferait la même chose, tout en gardant les commentaires courts et en amenant tout le monde à avoir une discussion autour de l'histoire, ce qui, je pense, serait plus utile.

Les inconvénients sont le danger d'une rencontre sans fin des critères d'acceptation :-( et je pense que vous essayez d'amener les gens dans la revue de code à jeter un œil au code d'implémentation, mais je suggère la programmation par paires et la rotation des paires comme une meilleure solution pour ce problème.

L'OP a ajouté un montage où ils présentent plus de détails sur ce qui est une fonctionnalité difficile ou lourde d'algorithme.

En réponse à cela, j'ajouterais que votre instinct d'avoir plus de regards sur le problème et la solution est bon. Peut-être jumeler plusieurs personnes individuellement jusqu'à ce que tout le monde ait vu le code d'implémentation et les tests vraiment difficiles. Chacun jetant de nouvelles idées et ajoutant plus de valeur.

Il existe une idée parfois appelée mob-programming, comme l'appairage mais avec plus de gens. C'est presque ce dont vous parlez, mais ils aident au moment de la rédaction plutôt que dans un examen formel par la suite. Ce n'est pas pour tout le monde, et peut nécessiter un pilote (leader) fort pour le faire fonctionner, ou une équipe qui est très à l'aise les uns avec les autres et le processus.

Faire la programmation mob après coup, je suppose, aurait beaucoup des mêmes avantages que de nombreux yeux voient le problème et suggèrent des améliorations et si c'est ainsi que votre équipe est à l'aise de fonctionner, cela peut aider, mais j'essaierais vraiment de garder le nécessaire les occurrences de cela au minimum car je pense que cela pourrait ralentir l'équipe.

Encaitar
la source
Les développeurs devraient peut-être écrire les tests comme bon leur semble, les télécharger dans le référentiel, mais la personne qui effectue la révision devrait écrire leurs propres tests et ne jamais regarder les tests que le développeur a écrits. Si les deux suites de tests réussissent, mais si les tests des examinateurs échouent, il peut y avoir un problème?
Sok Pomaranczowy
1
@SokPomaranczowy, l'ajout de redondance dans l'écriture des tests de différentes personnes a été essayé dans le passé. Je pense que si vous ne faites pas de logiciels vitaux, c'est un gaspillage d'effort et vous devriez plutôt vous concentrer sur l'endroit où il est préférable de passer votre temps (vous n'écrirez jamais TOUS les tests) et avec une bonne communication dans l'équipe, je pense que est une bien meilleure approche.
Encaitar
@Encaitar Je suis d'accord, cela sonne comme un énorme puits de temps qui n'améliorera probablement pas les choses. RoI et tout ça ...
sara
3

Comme vous le dites, si vous dirigez une équipe TDD, cela est théorique puisque le code doit déjà être testé.

Dans l'ensemble, je ne pense pas que ce soit une idée géniale, mais cela dépend de votre approche actuelle et de ce qui fonctionne pour vous. Fondamentalement, le problème que je vois est que vous perdez l'avantage de la "boucle de rétroaction courte" des tests. Recevoir une notification instantanée au moment où vous cassez quelque chose alors que vous écrivez du nouveau code est l'endroit où les tests brillent vraiment. Si vous retardez les tests jusqu'à la révision du code, vous dites essentiellement "nous pourrions avoir résolu ce problème plus tôt en moins de temps et avec moins de personnes impliquées, mais au moins nous avons tous appris quelque chose (peut-être)". Je préfère simplement m'assurer que les gens soumettent le code testé pour examen, puis vous jugez l'exactitude et la maintenabilité des tests. Après tout, la révision du code est pour la révision, pas pour l'écriture de code.

D'un autre côté, je vous recommande de FIDDLE avec les tests / code lors de l'examen. Essayez de casser quelque chose. Commentez une condition if. remplacer un booléen par un vrai / faux littéral. Voir si les tests échouent.

Mais oui, dans l'ensemble, je vous recommande d'écrire vos tests avec votre code, puis de les revoir tous en même temps.

Sara
la source
2

Cela dépend de ce que vous faites dans la révision du code. Je pense qu'il y a deux raisons principales pour écrire des tests à ce stade:

  • tout d'abord, si vous effectuez également une refactorisation lors de la révision du code et que vous notez qu'il n'y a pas suffisamment de tests unitaires pour couvrir le type de refactoring que vous souhaitez appliquer, ajoutez de tels tests

  • deuxièmement, si le code vous semble avoir un bogue et que vous voulez qu'il le prouve (ou le réfute), écrivez un test pour cela

Les deux cas expriment le besoin de tests qui ne sont pas là pour le moment, mais qui devraient l'être. Bien sûr, cela peut dépendre de la culture de votre équipe si ce type de tests doit être écrit par le réviseur ou par l'auteur d'origine, mais quelqu'un doit écrire les tests.

En fait, je ne pense pas que ce soit "un cas de coin" juste adapté aux "algorithmes scientifiques complexes" - bien au contraire, cela convient à tout type de logiciel dont vous attendez un certain degré de qualité.

Doc Brown
la source
2

Non, ne le fais pas. Vous leur ferez penser que TDD est horrible.

Je pense que @ k3b a raison dans les commentaires sur la question. Le code écrit via un processus de type TDD a tendance à ressembler et à interagir très différemment du code écrit sans test. L'ajout de (bons) tests à du code non testé prend généralement beaucoup de refactorisation du code pour clarifier son intention et les parties mobiles.

En ajoutant les tests après avoir écrit le code, vous manquez les aspects architecturaux des avantages de TDD (qui sont à mon avis l'un des principaux avantages). Non seulement cela, vous demandez à quelqu'un d'autre, qui n'est pas si familier avec le code, de prendre le coup d'ajouter des tests qui sont déjà difficiles à ajouter.

Soit la personne qui ajoute des tests devra refactoriser considérablement le code, soit elle devra travailler très dur pour tester le code non testable. De toute façon, ils ne vont pas profiter de l'expérience. Même si ce n'est pas un TDD classique, ils ne le verront pas de cette façon, et vous pouvez les désactiver une fois pour toutes.

(Si vous suivez déjà un processus TDD, l'écriture de tests supplémentaires lors de la révision du code serait moins nuisible, bien que d'après mon expérience, si les tests sont déjà bien écrits, il est tout aussi facile d'expliquer le test supplémentaire à la personne qui soumet le code pour révision et demandez-leur de les écrire.)

Andy Mortimer
la source
1

Les tests unitaires lors de la révision du code sont un mauvais substitut aux tests unitaires pendant le développement.

Ce que vous proposez a beaucoup de sens, intuitivement. À quoi sert la revue? Pour vérifier que le code est bon. À quoi servent les tests? Pour vérifier que le code est bon. Alors pourquoi ne pas combiner les deux?

Voici pourquoi.

Mettre le code sous test est un travail difficile. Écrire du code qui fonctionne uniquement à la seule chose qu'il est censé faire est une chose; écrire du code qui peut être testé de manière efficace et efficiente en est une autre. Le simple fait que le code s'exécute maintenant selon deux scénarios - "travail réel" et "test" - exige une flexibilité beaucoup plus grande, exige que ce code soit capable de se suffire à lui-même de manière significative.

Écrire votre code pour qu'il soit testable est un travail et des compétences supplémentaires. Refactoriser le code de quelqu'un d' autre pour la testabilité, alors qu'il n'a pas été écrit avec la testabilité en tête pour commencer, peut être une tâche majeure.

Vous dupliquez l'effort entre le développeur et le réviseur. Vraisemblablement, votre développeur ne remet pas son code pour examen sans au moins un certain niveau de confiance que cela fonctionne. Il a déjà besoin de tester le code. Maintenant, il existe différents niveaux et étendues de test. Le contrôle qualité teste le code après le développeur et le réviseur. Mais quelle que soit la portée que vous pensez appropriée pour le développeur et le réviseur, cela n'a aucun sens pour le développeur de comprendre comment tester le code à ce niveau une fois , mais de rendre ses tests jetables et difficiles à reproduire, puis d'amener le réviseur à développer à nouveau le test, cette fois automatisés et reproductibles. Vous avez juste tous les deux investi du temps à écrire les mêmes tests - une fois mal, une fois bien.

Vous transformez l'examen en une étape beaucoup plus longue et plus laborieuse. Si les tests constituent une partie importante du processus d'examen, que se passe-t-il lorsque certains tests échouent ? L'examinateur est-il responsable de l'exécution de tous les tests, il doit donc également déboguer le code? Ou est-ce que ça va être ping-pong dans les deux sens, l'un écrit des tests, l'autre les fait passer?

Parfois, vous pouvez écrire tout un tas de tests qui sont tous orthogonaux les uns aux autres, vous n'avez donc pas besoin de faire du ping-pong. Le réviseur écrit une douzaine de tests, la moitié d'entre eux échouent, le développeur corrige les bugs et tous les tests restent valides, et passent maintenant. Mais ... la plupart du temps, vous avez des bogues bloquants, ou des bogues qui nécessitent une refonte et des changements d'API, ou autre chose. Si vous jetez la responsabilité de passer des tests dans les deux sens entre le réviseur et le développeur, alors vous n'êtes pas réellement au stade de la révision. Vous êtes toujours en développement.

La nécessité de passer des tests n'incite pas à un examen plus approfondi. Cela signifie essentiellement que plus vous allez en profondeur, plus vous devez écrire de tests, et ce seront probablement des tests difficiles qui doivent être approfondis dans le système.

Comparez avec le développeur qui écrit les tests, où sa motivation est: si je n'écris pas de tests importants, le réviseur le soulignera dans la revue.

Même le réviseur aura une bien meilleure compréhension du système s'il doit passer en revue des tests approfondis du code , puis s'il doit décider par lui-même quand elle peut arrêter d'écrire un test de recherche approfondie et juste OK la révision du code.

Si le développeur n'écrit pas de tests unitaires, le réviseur ne le fera pas non plus. Il existe de nombreux obstacles à l'adoption du test comme pratique courante. Peut-être que vous êtes trop sous pression et que votre base de code est difficile à tester. Peut-être que vous n'êtes pas très expérimenté dans les tests et que vous ne pouvez pas vous permettre la courbe d'apprentissage. Vous avez peut-être un meurtrier à la hache qui envoie des notes menaçantes aux personnes qui passent des tests. Je ne sais pas!

Mais quelle qu'en soit la cause, il est sûr de parier que cela s'applique aussi bien au réviseur qu'au développeur. Si l'équipe est stressée, le réviseur n'a pas plus de temps que le développeur (si elle le fait, redistribuez le travail afin que les gens ne soient pas aussi stressés ). Si personne ne sait bien écrire les tests unitaires, le réviseur ne le fait probablement pas non plus (si elle le fait, elle devrait s'asseoir et enseigner à ses coéquipiers ).

Cette suggestion ressemble à essayer de passer la balle d'un collègue à un autre. Et je ne vois tout simplement aucun moyen pour que cela fonctionne bien, d' abord et avant tout parce qu'il est vraiment difficile (et malsain) de créer une situation où une personne est la seule à pouvoir faire des tests et une autre personne ne peut pas le faire. aucun test du tout.


Ce qui fonctionne, c'est d' avoir également les tests de couverture. Si le développeur a déjà écrit dix tests, il est beaucoup plus probable que le réviseur puisse suggérer dix autres tests que si le développeur n'en avait pas écrit.

Et, si le test des cas d'angle est une tâche majeure, il pourrait être judicieux de le distribuer plus largement dans l'équipe. ** Une fois que le code est testable en premier lieu, écrire plus de tests devient beaucoup plus facile. **

La révision est le moment idéal pour repérer les cas d'angle. Et, si la critique peut intervenir et écrire un test pour les cas d'angle qu'elle trouve, alors bon - tant mieux! Mais de manière générale, en supposant que le réviseur puisse écrire des tests où le développeur ne semble pas être une très mauvaise idée.

Standback
la source