Comment avez-vous rendu les tests unitaires plus agréables? [fermé]


18

Si vous avez toujours aimé les tests unitaires, tant mieux pour vous! Mais pour les malheureux qui ne sont pas nés avec un tel goût, comment avez-vous réussi à rendre cette tâche plus agréable?

Ce n'est pas une question "quelle est la bonne façon de faire un test unitaire". Je veux simplement connaître de petites astuces personnelles qui réduisent l'ennui (oserais-je dire) d'écrire des tests unitaires.


1
J'adore écrire des tests unitaires et d'autres tests, en partie parce que presque tout le monde aspire (parfois ils aspirent également à fabriquer des outils que je teste). Non, je ne crains pas en tant que développeur. J'aime la convivialité, le plaisir des yeux et l'automatisation. La MbUnitbibliothèque a changé ma vie. Le test automatique est important. Le test automatique fait gagner du temps. Le test automatique permet d'économiser de l'argent. Les tests automatiques peuvent sauver des vies. Le test automatique est le seul moyen. L'autotest est un autre filet de sécurité. Quand je fais partie d'une cinquantaine de personnes travaillant sur une immense architecture, j'ai l'impression d'être encore une autre brique dans un mur. Avec des tests unitaires, je contrôle.
Job

La paresse et la frustration lors des tests unitaires sont une réaction normale au travail que notre cerveau perçoit comme inutile. Je déteste écrire et maintenir des tests unitaires qui ont un retour sur investissement faible ou négatif. Cependant, écrire des tests utiles est une tâche agréable, mais c'est une compétence en soi pour reconnaître ce qui est utile et ce qui est des ordures. Il y a un gars qui écrit un livre sur ce sujet basé sur son blog, vous pouvez lire ici: enterprisecraftsmanship.com/2016/06/01/…
KolA

Réponses:


22

Tout d'abord, je suis d'accord avec vous - si vous écrivez vos tests unitaires sur du code déjà terminé, ou si vous testez manuellement votre code unitaire, je trouve cela extrêmement ennuyeux aussi.

Je trouve qu'il y a deux façons de faire des tests unitaires qui me rendent vraiment agréable:

  1. En utilisant Test Driven Development (TDD) - l'écriture des tests d'abord me permet de penser à la prochaine fonctionnalité ou au comportement dont j'ai besoin dans mon code. Je trouve que conduire vers mon objectif final en petites étapes et voir des progrès tangibles vers cet objectif toutes les quelques minutes est extrêmement gratifiant et agréable.
  2. Lorsqu'il y a des bogues, plutôt que d'aller directement au débogueur, c'est un défi amusant de trouver un moyen d'écrire un test unitaire défaillant qui reproduit le bogue. Il est extrêmement satisfaisant de comprendre enfin les circonstances qui font échouer votre code, puis de le corriger et de regarder la barre devenir verte pour le nouveau test défaillant (et rester verte pour tous vos tests existants).

12

Supériorité suffisante.

Je ne plaisante qu'à moitié. «Regardez-moi, cultivez de bonnes habitudes de programmation! Ce truc de« test unitaire »est quelque chose que Me From Ten Years Ago n'aurait jamais fait - quel idiot! ce travail ennuyeux et fastidieux que je fais en ce moment - mon code sera génial! Je vais obtenir une augmentation à coup sûr! * "

* - Non, je ne le ferai pas.

Je trouve que c'est comme travailler ou manger sainement; jusqu'à ce que les avantages tangibles se concrétisent ("Balles sacrées, je suis vraiment en train d'attraper une merde d'erreurs de régression qui se seraient glissées dans la production!"), la fierté morale de savoir que vous faites la bonne chose peut vous aider à vous transporter par.


7

D'une part, je ne m'assois presque jamais là et j'écris des tests unitaires. Les tests unitaires sont un moyen d'arriver à une fin, pas une fin en soi. Ils sont un moyen de répondre «ce code fait-il la tâche de base qu'il est censé faire».

Par exemple, certaines personnes écriront une fonction, puis ouvriront une session interactive pour la tester sur quelques valeurs et s'assurer qu'elle fonctionne:

def fact x
  if x == 0
    1
  else 
    x * fact(x-1)
  end
end

>> fact 10
=> 3628800
>> fact 7
=> 5040

Mais maintenant, vous découvrez un bug:

>> fact -1
SystemStackError: stack level too deep
    from (irb):2:in `fact'
    from (irb):5:in `fact'
    from (irb):10

Donc vous le corrigez:

def fact x
  if x < 0
    raise "Can't take the factorial of a negative number"
  elsif x == 0
    1
  else 
    x * fact(x-1)
  end
end

>> fact -1
RuntimeError: Can't take the factorial of a negative number
    from (irb):3:in `fact'
    from (irb):10

Mais maintenant, vous devez vraiment tester pour vous assurer que cela fonctionne toujours:

>> fact 10
=> 3628800
>> fact 7
=> 5040

Comme vous pouvez le voir, vous continuez à répéter les mêmes tests ... et vous devez comparer les résultats visuellement. Les tests unitaires sont un moyen d'éviter la répétition dans ce cas; cela réduit la quantité de travail que vous devez faire. Et bien que ce soit un petit exemple stupide, dans le monde réel, il devient de plus en plus important et de plus en plus difficile à tester manuellement. Cela signifie, bien sûr, que les gens ne testent tout simplement pas les composants individuels; ils testent tout le programme. Mais ensuite, des bogues surgissent et ils sont beaucoup plus difficiles à trouver. Ou des bugs se produisent, et ils sont corrigés, mais quelqu'un réintroduit le même bogue, car personne n'a ajouté un cas de test pour s'assurer que cela ne s'est pas produit. Ou quelqu'un regarde un gros morceau de code et dit: "Je n'ai aucune idée de ce que cela est censé faire, car il n'est pas documenté et n'a pas de tests ... si je corrige ce bogue, je n'ai aucune idée si je vais casser quelque chose d'autre en fonction de lui; peut-être que je vais juste réécrire ça à partir de zéro. "

Les tests unitaires réduisent tout le travail supplémentaire dans ces cas. La meilleure façon de les rendre amusants est de s'assurer que les gens comprennent tout le travail qu'ils remplacent et la flexibilité supplémentaire qui vient de savoir ce que chaque morceau de code est censé faire. Dans une certaine mesure, les gens doivent avoir un peu plus d'expérience avec l'écriture et le maintien d'une grande base de code pour comprendre l'importance des tests unitaires; si tout leur code est quelque chose qu'ils écrivent une fois et jettent, ils ne l'obtiendront jamais tout à fait.

Et les tests unitaires ne devraient pas être écrits après coup, comme une corvée supplémentaire une fois que vous avez du code que vous "connaissez" déjà fonctionne. Les tests unitaires doivent être écrits en premier, ou à tout le moins (puisque vous oubliez parfois de les écrire en premier) juste après avoir écrit le code en question. C'est ce qu'on appelle le développement piloté par les tests, et cela peut aider à améliorer vos API; si vous écrivez d'abord les tests qui exercent les API, vous apprendrez où les API sont difficiles à utiliser avant même d'écrire le code, et vous pourrez repenser beaucoup plus facilement que si vous ajoutez uniquement les tests par la suite.


@Biran, je suis d'accord. Mais tout cela en fait la «bonne» chose. Mais comment le rendre agréable? Même légèrement?
Preets

@Preets C'est agréable car vous évitez de faire des tests manuels répétitifs. C'est plus agréable lorsque vous le faites en premier , plutôt qu'après coup, car cela fait partie du processus de conception, pas une corvée après coup pour du code qui "fonctionne" déjà.
Brian Campbell

Alors, passez du temps à le faire mal, de sorte que le faire BIEN soit amusant en comparaison? ... Cela pourrait fonctionner, en fait ....
BlairHippo

@Biran, je suis d'accord, il faut le faire "en premier" - non seulement pour éliminer l'ennui, mais je suppose que c'est la bonne façon de le faire pour récolter les véritables avantages des tests unitaires.
Preets

@Biran, merci! J'ai récemment utilisé TDD sur un de mes projets de loisirs et cela a changé ma façon de penser les tests unitaires.
Preets

5

Je ne sais pas. Ce qui rend définitivement le test unitaire plus agréable pour moi, c'est la pensée de tout le débogage frustrant, long, ennuyeux et peu gratifiant que je n'aurai pas à passer à chaque fois que je changerai le logiciel :)


2
C'est intéressant. Parce que personnellement, quand quelqu'un trouve un bogue dans mon code, je m'enfonce dans la honte, mais en même temps, le processus de débogage pour moi est en fait assez amusant et bien plus amusant que les tests unitaires. C'est comme résoudre un puzzle où vous devez attraper ce bug sournois.
Preets

@Preets: Je suis d'accord, parfois cela peut être amusant, mais pour moi, la conception est beaucoup plus intéressante que la mise en œuvre. Je n'aime donc pas consacrer beaucoup de temps à la mise en œuvre. Je préfère que ce soit simple et prévisible, surtout parce qu'il permet de faire des horaires plus fiables. Autant j'aime le processus de création d'un logiciel, je pense que le résultat est déterminant.
back2dos

Oh je suis complètement d'accord! Un système avec des bugs aléatoires peut provoquer des nuits blanches .. mon choix était simplement une préférence dans un monde irréel où rien d'autre que le plaisir ne comptait!
Preets

3

La supériorité béat que vous ressentez lorsque vous archivez du code solide, robuste et stable. Et si vous écrivez des tests unitaires avec un outil de couverture de code, vous pouvez vous vanter dans vos commentaires que votre couverture de code est de 90% ou plus.


3

De toute évidence, il y a la satisfaction du développement test-first et le sentiment que vous ressentez lorsque votre conception et vos tests sont réunis. Cependant, l'écriture de tests pour du code préexistant / hérité peut être ahurissante et frustrante. Lorsque notre projet était dans un modèle de maintenance, j'ai écrit des tests pour le code non testé en utilisant le rapport de couverture comme un jeu. Vous pouvez créer un peu de compétition avec vous-même et / ou d'autres pour augmenter les numéros de couverture. Certes, vous pouvez aller trop loin et créer de mauvais tests, mais cela peut être une bonne motivation.


étant donné que le code hérité n'est généralement pas facilement testable, j'ai du mal à écrire de bons tests unitaires - donc non seulement le processus est douloureux, mais le résultat (tests unitaires) n'est pas particulièrement utile non plus: - / Je trouve cela le plus frustrant .. Le jeu de couverture est bon cependant :)
Pré

1

Essayez d'entrer dans le Flow . Fixez-vous des objectifs difficiles mais réalisables. Quel pourrait être un objectif dans les tests unitaires? Par exemple, essayez d'écrire plus rapidement tout en conservant la qualité. Les tests unitaires ne nécessitent pas trop de réflexion, il est donc peu probable de se tromper. Concentrez-vous sur votre objectif et vérifiez souvent pour voir à mesure que vous vous en approchez.


Alors, pourquoi dites-vous que le test unitaire ne nécessite pas trop de réflexion? Si vous travaillez avec TDD, cela implique beaucoup de réflexion. N'est-ce pas vrai?
Preets

Vous avez raison, je n'ai pas pris en compte TDD.
Tamás Szelei

0

Parfois, pour me motiver, j'écrirai ma "couverture de code" actuelle en début de journée. Ensuite, chaque fois que j'écris un test et que je le réussis, je lance la suite et je mets à jour le numéro de couverture. C'est amusant et ça me rappelle pourquoi je fais ça. (Il y a aussi d'autres raisons, mais j'aime les chiffres. Peut-être que c'est juste moi!)


0

En n'essayant pas de me leurrer, je peux faire croire à mon esprit que les tests unitaires peuvent être agréables pendant toute période de temps durable.

Accepter la réalité que les tests unitaires ne sont pas là pour être appréciés m'aide beaucoup, me faisant réaliser que je cherche quelque chose dans un endroit où il n'a jamais été censé être.

Dans ces brèves excursions mentales quand j'arrive à percevoir les tests unitaires comme ce qu'ils sont réellement, c'est-à-dire une tâche cruellement, insupportablement et ennuyeusement ennuyeuse, je me demande si je peux me permettre de les abandonner, c'est-à-dire de ne pas avoir garanties élevées quant à l'exactitude fonctionnelle.

Invariablement, la réponse est un «non» retentissant.

En acceptant mon destin, je continue de pousser ces objets carrés avec des lettres, des chiffres et des symboles devant eux, que nous appelons clavier, sachant par expérience que, à chaque clic sur le clavier, la fin du test unitaire est plus proche qu'elle n'a jamais été.


Tous les tests ne sont pas bons ou utiles. C'est quelque chose que les TDD'ers et autres évangélistes de test ne mentionnent généralement pas. Je parie que dans de rares moments, vous appréciez les tests unitaires lorsque vous savez qu'il teste une logique complexe, le test est élégant et non couplé à la mise en œuvre, et je déteste plutôt lorsque vous êtes forcé de tester des conneries triviales uniquement pour atteindre une cible de couverture de code lunatique requise par directives du projet.
KolA

@KolA Vous avez raison, il existe des tests unitaires difficiles qui nécessitent de la créativité, mais l'écriture de tests unitaires sans fin peut aspirer la joie même des tests intrinsèquement intéressants.
bugfoot
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.