Nous testons notre code pour le rendre plus correct (en fait, moins susceptible d'être incorrect ). Cependant, les tests sont aussi du code - ils peuvent également contenir des erreurs. Et si vos tests sont bogués, ils n'améliorent guère votre code.
Je peux penser à trois types d’erreurs possibles dans les tests:
Erreurs logiques, lorsque le programmeur a mal compris la tâche à accomplir et que les tests font ce qu'il pensait devoir faire, ce qui est faux;
Erreurs dans la structure de test sous-jacente (par exemple, une abstraction moqueuse qui fuit);
Bugs dans les tests: le test est légèrement différent de ce que le programmeur pense.
Les erreurs de type (1) semblent impossibles à prévenir (à moins que le programmeur ... devienne plus intelligent). Cependant, (2) et (3) peuvent être traitables. Comment gérez-vous ces types d'erreurs? Avez-vous des stratégies spéciales pour les éviter? Par exemple, écrivez-vous des tests "vides" spéciaux, qui vérifient uniquement les présupposés de l'auteur du test? De plus, comment abordez-vous le débogage d'un scénario de test cassé?
la source
Réponses:
Les tests sont déjà testés. De par leur conception, les tests sont protégés contre les bogues, car ils ne détectent que les différences entre le code et nos attentes. S'il y a des problèmes, nous avons une erreur. L'erreur pourrait être dans le code ou avec la même probabilité dans les tests.
Certaines techniques vous empêchent d'ajouter le même bogue dans votre code et vos tests:
Vous n'avez pas besoin de tester la plateforme sous-jacente. Les tests non seulement exercent le code que vous avez écrit, mais ils le font aussi depuis la plate-forme. Bien que vous ne vouliez pas nécessairement attraper des bogues dans la plate-forme de test, il est très difficile d'écrire du code et des tests qui cachent toujours un bogue dans la plate-forme. En d'autres termes, il est très difficile d'avoir un bogue systématique dans vos tests / code et dans la plate-forme, et la probabilité est réduite à chaque test que vous créez. Même si vous essayiez de faire cela, vous auriez une tâche très difficile.
Vous pourriez avoir des bugs lors des tests mais en général, ils sont facilement détectés car les tests sont testés avec le code développé. Entre le code et les tests, vous avez un retour d’auto-application. Les deux prédisent comment un appel spécifique d'une interface devrait se comporter. Si la réponse est différente, vous n'avez pas nécessairement de bogue dans le code. Vous pourriez aussi avoir un bug dans le test.
la source
Essayez de faire les tests individuels aussi courts que possible.
Cela devrait réduire les chances de créer un bogue en premier lieu. Même si vous parvenez à en créer un, il est plus facile à trouver. Les tests unitaires sont supposés être petits et spécifiques, avec une faible tolérance à l'échec et à la déviation.
En fin de compte, c'est probablement juste une question d'expérience. Plus vous écrivez de tests, plus vous y réussissez, moins vous avez de chances de faire des tests de mauvaise qualité.
la source
A
, vous attendez le résultatB
. Si vous n'avez pas d'étatA
, un test devrait échouer. À ce stade, vous pouvez rechercher les raisons de votre échec, de mauvaises conditions initiales ou d'un mauvais test, mais cela devrait échouer dans les deux cas. Même si c'est, comme tu le dis, "légèrement en retrait" (c'est"A" => "B"
-à- dire"a" => "b"
, mais jamais"a" => "B"
ou si ton test est mauvais).Une tactique consiste à écrire le test avant le code qu'il teste et à s'assurer que le test échoue d'abord pour la bonne raison. Si vous utilisez TDD, vous devriez obtenir au moins ce niveau de test.
Un moyen plus exhaustif de tester la qualité d'une suite de tests consiste à utiliser le test de mutation .
la source
Pour les tests n ° 1 et n ° 3: les tests unitaires ne doivent contenir aucune logique. Dans ce cas, vous testez probablement plus d'une chose dans votre test unitaire. Une des meilleures pratiques pour les tests unitaires consiste à n’avoir qu’un seul test par test unitaire.
Regardez cette vidéo de Roy Osherove pour en savoir plus sur la manière de bien écrire les tests unitaires.
la source
En termes de n ° 1 - Je pense que c'est une bonne idée de réviser les paires / codes pour ce côté des choses. Il est facile de faire des présupposés ou de tout simplement se tromper, mais si vous devez expliquer en quoi consiste votre test, vous êtes plus susceptible de réagir si vous visez la mauvaise cible.
la source
Il doit y avoir un moment où l’on devrait arrêter d’essayer de faire des tests unitaires. Devrait savoir quand tracer la ligne. Devrions-nous écrire des cas de test pour tester des cas de test? Qu'en est-il des nouveaux cas de test écrits pour tester des cas de test? Comment allons-nous les tester?
Edit: mis à jour avec l'explication suggérée par le commentaire.
la source
Hey.
Vous devez faire des applications:
Lorsque vous exécutez des tests sur votre produit, vous n'êtes pas intéressé par le test lui-même, mais par l' interaction entre votre produit et vos tests. Si le test échoue, cela ne signifie pas que l'application a un bogue. Il indique que l' interaction entre le produit et le test n'a pas abouti . Il vous appartient maintenant de déterminer ce qui a mal tourné. Cela peut être soit:
Pour moi, les tests qui échouent ne sont pas un simple retour d'information, mais ceci est faux . C'est un indicateur d'incohérence, et je dois examiner les deux pour vérifier si le besoin s'est mal passé. En fin de compte, je suis responsable de la vérification de l’application, les tests ne sont qu’un outil pour mettre en évidence les domaines qui méritent d’être vérifiés.
Les tests ne vérifient que certaines parties de l'application. Je teste l'application, je teste les tests.
la source
Les tests ne doivent pas être assez "intelligents" pour héberger des bugs.
Le code que vous écrivez implémente un ensemble de spécifications. (Si X, alors Y, sauf Z, auquel cas Q, etc., etc.). Tout ce que l’essai devrait faire est de déterminer que X est vraiment Y, sauf si Z est dans quel cas. Cela signifie que tout ce qu’un test devrait faire est de définir X et de vérifier Y.
Mais cela ne couvre pas tous les cas, vous dites probablement, et vous auriez raison. Mais si vous faites le test suffisamment "intelligent" pour savoir que X ne doit être sélectionné que par Y, sinon par Z, vous réimpliquez la logique métier dans le test. C'est problématique pour les raisons que nous allons approfondir un peu plus loin. Vous ne devriez pas améliorer la couverture de code en rendant votre premier test "plus intelligent", mais plutôt en ajoutant un second test muet qui définit X et Z et vérifie Q. Ainsi, vous disposerez de deux tests, l'un couvrant le cas général ( parfois aussi connu comme le chemin heureux) et celui qui couvre le cas limite comme un test séparé.
Il y a plusieurs raisons à cela. Premièrement, comment déterminer si un test ayant échoué est dû à un bogue dans la logique métier ou à un bogue dans les tests? Évidemment, la réponse est que si les tests sont aussi simples que possible, il est très peu probable qu’ils hébergent des insectes. Si vous pensez que vos tests doivent être testés, vous testez mal .
D'autres raisons incluent le fait que vous ne faites que reproduire vos efforts (comme je l'ai déjà mentionné, écrire un test suffisamment intelligent pour exploiter toutes les possibilités dans un seul test revient essentiellement à reproduire la logique métier que vous essayez de tester en premier lieu), si les exigences changent. alors les tests devraient être faciles à modifier pour refléter les nouvelles exigences, les tests servent de sorte de documentation (ils constituent un moyen formel de dire quelle est la spécification de l'unité testée), etc.
TL: DR: Si vos tests doivent être testés, vous le faites mal. Ecrire des tests stupides .
la source
Pas une réponse (je n'ai pas le privilège de commenter), mais je me demandais si vous aviez oublié d'autres raisons de développer des cas de test ...
Une fois que vous avez trouvé tous les bugs dans les tests, vous pouvez facilement tester votre application par régression. Les suites de tests automatisées vous aideraient à détecter les problèmes plus tôt, avant l'intégration. Les modifications apportées aux exigences sont relativement plus faciles à tester, car elles peuvent devenir plus récentes, une version modifiée d'anciens cas de test ayant passé avec succès, et les cas plus anciens restant destinés à détecter les échecs.
la source
Réponse courte: le code de production teste les tests .
Comparez cela au modèle de crédit / débit utilisé en économie. Les mécanismes sont très simples - Si le crédit diffère du débit, il y a un problème.
Il en va de même pour les tests unitaires - Si un test échoue, cela signifie que quelque chose ne va pas. Il s’agit peut-être du code de production, mais également du code de test! Cette dernière partie est importante.
Notez que vos bogues de type (1) ne peuvent pas être trouvés par les tests unitaires. Pour éviter ce type de bogues, vous avez besoin d'autres outils.
la source