Je peux écrire un message d'assertion de deux manières. Constatant le succès:
assertEquals( "objects should be identical", expected, actual );
Ou indiquant la condition d'être brisé:
assertEquals( "objects aren't identical", expected, actual );
Existe-t-il une norme pour cela dans JUnit? Si non, quels sont les arguments de chaque côté?
P.S. J'ai vu des articles sur le Web illustrant ces deux choses sans explication. Il ne suffit donc pas de dire "rechercher sur Google"!
[METTRE À JOUR]
Tout le monde s'accroche au fait que j'ai utilisé assertEquals
et donc le message est probablement inutile. Mais bien sûr, c'est simplement parce que je voulais illustrer la question simplement.
Alors, imaginez plutôt:
assertTrue( ... big long multi-line expression ... );
Où un message est utile.
Je m'ennuie rarement avec un message, du moins pour assertEquals
. Tout testeur avisé expliquera que vous utilisiez assertEquals
et les deux choses qui étaient censées être égales. Aucun de vos messages ne donne plus d'informations que cela.
Je trouve généralement que les échecs de tests unitaires sont des choses passagères - je vais rapidement découvrir ce qui ne va pas et le réparer. "Trouver ce qui ne va pas" implique généralement suffisamment de détails pour qu'un seul message ne fasse pas beaucoup de différence. Considérez "gain de temps en ayant un message" vs "temps passé à penser aux messages" :)
EDIT: OK, un cas où je pourrais utiliser un message: quand il y a une description compacte dans le texte qui n’est pas évidente à partir de la représentation sous forme de chaîne de l’objet.
Par exemple: "Date prévue pour le 1er décembre" lors de la comparaison de dates stockées en millisecondes.
Je ne voudrais pas m'inquiéter de la façon dont vous l'exprimez exactement: assurez-vous que le message indique clairement ce que vous voulez dire. Soit "devrait être" ou "n'était pas" c'est bien - le "1er décembre" ne serait pas évident.
Selon l'API Junit, le message est le "message d'identification pour AssertionError". Ce n'est donc pas un message décrivant la condition à remplir, mais un message décrivant ce qui ne va pas si la condition n'est pas remplie. Ainsi, dans votre exemple, "les objets ne sont pas identiques" semble être plus conforme.
Contrairement à beaucoup d'autres, j'estime que l'utilisation d'un message est extrêmement utile pour plusieurs raisons:
La personne qui consulte le journal d'un test ayant échoué n'est peut-être pas celle qui a écrit le test. La lecture du code et la compréhension du cas que l'assertion est censée traiter peuvent prendre un certain temps. Un message utile vous fera gagner du temps.
Même s'il s'agit du développeur du test qui examine les journaux, cela peut prendre plusieurs jours ou mois depuis l'écriture du test et, encore une fois, un message peut faire gagner du temps.
Mon conseil serait d'écrire le message avec une déclaration du comportement attendu. Par exemple:
assertEquals("The method should be invoked 3 times", 3, invocationCount);
Je ne pense pas que cela compte du tout. Vous savez déjà qu'un échec s'est produit. Par conséquent, peu importe si le message indique ce qui aurait dû se passer ou ce qui ne devrait pas se produire.
Le but du message est de vous aider quand il le peut et non d’obtenir une certaine complétude.
Évidemment, dans le cas de assertEquals, cela est moins important, mais le message est important dans le cas des assertions générales. Le message devrait vous aider à obtenir suffisamment de contexte pour comprendre immédiatement ce qui a exactement échoué.
Cependant, la quantité de contexte nécessaire (et donc les détails dans le message) doivent dépendre de la manière dont vous obtenez le rapport. Par exemple, si vous recevez le message dans Eclipse, vous pouvez facilement interagir et voir ce qui s'est passé. Le message est donc moins important. Toutefois, si vous recevez vos rapports par courrier électronique (par exemple, à partir d’un serveur de génération continue), vous souhaitez que le message contienne suffisamment d’informations pour que vous ayez une idée de ce qui se passe avant même de vous rendre au code source correspondant.
J'aimerais répondre à la question sans réfléchir, si un message en général est utile.
Si un test échoue, quelque chose ne va pas. Je sais ça. Je veux savoir pourquoi il est cassé. C'est très facile à découvrir car il me suffit d'ouvrir le dossier de test et le SUT . Comme Jon l'a dit, il est très facile de le réparer (j'espère ;-)).
Mais qu'en est-il du message? Le message est pour moi un conseil, ce qui pourrait être fait pour le transformer en un test vert. J'apprécierais donc si le texte du message donne un conseil, comment résoudre ce problème ou où le rechercher.
Un autre aspect intéressant serait l'utilisation d'expressions positives. Il vaut la peine d’envisager d’utiliser des messages texte positifs. Dans votre exemple, j'utiliserais Objects should be identical
. Mais c'est une petite raison.
Selon les spécifications, le message consiste à décrire l'erreur lorsqu'elle se produit . Elle est également utile lorsque vous créez votre application dans un environnement d'infrastructure de configuration, telle que Jenkins, et que vous utilisez des plug-ins pour analyser les résultats d'erreur.
http://junit.sourceforge.net/javadoc/org/junit/Assert.html#assertTrue(Java.lang.String,%20boolean)
message - le message d'identification pour AssertionError (null okay)
Je vois cette question de deux points de vue,
La première et la perspective la plus commune, qui fait déjà l’objet de discussions par la plupart d’entre nous ici: Du point de vue de quelqu'un qui voit les journaux et tente de corriger l'erreur:} Je crois que les deux fournit des informations égales.
La deuxième perspective est celle de quelqu'un qui lit/maintient/examine le code: Comme nous parlons depuis des siècles de la lisibilité et de la simplicité du code. Donc, c'est également tout aussi important.
On nous a fait croire que mon code devrait être simple et explicite, de sorte qu'aucun commentaire explicite ne soit nécessaire et je suis tout à fait d'accord avec cela.
De cette perspective:
Ces messages facilitent beaucoup la lecture et la lecture du code car ils servent à la fois à la documentation et au rapport d'erreur:
assertEquals( "objects should be identical", expected, actual );
assertTrue( "flag should have been set", flag );
assertNotNull( "object must not be null", object );
Ces messages ne sont pas aussi faciles à lire car ils parlent de la situation inattendue:
assertEquals( "objects aren't identical", expected, actual );
assertTrue( "flag is not set", flag );
assertNotNull( "object is null", object );
Votez-moi aussi (comme Jon), mais la seule fois où je n'ai jamais utilisé un message comme celui-ci (sur assert equals), c'est lors de la construction d'un test unique avec une matrice de valeurs et qu'un des éléments du test échoue: j'utilise le message pour indiquer quel scénario de test a échoué. Sinon, le texte est totalement redondant.
Des javadocs de JUnit:
Affirme que deux objets sont égaux. Si ils ne sont pas une AssertionFailedError est jeté avec le message donné.
Selon l'API, le message peut être celui que vous souhaitiez. Je dirais que les deux options que vous avez sont à la fois identiques et superflues. Le succès ou l'échec de l'assertion fournit déjà toutes les informations que vous fournissez dans le message.
Il s’ensuit pour moi que vous ne devez rien avoir (il y a une assertion qui ne prend pas une chaîne à dessein) OR inclut un message avec une signification au-delà de ce qui existe déjà.
Donc, je suppose que ceci est une réitération de la réponse de Jon, mais trop verbeuse pour être un commentaire.
J'aime particulièrement le fait que le framework de tests Spock encourage les tests qui se lisent comme une histoire et sont venus structurer des tests de manière similaire. Je ne suis pas particulièrement préoccupé par le message d'erreur individuel qui a beaucoup de sens, je cherche à comprendre rapidement tout le test une fois que je l'ai ouvert:
assertEquals("Cloned and persisted items", mockedTiCount, clonedTis.size());
assertTrue("Belong to new transaction", clonedTis.stream().allMatch(ti -> ti.getTransaction().getId().equals(cloned.getId())));
assertNotEquals("Which has a different ID", t.getId(), cloned.getId());
assertEquals("While the originals are left intact", mockedTiCount, transactionItemRepository.findByTransactionId(t.getId()).size());
Opter pour de nombreux petits tests au lieu de quelques-uns de gros est également utile, tout comme un code de configuration de test parfaitement structuré et, espérons-le, réutilisable.
Je conviens qu’il est utile de fournir un message et j’en transmets toujours un.
Pour moi, la chose utile à inclure est une déclaration claire de ce qui a mal tourné - impliquant généralement les mots «devrait» ou «ne devrait pas».
Par exemple, "les objets sont égaux" est ambigu - cela signifie-t-il que les objets sont égaux et c'est pourquoi le test a échoué? Ou que les objets doivent être égaux mais qu'ils ne le sont pas? Mais si vous dites "Les objets doivent être égaux" ou "Les objets ne doivent pas être égaux", vous comprendrez pourquoi l'assertion a échoué.
Je ne mets pas de message pour le cas que vous citez, à moins d'exécuter un test dans lequel j'ai un tableau de valeurs de test similaires que je suis en train d'exécuter en boucle et je souhaite identifier exactement celle qui a échoué. Ensuite, j'ajoute un message pour me dire lequel.