¿Por qué debería usar Hamcrest-Matcher y afirmar That () en lugar del aserción tradicional XXX () - Métodos

153

Cuando miro los ejemplos en la clase 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

No veo una gran ventaja sobre, digamos, assertEquals( 0, 1 ).

Quizás sea bueno para los mensajes si las construcciones se vuelven más complicadas, pero ¿ves más ventajas? ¿Legibilidad?

Peter Kofler
fuente

Respuestas:

172

No existe una gran ventaja para aquellos casos en los assertFooque existe uno que coincide exactamente con su intención. En esos casos se comportan casi igual.

Pero cuando se trata de controles que son algo más complejos, la ventaja se vuelve más visible:

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

vs.

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

Uno puede discutir cuál de ellos es más fácil de leer, pero una vez que la afirmación falla, obtendrá un buen mensaje de error assertThat, pero solo una cantidad mínima de información assertTrue.

assertThatle dirá cuál fue la afirmación y qué obtuvo en su lugar. assertTruesolo te dirá que llegaste a falsedonde esperabas true.

Joachim Sauer
fuente
También tenía esta pregunta en el fondo de mi mente. Gracias, nunca lo pensé de esta manera.
wheaties
1
También ayuda con la "regla" de una afirmación por prueba y se combina más fácilmente con las especificaciones de estilo BDD.
Nils Wloka el
2
Y separa el mecanismo de afirmación de la condición (que es lo que conduce a los mejores mensajes de error).
SteveD
2
El ejemplo es inverosímil ya que casi nadie usaría un solo assertTruecon un &&. Separarlo en dos condiciones hace que el problema sea obvio incluso en JUnit. No me malinterpretes; Estoy de acuerdo contigo, simplemente no me gusta tu ejemplo.
maaartinus
48

Las notas de la versión de JUnit para la versión 4.4 (donde se introdujo) establecen cuatro ventajas:

  • Más legible y escribible: esta sintaxis le permite pensar en términos de sujeto, verbo, objeto (afirmar "x es 3") en lugar de afirmar Equal , que usa verbo, objeto, sujeto (afirmar "es igual a 3 x")
  • Combinaciones: cualquier declaración de coincidencia se puede negar ( no (s) ), combinar ( ya sea (s) .o (t) ), asignar a una colección ( cada (s) ), o usar en combinaciones personalizadas ( afterFiveSeconds (s) )
  • Mensajes de falla legibles. (...)
  • Matchers personalizados. Al implementar la interfaz Matcher usted mismo, puede obtener todos los beneficios anteriores para sus propias afirmaciones personalizadas.

Argumento más detallado del tipo que creó la nueva sintaxis: aquí .

Manur
fuente
39

Básicamente para aumentar la legibilidad del código .

Además de Hamcrest, también puedes usar las afirmaciones festivas . Tienen algunas ventajas sobre Hamcrest como:

Algunos ejemplos

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

17 de octubre de 2016 Actualización

Fest ya no está activo, use AssertJ en su lugar.

Igor Popov
fuente
44
Fest parece haber muerto, pero el tenedor AssertJ está muy vivo.
Amedee Van Gasse
18

Una justificación muy básica es que es difícil estropear la nueva sintaxis.

Suponga que un valor particular, foo, debería ser 1 después de una prueba.

assertEqual(1, foo);

--O--

assertThat(foo, is(1));

Con el primer enfoque, es muy fácil olvidar el orden correcto y escribirlo al revés. Entonces, en lugar de decir que la prueba falló porque esperaba 1 y obtuvo 2, el mensaje es al revés. No es un problema cuando la prueba pasa, pero puede generar confusión cuando la prueba falla.

Con la segunda versión, es casi imposible cometer este error.

Andy Davis
fuente
... y cuando Eclipse informa un error de aserción, si coloca los argumentos al revés en el aserción tradicional ThatThat (), el error no tiene sentido.
Sridhar Sarnobat
9

Ejemplo:

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. puedes hacer tus pruebas más particulares
  2. obtienes una excepción más detallada, si las pruebas fallan
  3. más fácil de leer la prueba

por cierto: también puedes escribir texto en afirmar XXX ...

MartinL
fuente
1
Mejor aún, dejaría de lado el argumento de cadena en el assertThatcaso, porque el mensaje que recibe automáticamente es igual de informativo: "Esperado: (un valor mayor que <1> y un valor menor que <3>)"
MatrixFrog
Sí, tiene usted razón. Edito mi respuesta. Originalmente quiero usar ambos (Matcher) y (Matcher) pero no funcionó.
MartinL
3
assertThat(frodo.getName()).isEqualTo("Frodo");

Está cerca del lenguaje natural.

Lectura más fácil, análisis de código más fácil. El programador pasa más tiempo analizando el código que escribiendo uno nuevo. Entonces, si el código será fácil de analizar, entonces el desarrollador debería ser más productivo.

El código PS debe ser un libro bien escrito. Código auto documentado.

usuario4515828
fuente
44
Vale y…? Recomiendo apoyar su argumento explicando por qué es algo bueno.
Nathan Tuggy
0

Hay ventajas para afirmar que por aserción iguales -
1) más legible
2) más información sobre la falla
3) errores de tiempo de compilación - en lugar de errores de tiempo de ejecución
4) flexibilidad con condiciones de prueba de escritura
5) portátil - si está utilizando Hamcrest - puede usar jUnit o TestNG como el marco subyacente.

samshers
fuente