anti-modèle : il doit y avoir au moins deux éléments clés présents pour distinguer formellement un anti-modèle réel d'une simple mauvaise habitude, mauvaise pratique ou mauvaise idée:
- Certains schémas d'action, de processus ou de structure répétés qui semblent initialement bénéfiques, mais qui produisent en fin de compte plus de mauvaises conséquences que des résultats bénéfiques, et
- Une solution refactorisée clairement documentée, éprouvée dans la pratique et reproductible.
Votez pour l'anti-schéma TDD que vous avez vu "à l'état sauvage" une fois de trop.
Le billet de blog de James Carr et la discussion connexe sur le testdrivendevelopment yahoogroup
Si vous en avez trouvé un «sans nom», postez-les aussi. Un message par anti-modèle pour que les votes comptent pour quelque chose.
Mon intérêt direct est de trouver le sous-ensemble top-n afin que je puisse en discuter dans une réunion déjeuner dans un avenir proche.
Réponses:
Citoyens de deuxième classe - le code de test n'est pas aussi bien refactorisé que le code de production, contenant beaucoup de code dupliqué, ce qui rend difficile la maintenance des tests.
la source
The Free Ride / Piggyback - James Carr, Tim Ottinger
Plutôt que d'écrire une nouvelle méthode de cas de test pour tester une autre / caractéristique / fonctionnalité distincte , une nouvelle assertion (et ses actions correspondantes, c'est-à-dire les étapes de l'AAA), se déplace dans un cas de test existant .
la source
true
après chaque appel de mutateur possible. Vous voudrez donc vérifier que chaque invariant esttrue
après chaque combinaison de mutateur et de données d'entrée que vous testez. Mais vous souhaiterez réduire la duplication et vous assurer de vérifier tous les invariants, y compris ceux qui ne provoquent pas actuellement d'échecs de test. Vous les mettez donc tous dans unecheckInvariants()
fonction de vérification et vous les utilisez dans chaque test. Le code change et un autre invariant est ajouté. Vous mettez cela aussi dans la fonction, bien sûr. Mais c'est un freerider.Chemin heureux
Le test reste sur des chemins heureux (c'est-à-dire les résultats attendus) sans tester les limites et les exceptions.
Antipatterns JUnit
la source
Le héros local
Un scénario de test qui dépend de quelque chose de spécifique à l'environnement de développement sur lequel il a été écrit pour s'exécuter. Le résultat est que le test réussit sur les boîtes de développement, mais échoue lorsque quelqu'un tente de l'exécuter ailleurs.
La dépendance cachée
Étroitement lié au héros local, un test unitaire qui nécessite que certaines données existantes aient été remplies quelque part avant l'exécution du test. Si ces données n'ont pas été renseignées, le test échouera et ne laissera aucune indication au développeur sur ce qu'il voulait, ou pourquoi ... les obligeant à fouiller dans des hectares de code pour savoir d'où les données qu'il utilisait étaient censées provenir.
Malheureusement, cela a été trop souvent constaté avec les anciens fichiers .dll qui dépendent de fichiers .ini nébuleux et variés qui sont constamment désynchronisés sur un système de production donné, et encore moins qui existent sur votre machine sans consultation approfondie des trois développeurs responsables de ces fichiers. Soupir.
la source
Gang de chaîne
Quelques tests qui doivent être exécutés dans un certain ordre, c'est-à-dire qu'un test modifie l'état global du système (variables globales, données dans la base de données) et le ou les tests suivants en dépendent.
Vous voyez souvent cela dans les tests de base de données. Au lieu d'effectuer une restauration
teardown()
, les tests valident leurs modifications dans la base de données. Une autre cause courante est que les modifications de l'état global ne sont pas encapsulées dans des blocs try / finally qui nettoient en cas d'échec du test.la source
La moquerie
Parfois, la moquerie peut être bonne et pratique. Mais parfois, les développeurs peuvent se perdre et dans leur effort pour se moquer de ce qui n'est pas testé. Dans ce cas, un test unitaire contient tellement de simulations, de moignons et / ou de contrefaçons que le système testé n'est même pas testé du tout, mais les données renvoyées par les simulations sont ce qui est testé.
Source: poste de James Carr.
la source
Le Silent Catcher - Kelly?
Un test qui réussit si une exception est levée .. même si l'exception qui se produit réellement est une exception différente de celle prévue par le développeur.
Voir aussi: Secret Catcher
la source
L'inspecteur
Un test unitaire qui viole l'encapsulation dans un effort pour atteindre une couverture de code à 100%, mais en sait tellement sur ce qui se passe dans l'objet que toute tentative de refactorisation cassera le test existant et exigera que tout changement soit reflété dans l'unité tester.
'comment puis-je tester mes variables membres sans les rendre publiques ... juste pour des tests unitaires?'
la source
Configuration excessive - James Carr
Un test qui nécessite une configuration énorme pour même commencer les tests. Parfois, plusieurs centaines de lignes de code sont utilisées pour préparer l'environnement à un test, avec plusieurs objets impliqués, ce qui peut rendre difficile de vraiment déterminer ce qui est testé en raison du «bruit» de toute la configuration en cours. (Src: poste de James Carr )
la source
Sonde anale
Un test qui doit utiliser des moyens insensés, illégaux ou autrement malsains pour effectuer sa tâche comme: lire des champs privés en utilisant setAccessible de Java (vrai) ou étendre une classe pour accéder à des champs / méthodes protégés ou avoir à mettre le test dans un certain package pour accéder empaqueter les champs / méthodes globaux.
Si vous voyez ce modèle, les classes testées utilisent trop de données masquées.
La différence entre cela et l'inspecteur est que la classe sous test essaie de cacher même les choses dont vous avez besoin pour tester. Votre objectif n'est donc pas d'atteindre une couverture de test à 100%, mais de pouvoir tout tester. Pensez à une classe qui n'a que des champs privés, une
run()
méthode sans arguments et sans getters du tout. Il n'y a aucun moyen de tester cela sans enfreindre les règles.Commentaire de Michael Borgwardt: Ce n'est pas vraiment un contre-modèle de test, c'est du pragmatisme pour faire face aux déficiences du code testé. Bien sûr, il est préférable de corriger ces lacunes, mais cela peut ne pas être possible dans le cas des bibliothèques tierces.
Aaron Digulla: Je suis en quelque sorte d'accord. Peut-être que cette entrée est vraiment mieux adaptée à un wiki "JUnit HOWTO" et non à un antipattern. Commentaires?
la source
Le test sans nom - Nick Pellow
Le test qui est ajouté pour reproduire un bogue spécifique dans le traqueur de bogues et dont l'auteur pense qu'il ne garantit pas son propre nom. Au lieu d'améliorer un test manquant existant, un nouveau test est créé appelé testForBUG123.
Deux ans plus tard, lorsque ce test échoue, vous devrez peut-être d'abord essayer de trouver BUG-123 dans votre suivi des bogues pour comprendre l'intention du test.
la source
The Slow Poke
Un test unitaire incroyablement lent. Lorsque les développeurs démarrent, ils ont le temps d'aller aux toilettes, de fumer, ou pire, de lancer le test avant de rentrer chez eux à la fin de la journée. (Src: poste de James Carr )
alias les tests qui ne seront pas exécutés aussi souvent qu'ils le devraient
la source
Le papillon
Vous devez tester quelque chose qui contient des données qui changent tout le temps, comme une structure qui contient la date actuelle, et il n'y a aucun moyen de clouer le résultat à une valeur fixe. La partie laide est que vous ne vous souciez pas du tout de cette valeur. Cela rend simplement votre test plus compliqué sans ajouter de valeur.
La chauve-souris de son aile peut provoquer un ouragan à l'autre bout du monde. - Edward Lorenz, L'effet papillon
la source
System.DateTime.Now
, en plus d'avoir des tests unitaires plus simples ou plus déterministes?toString()
un objet qui n'écrase pas la méthode. Cela vous donnera l'ID de l'objet qui dépend de l'adresse mémoire. OutoString()
contient la clé primaire de l'objet et qui change à chaque fois que vous exécutez le test. Il existe trois façons de résoudre ce problème: 1. Modifiez le code que vous testez, 2. utilisez regexp pour supprimer les parties variables des résultats du test ou 3. utilisez des outils puissants pour écraser les services système pour leur faire renvoyer des résultats prévisibles.Le test du scintillement (Source: Romilly Cocking)
Un test qui échoue juste occasionnellement, pas à des moments précis, et est généralement dû aux conditions de course dans le test. Se produit généralement lors du test d'un élément asynchrone, tel que JMS.
Peut-être un super ensemble de l' anti-modèle " Wait and See " et " The Sleeper ".
La construction a échoué, eh bien, exécutez à nouveau la construction. - Développeur anonyme
la source
Attend et regarde
Un test qui exécute un code de configuration et doit ensuite «attendre» un certain temps avant de pouvoir «voir» si le code testé fonctionne comme prévu. Un testMethod qui utilise Thread.sleep () ou équivalent est très certainement un test "Wait and See".
En règle générale, vous pouvez voir cela si le test teste du code qui génère un événement externe au système tel qu'un e-mail, une requête http ou écrit un fichier sur le disque.
Un tel test peut également être un héros local car il échouera lorsqu'il sera exécuté sur une boîte plus lente ou un serveur CI surchargé.
L'anti-modèle Wait and See ne doit pas être confondu avec The Sleeper .
la source
Appareil partagé de manière inappropriée - Tim Ottinger
Plusieurs cas de test dans l'appareil de test n'utilisent même pas ou n'ont pas besoin d'être configurés / démontés. En partie en raison de l'inertie du développeur pour créer un nouveau montage de test ... plus facile d'ajouter simplement un cas de test supplémentaire à la pile
la source
Le géant
Un test unitaire qui, bien qu'il teste valablement l'objet testé, peut s'étendre sur des milliers de lignes et contenir de nombreux cas de test. Cela peut être un indicateur que le système testé est un objet divin (article de James Carr).
Un signe certain pour celui-ci est un test qui s'étend sur plus de quelques lignes de code. Souvent, le test est si compliqué qu'il commence à contenir des bogues de son propre comportement ou floconneux.
la source
J'y croirai quand je verrai des interfaces graphiques clignotantes
Une fixation / obsession malsaine pour tester l'application via son interface graphique `` comme un vrai utilisateur ''
"Vous devez comprendre que voir, c'est croire, mais aussi savoir que croire, c'est voir." - Denis Waitley
la source
Le dormeur, alias Mont Vésuve - Nick Pellow
Un test qui est destiné à échouer à une heure et une date spécifiques à l'avenir. Cela est souvent dû à une vérification des limites incorrecte lors du test du code qui utilise un objet Date ou Calendrier. Parfois, le test peut échouer s'il est exécuté à une heure très précise de la journée, telle que minuit.
«The Sleeper» ne doit pas être confondu avec l' anti-modèle « Wait And See ».
Ce code aura été remplacé bien avant l'an 2000 - De nombreux développeurs en 1960
la source
L'arbre mort
Un test où un stub a été créé, mais le test n'a pas été réellement écrit.
J'ai vu cela dans notre code de production:
Je ne sais même pas quoi en penser.
la source
a mordu par cela aujourd'hui:
Sol humide :
le test crée des données persistantes quelque part, mais le test ne se nettoie pas une fois terminé. Cela entraîne l'échec des tests (le même test ou éventuellement d'autres tests) lors des exécutions de test suivantes .
Dans notre cas, le test a laissé un fichier dans le répertoire "temp", avec les autorisations de l'utilisateur qui a exécuté le test la première fois. Lorsqu'un utilisateur différent a essayé de tester sur la même machine: boom. Dans les commentaires sur le site de James Carr, Joakim Ohlrogge a appelé cela le "Sloppy Worker", et cela faisait partie de l'inspiration pour "Generous Leftovers". J'aime mieux mon nom (moins insultant, plus familier).
la source
Le coucou - Frank Carver
Un test unitaire qui se trouve dans un scénario de test avec plusieurs autres, et bénéficie du même processus de configuration (potentiellement long) que les autres tests du scénario de test, mais élimine ensuite tout ou partie des artefacts de la configuration et crée le sien.
Symptôme avancé de: Appareil mal partagé
la source
The Secret Catcher - Frank Carver
Un test qui à première vue semble ne faire aucun test, en raison de l'absence d'assertions. Mais "Le diable est dans les détails" .. le test repose vraiment sur une exception à lever et attend du framework de test qu'il capture l'exception et la signale à l'utilisateur comme un échec.
la source
Assert.DoesNotThrow(SomeDelegateType act)
assertion de style qui peut être utilisée spécifiquement dans des cas comme celui-ci. Je trouve cela moins grossier que d'avoir un cas de test qui réussit lorsqu'un constructeur retourne non nul, mais échoue lorsque le constructeur lance. Un constructeur ne retournera jamais null. (Remarque: s'applique uniquement aux langues où un constructeur est garanti de retourner non nul)Le vandalisme environnemental
Un test «unitaire» qui pour diverses «exigences» commence à se répandre dans son environnement, en utilisant et en définissant des variables / ports d'environnement. L'exécution simultanée de deux de ces tests entraînera des exceptions de «port indisponible», etc.
Ces tests seront intermittents et laisseront les développeurs dire des choses comme «il suffit de le relancer».
Une solution que j'ai vue consiste à sélectionner au hasard un numéro de port à utiliser. Cela réduit la possibilité d'un conflit, mais ne résout clairement pas le problème. Donc, si vous le pouvez, moquez toujours le code afin qu'il n'alloue pas réellement la ressource non partageable.
la source
Le test de Turing
Un testcase généré automatiquement par un outil coûteux qui contient de nombreuses assertions glanées dans la classe testée en utilisant une analyse de flux de données trop intelligente par moitié. Endort les développeurs dans un faux sentiment de confiance que leur code est bien testé, les déchargeant de la responsabilité de concevoir et de maintenir des tests de haute qualité. Si la machine peut écrire les tests pour vous, pourquoi ne peut-elle pas retirer son doigt et écrire l'application elle-même!
Bonjour stupide. - L'ordinateur le plus intelligent du monde à un nouvel apprenti (d'une vieille bande dessinée d'Amiga).
la source
Le test du pôle de quarante pieds
Peur de se rapprocher trop de la classe qu'ils tentent de tester, ces tests agissent à distance, séparés par d'innombrables couches d'abstraction et des milliers de lignes de code de la logique qu'ils vérifient. En tant que tels, ils sont extrêmement fragiles et sensibles à toutes sortes d'effets secondaires qui se produisent lors du voyage épique vers et depuis la classe d'intérêt.
la source
Doppelgänger
Pour tester quelque chose, vous devez copier des parties du code sous test dans une nouvelle classe avec le même nom et le même package et vous devez utiliser la magie du chemin de classe ou un chargeur de classe personnalisé pour vous assurer qu'il est visible en premier (afin que votre copie soit choisie vers le haut).
Ce modèle indique une quantité malsaine de dépendances cachées que vous ne pouvez pas contrôler à partir d'un test.
J'ai regardé son visage ... mon visage! C'était comme un miroir mais ça a fait geler mon sang.
la source
La mère poule - Frank Carver
Une configuration commune qui fait bien plus que les cas de test réels ont besoin. Par exemple, la création de toutes sortes de structures de données complexes peuplées de valeurs apparemment importantes et uniques lorsque les tests n'affirment que la présence ou l'absence de quelque chose.
Symptôme avancé de: Appareil mal partagé
Je ne sais pas ce que ça fait ... Je l'ajoute quand même, juste au cas où. - Développeur anonyme
la source
Le test tout
Je ne peux pas croire que cela n'ait pas été mentionné jusqu'à présent, mais les tests ne devraient pas briser le principe de responsabilité unique .
Je l'ai rencontré tellement de fois, les tests qui enfreignent cette règle sont par définition un cauchemar à maintenir.
la source
Frappeur de ligne
À première vue, les tests couvrent tout et les outils de couverture de code le confirment à 100%, mais en réalité, les tests ne frappent que le code sans aucune analyse de sortie.
couverture-vs-code-accessible
la source