Comprobar una lista con JUnit

155 views
Skip to first unread message

José Manuel Beas

unread,
Oct 19, 2010, 7:10:30 PM10/19/10
to tddev-sp
Hola,

Siento preguntar algo tan básico, pero...

Tengo un método que me devuelve List<String> (en Java) y quiero comprobar con JUnit que son los que espero. ¿Cómo lo hacéis, un bucle o JUnit proporciona algo para escribirlo más compacto?

Alberto Peña

unread,
Oct 19, 2010, 7:35:52 PM10/19/10
to tdde...@googlegroups.com
El 2010/10/20 José Manuel Beas <jose....@gmail.com> escribió  

 
Tengo un método que me devuelve List<String> (en Java) y quiero comprobar con JUnit que son los que espero. ¿Cómo lo hacéis, un bucle o JUnit proporciona algo para escribirlo más compacto?


Nosotros usamos la librería de hamcrest y hacemos:

  assertThat(miLista, hasItem(laCadenaQueQuieroQueTenga));

Eso por cada elemento de la lista que quiero comprobar.

assertThat y hasItem son métodos estáticos que te da hamcrest. JUnit tiene dentro algo de hamcrest, pero no se si tiene el hasItem(el assertThat seguro que sí)

Si lo que quieres es comprobar que te devuelve 1000 elementos entonces algo huele a podrido :P Pero para Strings creo que vale con:

  assertThat(miLista, is(laCadenaQueQuieroQueTenga));


Si no quieres usar hamcrest puedes hacer un 

  assertTrue(miLista.contains(laCadenaQueQuieroQueTenga));

Pero no queda tan molón :P

Y para el caso chungo, igual te vale:

  assertEquals(miLista, laListaQueEspero);

El equals de las listas comprueba que sus elementos sean los iguales.

Un saludo

PS: Supongo que con decirte assertEquals(miLista, laListaQueEspero); te habría valido, pero no lo he pensado hasta el final del correo y ya no quería borralo todo :P

--
Alberto Peña Abril

http://twitter.com/plagelao
http://plagelao.blogspot.com/

belano

unread,
Oct 19, 2010, 7:38:33 PM10/19/10
to TDDev
Buenas,

Yo suelo utilizar matchers de la librería hamcrest. Copio y pego un
ejemplo por si te puede ayudar:

import static org.hamcrest.Matchers.*;
import static org.junit.matchers.JUnitMatchers.*;
import static util.matchers.CustomMatchers.*

...

List<DatosBasicosPlanFormativo> planesFormativos =
soapProxy.getPlanesFormativos(2009, EstadoPlan.FINALIZADO);

assertTrue(CollectionUtils.isNotEmpty(planesFormativos));
assertThat(
planesFormativos,
everyItem(
allOf(
withPropertyEquals(DatosBasicosPlanFormativo.class, "estado",
EstadoPlan.FINALIZADO),
withPropertyEquals(DatosBasicosPlanFormativo.class, "anualidad",
2009)
)
)
);

El método estático withPropertyEquals lo defino en una clase
CustomMatchers:

public class CustomMatchers {

public static <T, U> Matcher<T> withPropertyEquals(Class<T> clazz,
String propertyName, U value) {
return hasProperty(propertyName, IsEqual.equalTo(value));
}

public static <T, U> Matcher<T> withPropertyMatches(Class<T> clazz,
String propertyName, Matcher<U> matcher) {
return hasProperty(propertyName, matcher);
}

}

Si lo que quieres es comprobar los valores de una lista de String,
creo que con el matcher "is" te valdría:

assertThat(
miLista,
everyItem(is("Texto"))
);

Saludos

José Manuel Beas

unread,
Oct 19, 2010, 8:12:19 PM10/19/10
to tdde...@googlegroups.com
En realidad busco una manera más compacta de escribir:

@Test
public void testQueLasPropuestasSalenEnLaListaDeLineas() throws Exception {
List<LineaDeInformeDeContratos> lineasDeInforme = generador.construyeInformeDeContratos();
assertEquals(3,lineasDeInforme.size());
LineaDeInformeDeContratos primeraLineaDelInforme = lineasDeInforme.get(0);
assertEquals("108",primeraLineaDelInforme.getNumeroPropuesta());
LineaDeInformeDeContratos segundaLineaDelInforme = lineasDeInforme.get(1);
assertEquals("734",segundaLineaDelInforme.getNumeroPropuesta());
}

@Test
public void testQueLasPropuestasTienenElNombreDeLaOficinaDondeSeFirmo() throws Exception {
List<LineaDeInformeDeContratos> lineasDeInforme = generador.construyeInformeDeContratos();
LineaDeInformeDeContratos primeraLineaDelInforme = lineasDeInforme.get(0);
assertEquals("MADRID",primeraLineaDelInforme.getNombreOficina());
LineaDeInformeDeContratos segundaLineaDelInforme = lineasDeInforme.get(1);
assertEquals("LONDRES",segundaLineaDelInforme.getNombreOficina());
}
@Test
public void testQueLasPolizasSalenEnLaListaDeLineas() throws Exception {
List<LineaDeInformeDeContratos> lineasDeInforme = generador.construyeInformeDeContratos();
LineaDeInformeDeContratos lineaDeUnaPropuestaNoConfirmada = lineasDeInforme.get(0);
assertFalse("una propuesta no confirmada no es una póliza",lineaDeUnaPropuestaNoConfirmada.haSidoConfirmada());
LineaDeInformeDeContratos lineaDeUnaPropuestaConfirmada = lineasDeInforme.get(1);
assertTrue("una propuesta una vez confirmada es una póliza",lineaDeUnaPropuestaConfirmada.haSidoConfirmada());
}

Y busco que sea más compacto porque sé que esto se va a ir complicando y entonces necesitaré una manera de tener una notación que me permita leer y escribir más tests y mantener la legibilidad. (He pensado pasarme a Concordion, pero el entorno donde se ejecutaría no está preparado aún y no creo que me permita resolver el problema más fácilmente).

Gracias por las ideas. Si no las uso ahora las usaré más adelante. :-)


Un saludo,
2010/10/20 belano <dieli...@gmail.com>
--
Has recibido este mensaje porque estás suscrito al grupo "TDDev" de Grupos de Google.
Para publicar una entrada en este grupo, envía un correo electrónico a tdde...@googlegroups.com.
Para anular tu suscripción a este grupo, envía un correo electrónico a tddev-sp+u...@googlegroups.com
Para tener acceso a más opciones, visita el grupo en http://groups.google.com/group/tddev-sp?hl=es.


Alfredo Casado

unread,
Oct 19, 2010, 9:00:07 PM10/19/10
to tdde...@googlegroups.com
Que tal algo como:

assertThat(informe.get(PRIMERA_LINEA), esComo(unaLineaDeInforme.conNombreOficina("208")
                                                                                                       .conNumeroPropuesta(32)
                                                                                                       .confirmada()
                                                                                                       .build()));

Te tienes que construir el matcher "esComo" que compara dos lineas de informes y el builder para crear las listas de informes, pero escala bien según vayas añadiendo nuevos elementos a la linea. No me convence lo de get(0) eso si... habría que darle una vuelta.

Abel Cuenca

unread,
Oct 20, 2010, 12:53:45 AM10/20/10
to tdde...@googlegroups.com
Es un poco pronto para mi, igual digo algo que no vale:-), ¿tienes algún problema en montar una lista con todo lo que esperas? Lo digo porque JB en jUnit Recipes recomienda montar una lista con los datos que esperas y hacer un assertEquals() entre esa lista y tu resultado o usar GSBase, si tienes condiciones del tipo objetos repetidos en tu resultado. 

El libro, de todas maneras, tiene 5 años, igual hay otras opciones mejores. De hecho, me sorprendería que hamcrest no tuviera un comparador de Lists... 

Enviado desde mi iPhone

José Manuel Beas

unread,
Oct 20, 2010, 2:38:08 AM10/20/10
to tdde...@googlegroups.com
Gracias Alfredo, la combinación Matcher+Builder me ha gustado. Creo que viene a ser lo que estaba buscando.
Abel, tienes razón, debería haber sido mi primera opción (Alberto lo sugirió también) pero tenía en mente el futuro cercano y me resistí.
Lo del get(0) me ha servido al menos en los primeros pasos del TDD porque me ha forzado a triangular al hacer get(1). Tengo en la cabeza algo como lo que hace Concordion con las tablas, pero el inexorable Cronos ha llegado para comerse a su hijo más querido. :-)

Iván Párraga García

unread,
Oct 20, 2010, 2:58:26 AM10/20/10
to tdde...@googlegroups.com
Hola,

No sé si os estáis complicando un poco o si yo he leído demasiado en vertical, pero... ¿Qué tal lo siguiente?

List<Object> expected = ...
List<Object> actual = miSuperMetodoBajoTest();

assertArrayEquals(expected.toArray(), actual.toArray());

Iván



Alfredo Casado

unread,
Oct 20, 2010, 6:00:04 AM10/20/10
to tdde...@googlegroups.com
dandole una vuelta mejor así:

List<Linea> elInforme = ....
assertThat(elInforme , is(unInforme.con(unaLinea().conNombreOficina("208")
                                                                        .conNumeroPropuesta(32)
                                                                        .confirmada())
                                                 .con(unaLinea().conNombreOficina("208")
                                                                       .conNumeroPropuesta(32)
                                                                       .confirmada()));

Ahora si me gusta más, el "is" simplemente hace equals así que en el fondo lo único que haces es comparar dos listas.

Lo de hacer el arrayEquals, en algún sitio tendrás igualmente que construir la lista de informes esperada, en realidad esto lo único que es es la creación de la lista con un builder que es una forma de creación de objetos en mi opinión mucho más expresiva que ayuda a la legibilidad de los test una barbaridad. No veas el gustito que da entrar a un test que ha echo otro compañero tuyo hace un mes y entenderlo a la primera xd
                                                                     

J. B. Rainsberger

unread,
Oct 23, 2010, 7:45:53 AM10/23/10
to tdde...@googlegroups.com
2010/10/20 José Manuel Beas <jose....@gmail.com>
En realidad busco una manera más compacta de escribir:

@Test
public void testQueLasPropuestasSalenEnLaListaDeLineas() throws Exception {
List<LineaDeInformeDeContratos> lineasDeInforme = generador.construyeInformeDeContratos();
assertEquals(3,lineasDeInforme.size());
LineaDeInformeDeContratos primeraLineaDelInforme = lineasDeInforme.get(0);
assertEquals("108",primeraLineaDelInforme.getNumeroPropuesta());
LineaDeInformeDeContratos segundaLineaDelInforme = lineasDeInforme.get(1);
assertEquals("734",segundaLineaDelInforme.getNumeroPropuesta());
}

Yo creo la lista que espero, y después hago assertEquals(expected, actual). Para hacerlo, necesito implementar equals(), pero la pruebas son fáciles a escribir y comprender.
--
J. B. (Joe) Rainsberger :: http://www.jbrains.ca :: http://blog.thecodewhisperer.com
Diaspar Software Services :: http://www.diasparsoftware.com
Author, JUnit Recipes
2005 Gordon Pask Award for contribution to Agile practice :: Agile 2010: Learn. Practice. Explore.
Reply all
Reply to author
Forward
0 new messages