¿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?

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.


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í .


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.


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.


... 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 ...


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.


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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.