web-dev-qa-db-fra.com

Pourquoi devrais-je utiliser Hamcrest-Matcher et assertThat () au lieu de l'assertXXX () traditionnel - Méthodes

Quand je regarde les exemples de la classe Assert JavaDoc

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 un gros avantage sur, disons, assertEquals( 0, 1 ).

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

148
Peter Paul

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

Mais lorsque vous parlez de 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 déterminer lequel de ceux-ci est le plus facile à lire, mais une fois que l'assertion échoue, vous obtenez un bon message d'erreur de assertThat, mais une quantité très minime d'informations provenant de assertTrue.

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

168
Joachim Sauer

JUnit notes de version pour la version 4.4 (où il a été introduit) présente quatre avantages:

  • Plus lisible et typable: cette syntaxe vous permet de penser en termes de sujet, verbe, objet (assert "x est 3") plutôt que assertEquals , qui utilise un verbe, un objet et un sujet (affirmer "est égal à 3 x")
  • Combinaisons: toutes les instructions correspondantes peuvent être annulées (, non (s) ), combinées ( non plus. ou (t) ), mappé sur une collection ( each (s) ), ou utilisé dans des combinaisons personnalisées ( afterFiveSeconds (s) )
  • Messages d'échec lisibles. (...)
  • Matchers personnalisés. En implémentant vous-même l'interface Matcher , vous pouvez obtenir tous les avantages ci-dessus pour vos propres assertions personnalisées.

Argumentation plus détaillée de l'homme qui a créé la nouvelle syntaxe: ici .

45
Manur

Fondamentalement pour augmenter la lisibilité du code .

Outre hamcrest, vous pouvez également utiliser les assertions de fest . Ils ont quelques avantages par rapport au hamcrest tels que:

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));

Mise à jour du 17 octobre 2016

Fest n'est plus actif, utilisez plutôt AssertJ .

38
Igor Popov

Une justification de base est qu'il est difficile de gâcher la nouvelle syntaxe.

Supposons qu'une valeur particulière, foo, soit é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 le bon ordre et de le taper à l'envers. Ensuite, plutôt que de dire que le test a échoué car il s’attendait à 1 et 2, le message est inversé. Pas de problème lorsque le test réussit, mais peut entraîner une confusion lorsque le test échoue.

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

18
Andy Davis

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 à lire le test

au fait: vous pouvez aussi écrire du texte dans assertXXX ...

9
MartinL
assertThat(frodo.getName()).isEqualTo("Frodo");

Est proche du langage naturel.

Lecture plus facile, analyse plus facile du code. Le programmeur passe plus de temps à analyser le code qu'à en écrire un nouveau. Donc, si le code sera facile à analyser, le développeur devrait être plus productif.

P.S. Le code devrait être comme livre bien écrit. Code auto-documenté.

3
user4515828

il y a des avantages à affirmerQue par rapport à assertEquals -
1) plus lisible
2) plus d'informations sur l'échec
3) Compiler les erreurs de temps - plutôt que les erreurs de temps d'exécution
4) souplesse dans la rédaction des conditions de test
5) portable - si vous utilisez hamcrest - vous pouvez utiliser jUnit ou TestNG comme infrastructure sous-jacente.

1
samshers