Dónde dejamos los test
Idealmente una prueba unitaria va a permitir probar una unidad de código independiente. De modo que si nosotros en el área de código fuente de la aplicación tenemos clases, interfaces, registros y otro tipo de módulos, lo normal será que por cada uno de estos módulos exista a su vez una prueba unitaria vinculada al módulo para probarla por separado.
Lo habitual en el mundo de Java será que coexistan dos carpetas separadas, src/ y test/. La primera contiene solamente el código de la aplicación, pero la segunda es donde vamos a dejar las pruebas unitarias. Normalmente, cuando corremos el código en modo desarrollo o producción, la carpeta test/ se va a excluir. Sin embargo, cuando corramos el código en modo test, se van a solapar y juntar los archivos que hay en la carpeta src/ y en la carpeta test/, lo que significa que el código que tengamos en la carpeta test/ va a poder importar clases que estén en la carpeta src/.
Lo normal será que el test de una clase tenga el mismo nombre que el módulo que vamos a testear y que esté en el mismo paquete, pero con la partícula Test en el sufijo. Es decir, si vamos a probar la clase junit5.catalogo.Pedido, el test se llamará junit5.catalogo.PedidoTest, y formará parte del grupo test/. Al tener el mismo nombre de paquete, no hará falta poner imports, lo que hará los tests más directos de escribir. También tendrá la ventaja de que podremos probar clases no exportadas (que no tengan la palabra public).
Cómo hacer un test con JUnit 5
Una vez hayamos creado nuestra clase de test dentro del módulo correspondiente, lo que haremos será escribir el código fuente de un test. Para ello en JUnit 5 todo lo que hay que hacer es declarar un método público de tipo void que debe tener la anotación @Test, la cual podemos importar desde org.junit.jupiter.api.Test.
Por ejemplo, este podría ser el esqueleto de un test:
package junit5.carrito;
import org.junit.jupiter.api.Test;
public class CarritoTest {
@Test
public void testFoobar() {
}
}
Asertos
La unidad básica de pruebas en un framework como JUnit es el aserto. El aserto es un condicional que nos permite comprobar si algo es verdadero o falso o que cumple una determinada condición.
Sin embargo, es más sofisticado que un if. Los asertos en caso de detectar que un condicional no se cumple, pueden generar un mensaje de error automático que interrumpa la ejecución de un test. De este modo, podemos usar asertos para validar que una serie de propiedades dentro de un test se cumplen. En el momento que una de las propiedades deje de cumplirse, el test se interrumpe automáticamente y se marca como erróneo, debido a que uno de sus asertos ha fallado.
Por ejemplo, con el aserto assertTrue, podemos comprobar que el parámetro es verdadero. Si le pasamos como parámetro algo que evalúa a falso, esto marcará todo el test como erróneo porque generará un aviso.
@Test
public void testValido() {
assertTrue(2 == 2);
}
@Test
public void testInvalido() {
assertTrue(2 == 3);
}
Sobre cómo nos damos cuenta que el test ha fallado, lo cuento un poco más abajo. Decir que existen muchos más asertos. Por ejemplo:
- Con
assertFalse(x)podemos comprobar que x sea falso. - Con
assertEquals(x, y)podemos comprobar quexeysean iguales. - Con
assertNull(x)podemos comprobar que x sea null. - Con
assertSame(x, y)podemos comprobar que las dos variables efectivamente sean la misma en el sentido de que apunten a la misma referencia.
En el caso de JUnit 5, estas funciones forman parte de la clase Assertions, disponible en el paquete org.junit.jupiter.api. Lo típico será importar de manera estática todos los métodos estáticos de esta clase para no tener que escribir tanto:
package junit5.carrito;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class CarritoTest {
@Test
public void testFoobar() {
Carrito c = new Carrito(500);
assertTrue(500, carrito.total());
}
}