308 votes

De nouveaux tests unitaires, la façon d'écrire de grandes épreuves?

Je suis assez nouveau dans l'unité de test, et j'ai décidé d'ajouter de couverture de test pour mon application de cette semaine.

C'est une tâche énorme, principalement en raison du nombre de classes à tester, mais aussi parce que l'écriture de tests est tout nouveau pour moi.

Je l'ai déjà écrit des tests pour un tas de classes, mais maintenant je me demande si je suis en train de faire.

Quand je suis en train d'écrire des tests pour une méthode, j'ai l'impression de réécrire une deuxième fois ce que j'ai déjà écrit dans la méthode elle-même.
Mes tests semble donc étroitement liée à la méthode (le test de tous les codepath, attend quelques intérieure méthodes pour être appelé un certain nombre de fois, avec certains arguments), il me semble que si jamais je refactoriser le code de la méthode, les tests échouent, même si au final le comportement de la méthode n'a pas changé.

C'est juste un sentiment, et comme dit plus tôt, je n'ai pas d'expérience du test. Si certains plus expérimentés testeurs là-bas pourrait me donner des conseils sur la façon d'écrire de grands tests pour une application existante, ce serait grandement apprécié.

Edit : j'aimerais remercier Débordement de Pile, j'ai eu beaucoup d'entrées en moins de 15 minutes qui a répondu plus des heures de lecture en ligne, je viens de le faire.

203voto

Mark Byers Points 318575

Mes tests semble donc étroitement liée à la méthode (le test de tous les codepath, attend quelques intérieure méthodes pour être appelé un certain nombre de fois, avec certains arguments), il me semble que si jamais je refactoriser le code de la méthode, les tests échouent, même si au final le comportement de la méthode n'a pas changé.

Je pense que vous faites fausse route.

Un test unitaire doit:

  • tester une méthode
  • fournir des arguments à la méthode
  • vérifier que le résultat est comme prévu

Il ne faut pas regarder à l'intérieur de la méthode pour voir ce qu'il fait, de sorte qu'un changement de l'intérieur ne devrait pas provoquer le test à l'échec. Vous ne devriez pas tester directement que les méthodes privées sont appelés. Si vous êtes intéressé à en savoir si votre code est testé puis d'utiliser un outil de couverture du code. Mais ne soyez pas obsédé par cette: 100% de couverture n'est pas une exigence.

Si vos appels de méthode méthodes publiques dans d'autres classes, et ces appels sont garantis par votre interface, vous pouvez tester que ces appels sont faits à l'aide d'un moqueur cadre.

Vous ne devez pas utiliser la méthode elle-même (ou à l'interne, le code qu'il utilise) pour générer les résultats attendus de manière dynamique. Le résultat attendu doit être codée en dur dans votre cas de test de sorte qu'il ne change pas lors de la mise en œuvre des changements. Voici un exemple simplifié de ce qu'est un test unitaire doit faire:

testAdd()
{
    int x = 5;
    int y = -2;
    int expectedResult = 3;

    Calculator calculator = new Calculator();
    int actualResult = calculator.Add(x, y);
    Assert.AreEqual(expectedResult, actualResult);
}

Notez que la façon dont le résultat est calculé n'est pas cochée - seulement que le résultat est correct. Continuer à ajouter plus de et la plus simple des cas de test comme ci-dessus jusqu'à ce que vous avez couvert de nombreux scénarios possibles. Utilisez votre outil de couverture de code pour voir si vous avez manqué tout d'intéressantes pistes.

49voto

Dmitriy Likhten Points 1685

Pour les tests unitaires, je l'ai trouvé à la fois Piloté par les tests (tests, code de seconde) et le premier code, test de la deuxième à être extrêmement utile.

Au lieu d'écrire le code, alors l'écriture de test. Écrire du code ensuite, regardez ce que vous PENSEZ que le code doit être en train de faire. Pensez à toutes les utilisations et ensuite écrire un test pour chacune. Je trouve l'écriture de tests pour être plus rapide mais plus que le codage lui-même. Les essais doivent tester l'intention. Aussi la réflexion sur les intentions de vent jusqu'à trouver le coin des cas dans l'essai de phase d'écriture. Et bien sûr, lors de l'écriture de tests vous pouvez trouver l'un des quelques utilisations cause d'un bug (quelque chose que je trouve souvent, et je suis très content que ce bug n'a pas de corrompre les données et l'impunité).

Pourtant, le test est presque comme de codage à deux reprises. En fait, j'avais les applications où il n'y a plus de code de test (quantité) que le code de l'application. Par exemple, on a une très complexe de l'état de la machine. J'ai dû faire en sorte que, après l'ajout de plus logique pour elle, la chose entière a toujours travaillé sur tous les cas d'utilisation. Et depuis ces cas ont été assez dur à suivre, en regardant le code, j'ai fini par avoir une bonne suite de test pour cette machine que j'étais convaincu qu'il ne serait pas briser, même après avoir fait des changements, et les tests sauvé mon cul plusieurs fois. Et que les utilisateurs ou les testeurs ont été de trouver des bugs avec le flux ou le coin des cas inexpliqués, devinez ce qui, ajouté à des tests et n'est jamais arrivé encore. Cela a vraiment donné confiance dans mon travail, en plus de la totalité de la chose super stable. Et quand il a dû être ré-écrit pour des raisons de performances, devinez quoi, il a fonctionné comme prévu sur toutes les entrées grâce à des tests.

Tous les exemples simples comme function square(number) est super et tout, et sont probablement les mauvais candidats à passer beaucoup de temps à tester. Ceux qui ne important la logique métier, c'est là que le test est important. Test les exigences. Ne vous contentez pas de test de la plomberie. Si les besoins changent alors devinez quoi, les tests doivent le faire aussi.

Les tests ne doivent pas être littéralement tests de la fonction foo fonction invoquée barre 3 fois. Ce qui est mauvais. Vérifier si le résultat et les effets secondaires sont corrects, pas à l'intérieur de la mécanique.

24voto

David Points 65209

Il est intéressant de noter que le rétro-montage de tests unitaires sur le code existant est beaucoup plus difficile que de conduire à la création de ce code avec des tests en premier lieu. C'est l'une des grandes questions à traiter avec des applications existantes... comment test unitaire? Cela a été demandé à plusieurs reprises avant (de sorte que vous peut être fermé comme une dupe question), et les gens finissent généralement par ici:

http://stackoverflow.com/questions/167079/moving-existing-code-to-test-driven-development

Je seconde la accepté de répondre le livre de recommandation, mais au-delà il n'y a plus d'informations liées dans les réponses.

18voto

Jon Reid Points 9726

Ne pas écrire des tests pour obtenir une couverture complète de votre code. Écrire des tests qui garantissent à vos exigences. Vous pouvez découvrir codepaths qui sont inutiles. A l'inverse, si elles sont nécessaires, ils sont là pour répondre à certaines exigences; trouver ce que c'est et test de l'obligation (et non pas le chemin).

Garder vos petits tests: un test selon l'exigence.

Plus tard, lorsque vous avez besoin de faire un changement (ou écrire du nouveau code), essayez d'écrire un test de la première. Juste une. Ensuite, vous avez pris la première étape dans le développement piloté par les tests.

14voto

x3ro Points 12721

Le test unitaire est à propos de la sortie que vous obtenez à partir d'une fonction/méthode/de l'application. Ce n'est pas grave du tout comment le résultat est produit, il importe seulement que c'est correct. Par conséquent, votre approche de comptage des appels à l'intérieur des méthodes et telle est complètement faux ;) Ce que j'ai tendance à faire est de s'asseoir et d'écrire ce qu'une méthode doit renvoyer des données certaines valeurs d'entrée ou d'un environnement donné, puis d'écrire un test qui permet de comparer la valeur retournée avec ce que je suis venu avec.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X