159 votes

Pourquoi devrais-je utiliser Hamcrest-Matcher et assertThat() au lieu des méthodes traditionnelles assertXXX() ?

Quand je regarde les exemples dans la JavaDoc de la classe Assert

assertThat("Help! Integers don't work", 0, is(1)); // fails:
// failure message:
// Help! Integers don't work
// expected: is <1> 
// got value: <0>
assertThat("Zero is one", 0, is(not(1))) // passes

Je ne vois pas de gros avantage par rapport à, disons.., assertEquals( 0, 1 ) .

C'est bien peut-être pour les messages si les constructions deviennent plus compliquées, mais voyez-vous d'autres avantages ? La lisibilité ?

175voto

Joachim Sauer Points 133411

Il n'y a pas de gros avantage pour les cas où une assertFoo existe qui correspond exactement à votre intention. Dans ces cas-là, ils se comportent presque de la même manière.

Mais lorsque l'on en vient à des contrôles un peu plus complexes, l'avantage devient plus visible :

assertTrue(foo.contains("someValue") && foo.contains("anotherValue"));

vs.

assertThat(foo, hasItems("someValue", "anotherValue"));

On peut discuter de celle qui est la plus facile à lire, mais une fois que l'assert échoue, vous obtiendrez un bon message d'erreur de la part de assertThat mais seulement une quantité très minime d'informations de la part de assertTrue .

assertThat vous dira quelle était l'affirmation et ce que vous avez obtenu à la place. assertTrue vous dira seulement que vous avez false où vous vous attendiez true .

51voto

Manur Points 2652

Le JUnit notes de mise à jour pour la version 4.4 (où il a été introduit) font état de quatre avantages :

  • Plus lisible et plus facile à taper : cette syntaxe permet de penser en termes de sujet, verbe, objet (assertion "x est 3") plutôt que de assertEquals qui utilise le verbe, l'objet et le sujet (assertion "égale 3 x").
  • Combinaisons : toute déclaration de matcheur s peut être niée ( pas(s) ), combinés ( soit(s).soit(t) ), mis en correspondance avec une collection ( chacun(e) ), ou utilisés dans des combinaisons personnalisées ( aprèsCinqSecondes(s) )
  • Messages d'échec lisibles. (...)
  • Correspondants personnalisés. En mettant en œuvre le Matcher interface vous-même, vous pouvez bénéficier de tous les avantages ci-dessus pour vos propres assertions personnalisées.

Une argumentation plus détaillée de la part de celui qui a créé la nouvelle syntaxe : ici .

40voto

Igor Popov Points 3198

En fait, pour améliorer la lisibilité du code .

Outre hamcrest, vous pouvez également utiliser le assertions de fête . Ils ont quelques avantages par rapport à l 'Ham bien comme :

Quelques exemples

import static org.fest.assertions.api.Assertions.*;

// common assertions
assertThat(yoda).isInstanceOf(Jedi.class);
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);
assertThat(frodo).isIn(fellowshipOfTheRing);
assertThat(sauron).isNotIn(fellowshipOfTheRing);

// String specific assertions
assertThat(frodo.getName()).startsWith("Fro").endsWith("do")
                           .isEqualToIgnoringCase("frodo");

// collection specific assertions
assertThat(fellowshipOfTheRing).hasSize(9)
                               .contains(frodo, sam)
                               .excludes(sauron);

// map specific assertions (One ring and elves ring bearers initialized before)
assertThat(ringBearers).hasSize(4)
                       .includes(entry(Ring.oneRing, frodo), entry(Ring.nenya, galadriel))
                       .excludes(entry(Ring.oneRing, aragorn));

19voto

Andy Davis Points 411

Une justification très élémentaire est qu'il est difficile de se tromper dans la nouvelle syntaxe.

Supposons qu'une valeur particulière, foo, doive être égale à 1 après un test.

assertEqual(1, foo);

--OU

assertThat(foo, is(1));

Avec la première approche, il est très facile d'oublier l'ordre correct et de le taper à l'envers. Ainsi, au lieu de dire que le test a échoué parce qu'il attendait 1 et a obtenu 2, le message est inversé. Ce n'est pas un problème lorsque le test est réussi, mais cela peut prêter à confusion lorsque le test échoue.

Avec la deuxième version, il est presque impossible de faire cette erreur.

9voto

MartinL Points 537

Exemple :

assertThat(5 , allOf(greaterThan(1),lessThan(3)));
//  java.lang.AssertionError:
//  Expected: (a value greater than <1> and a value less than <3>)
//       got: <5>
assertTrue("Number not between 1 and 3!", 1 < 5 && 5 < 3);
//  java.lang.AssertionError: Number not between 1 and 3!
  1. vous pouvez rendre vos tests plus particuliers
  2. vous obtenez une Exception plus détaillée, si les tests échouent
  3. plus facile de lire le test

btw : vous pouvez aussi écrire du texte dans assertXXX...

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