Perché dovrei usare Hamcrest-Matcher e assertThat () invece del tradizionale assertXXX () - Metodi


153

Quando guardo gli esempi nella 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

Non vedo un grande vantaggio rispetto, diciamo, assertEquals( 0, 1 ).

È bello forse per i messaggi se i costrutti diventano più complicati ma vedi più vantaggi? Leggibilità?

Risposte:


172

Non c'è un grande vantaggio per quei casi in cui assertFooesiste un esatto che corrisponde esattamente al tuo intento. In quei casi si comportano quasi allo stesso modo.

Ma quando si arriva a controlli che sono un po 'più complessi, allora il vantaggio diventa più visibile:

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

vs.

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

Si può discutere su quale di questi sia più facile da leggere, ma una volta che l'asserzione fallisce, si ottiene un buon messaggio di errore assertThat, ma solo una quantità minima di informazioni da assertTrue.

assertThatti dirò qual è stata l'asserzione e cosa hai ottenuto invece. assertTrueti dirò solo che sei arrivato falsedove ti aspettavi true.


Anch'io avevo questa domanda nella parte posteriore della mia mente. Grazie, non ci ho mai pensato in questo modo.
esibisce il

1
Aiuta anche con la "regola" di un'asserzione per test e si fonde più facilmente con le specifiche in stile BDD.
Nils Wloka,

2
E separa il meccanismo di asserzione dalla condizione (che è ciò che porta ai migliori messaggi di errore).
SteveD,

2
L'esempio non è plausibile poiché quasi nessuno userebbe un singolo assertTruecon un &&. Separarlo in due condizioni rende evidente la causa del problema anche in JUnit. Non fraintendetemi; Sono d'accordo con te, non mi piace il tuo esempio.
maaartino,

48

Le note sulla versione di JUnit per la versione 4.4 (dove è stata introdotta) presentano quattro vantaggi:

  • Più leggibile e tipizzabile: questa sintassi ti permette di pensare in termini di soggetto, verbo, oggetto (asserire "x is 3") piuttosto che assertEquals , che usa verbo, oggetto, soggetto (assert "equals" equals 3 x ")
  • Combinazioni: qualsiasi istruzione corrispondente può essere annullata ( non) ), combinata ( o (s) .o (t) ), mappata a una raccolta ( ciascuna ) o utilizzata in combinazioni personalizzate ( afterFiveSeconds (s) )
  • Messaggi di errore leggibili. (...)
  • Matcher personalizzati. Implementando il tu stesso l'interfaccia Matcher , puoi ottenere tutti i vantaggi di cui sopra per le tue affermazioni personalizzate.

Argomentazioni più dettagliate del ragazzo che ha creato la nuova sintassi: qui .


39

Fondamentalmente per aumentare la leggibilità del codice .

Oltre alla più amara, puoi anche usare le asserzioni fest . Hanno alcuni vantaggi rispetto alla più amara come:

Qualche esempio

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

Aggiornamento del 17 ottobre 2016

Fest non è più attivo, utilizzare invece AssertJ .


4
Fest sembra essere morto, ma il fork AssertJ è molto vivo.
Amedee Van Gasse,

18

Una giustificazione molto semplice è che è difficile confondere la nuova sintassi.

Supponiamo che un valore particolare, foo, dovrebbe essere 1 dopo un test.

assertEqual(1, foo);

--O--

assertThat(foo, is(1));

Con il primo approccio, è molto facile dimenticare l'ordine corretto e digitarlo all'indietro. Quindi, invece di dire che il test ha avuto esito negativo poiché prevedeva 1 e ne otteneva 2, il messaggio è al contrario. Non è un problema al superamento del test, ma può causare confusione quando il test fallisce.

Con la seconda versione, è quasi impossibile commettere questo errore.


... e quando Eclipse segnala un errore di asserzione, se metti gli argomenti in modo errato nel tradizionale assertThat (), l'errore non ha senso.
Sridhar Sarnobat,

9

Esempio:

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. puoi rendere i tuoi test più particolari
  2. si ottiene un'eccezione più dettagliata, se i test falliscono
  3. più facile da leggere il test

btw: puoi scrivere anche il testo in assertXXX ...


1
Meglio ancora, tralascerei l'argomento stringa nel assertThatcaso, perché il messaggio che ricevi automaticamente è altrettanto informativo: "Previsto: (un valore maggiore di <1> e un valore inferiore a <3>)"
MatrixFrog

Si hai ragione. Modifica la mia risposta. Inizialmente voglio usare entrambi (Matcher) .e (Matcher) ma non ha funzionato.
MartinL,

3
assertThat(frodo.getName()).isEqualTo("Frodo");

È vicino al linguaggio naturale.

Codice di lettura più facile, più facile da analizzare. Il programmatore impiega più tempo ad analizzare il codice che a scriverne uno nuovo. Quindi, se il codice sarà facile da analizzare, lo sviluppatore dovrebbe essere più produttivo.

Il codice PS dovrebbe essere un libro ben scritto. Codice auto documentato.


4
Ok e…? Consiglio di sostenere la tua tesi spiegando perché è una buona cosa.
Nathan Tuggy,

0

ci sono vantaggi da asserire Che su assertEquals -
1) più leggibili
2) maggiori informazioni sull'errore
3) compilare errori di tempo - piuttosto che errori di runtime
4) flessibilità con la scrittura delle condizioni del test
5) portatile - se si sta usando hamcrest - è possibile utilizzare jUnit o TestNG come framework sottostante.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.