Une barre rouge inattendue. Je scrute le message d'échec du test dans le panneau junit :
Je double-clique sur expected: pour obtenir le comparateur de l'IDE. Zut rien ne se passe ! Du coup je scrolle pour voir tout le message d'erreur, mais je ne distingue aucune différence entre résultats attendu et obtenu. Et là je m'interroge : pourquoi je n'obtiens pas le comparateur quand je double-clique :-( ?
Ca ne vous est jamais arrivé ? Dans mon équipe, ça arrive tout le temps.
Eclipse et intelliJ IDEA réagissent de la même manière. Leur comportement dépend de l'exception qu'il reçoivent :
- avec
AssertionError
le double-clic ne fait rien - avec
ComparisonFailure
le double-clic ouvre la belle popup du comparateur :
Quand ces exceptions sont-elles levées ?
ComparisonFailure
est levée par assertEquals(String, String)AssertionError
est levée par assertEquals(Object, Object) et assertThat
AssertionError
n'est pas spécifique à junit, c'est une java.lang.AssertionError
, elle peut provenir du code lui-même plutôt que du test. L'IDE ne l'interprète pas comme le résultat d'un test.
De loin, les messages semblent identiques [1] car assertEquals(Object, Object)
affiche des toString()
. Voilà pourquoi les variations de comportement du double-clic surprennent. Certains en viennent à ajouter des toString() pour souligner les différences :
assertEquals(attendu.toString(), obtenu.toString());
C'est dangereux car l'égalité n'est pas déterminée par le equals()
de Object
, ce qui viole un contrat Java. En plus, ça ne marche pas pour assertThat
qui lève AssertionError
même pour deux String (assertThat("Philippe", equalTo("Blayo")
). J'aimerais plutôt que :
equals()
détermine la réussite ou l'échec du test (rouge/vert)- une comparaison entre les
toString()
enrichisse l'affichage expected/actual des barres rouges, quelque soit la classe des objets comparés
Suivant le contexte, je connais deux manières d'y parvenir :
- utiliser une lib qui lève déjà une
ComparisonFailure
comme FEST-assert - coder soi-même une assertion qui lève une
ComparisonFailure
(custom assertion). En laissant de coté la gestion desnull
, la substance d'une telle assertion serait :static void assertLisible(Object expected, Object actual) { if (! expected.equals(actual)) throw new ComparisonFailure("", expected.toString(), actual.toString()); }
[1] ComparisonFailure
met entre crochets la différence bl[ay]o
/ bl[ya]o
, là où AssertionError
laisse blayo
/ blyao
. Les messages ne sont donc identiques qu'en apparence. Mais ces crochets ne suffisent pas : une popup ne s'ouvre qu'avec une ComparisonFailure
.