Enjoy A New Student Discount All 55,000 Courses on sale for Only $12.99

Ends in 05h 23m 49s

Desarrollo de un CRUD con SpringBoot. Test de las validaciones

Hemos terminado de escribir un modulo dentro del proyecto. Este modulo es el de validaciones, y es totalmente plano, esto hace que pasarles unos test sea muy sencillo, El desarrollo lo podeis encontrar en el articulo anterior de Desarrollo de un CRUD, en el canal de YouTube, o en GitHub (desaconsejado), si os da pereza escribirlo, pero lo vais a necesitar para poder empezar a realizar los test unitarios

Para que molestarnos en hacer Test

Por muy seguro que estemos de lo bien que programamos, cada día la realidad nos muestra que cometemos errores, y, aunque los lenguajes y los IDEs intentan minimizarlos, siempre se nos van escapando alguno, que antes o después, puede crear una mala imagen de la aplicacion, de la empresa, de la web, de la aplicación, … y como consecuencia una mala imagen nuestra. Realmente, manejamos informacion a veces delicada, a veces critica, y, debemos hacer todos los esfuerzos necesarios para minimizar esos problemas (aunque siempre podrán existir).

Los problemas, normalmente , no surgen de que hagamos algo mal, si no de que no hemos previsto todas las posibilidades que se pueden dar con lo datos que manejan nuestro código, y, esa combinación seguro que ocurrirá, provocando un error, luego necesitamos una herramienta que nos permita simular esas combinaciones de una forma rapida, para asi probar nuestro codigo de una forma cómoda, (que alguien no tenga que pasar horas en el terminal probando combinaciones)

Otra fuente de errores, todavía mas odiosa, es cuando nos dan una aplicacion que funciona perfectamente, para que modifiquemos un pequeño detalle, y, naturalmente que nosotros vamos a probar esa corrección hasta la saciedad, pero… si esa modificación, afecta a una función que esta 100 lineas mas abajo del codigo, y por la que se pasa en muy contadas ocasiones… un buen dia seremos responsable de un error en un sitio que nunca habíamos tocado. Entonces, nuestra herramienta mágica deberia poder realizar pruebas sobre todo el aplicativo, cada vez que alguien lo modifica, aunque sea una tonteria.

Bien, os acabo de describir Junit, un paquete pensado para poder realizar test, y dejarlos guardados, para que los podamos repetir siempre que queramos

El paquete Junit5

Este articulo no esta pensado para extendernos en las clases de test que hay, podemos verlas mas adelante; como introducción, solo quiero hablar de los test unitarios, en los que solo interviene en la prueba una función; nosotros le damos unos datos, y comprobamos nos de el resultado que nosotros sabemos que es el correcto. y con eso, y un muchísimo de imaginación, tenemos resuelto el problema.

Junit5 tiene muchas anotaciones y asserts disponibles; os invito a que las reviseis en junit.org

Como he dicho antes, vamos a realizar el test de la clase que construimos en el articulo anterior y lo realizaremos con este framework muy habitual en Java, que es Junit 5

Si abrimos STS con la app descargada, veremos el siguiente esquema.

Realmente, nosotros vamos a escribir el módulo RutinasTest.java, que utilizaremos para comprobar si nuestra clase Rutinas funciona bien.

Lo primero de todo, observad que ya tenemos un directorio src/test/java, para todos los package de test y se debe replicar exactamente los existentes en el directorio de trabajo src/main/java. Esto nos permite suprimir las clases de test en la generación de produccion, pero nos deja reconocer fácilmente el package

Programando el test

La clase de test la podemos definir manualmente, pero si nos ayudan un poco mejor, de forma que si apoyamos el ratón en el modulo a testear y utilizamos el botón derecho…

Nos aparece la pantalla de creación con

Nos aparece seleccionado New Junit Jupiter, que es el nombre como se reconoce también a la version 5 de Junit

El sistema ya nos ofrece correctamente el resto de la informacion, por lo que podemos pulsar en Next Para ir a

La idea es que seleccionemos los métodos para los que vamos a realizar test, y que normalmente, serán todos los de la clase, por lo que marco el checkbox situado al lado de Rutinas y pulsamos Finish

En unos segundos, nos aparece el módulo de test preparado para que podamos escribir nuestras instrucciones

Cada uno de estos métodos que ha creado, son para que nosotros escribamos las instrucciones para realizar el test de la función descrita en el nombre. Por ejemplo, en la linea 11 deberemos probar el método isVacio, y asi sucesivamente

La anotación @Test define que esa función es de test, por lo que no debe devolver nada

Veamos como resolvemos este test. El método espera recibir una string, y ha de contestar true si llega una string nula o vacía, y falso, para el resto de casos.

Podemos definir tres constantes String con esas características, luego, al principio de la clase, podemos decir

        String STRING_NULA;
	final String STRING_VACIA = "";
        final String STRING_CON_DATOS = "Hola";

Ahora ya podemos escribir el test, enviando cada uno de esos datos, e indicando la respuesta que esperamos (True o False)

        @Test
	void testIsVacio() {
		assertTrue(Rutinas.isVacio(STRING_NULA)); 
		assertTrue(Rutinas.isVacio(STRING_VACIA));
		assertFalse(Rutinas.isVacio(STRING_CON_DATOS));
	}

Es bastante claro, podríamos hacer tantas comprobaciones como queramos, indicando, siempre, la respuesta que esperamos

Sin embargo, si lo queremos hacer asi, dentro de un test, el sistema detiene la ejecución cuando encuentra un error, por lo que en una pasada, no veríamos todos los test; eso lo podemos evitar usando el assertAll

        @Test
	void testIsVacio() {
		assertAll(
			() -> assertTrue(Rutinas.isVacio(STRING_NULA)),
                        () -> assertTrue(Rutinas.isVacio(STRING_VACIA)),
                        () -> assertFalse(Rutinas.isVacio(STRING_CON_DATOS))
                );
        }

Asi, hacemos que se realicen todas las pruebas, independientemente del resultado

Ahora, podemos iniciar la ejecución, cursor de ratón encima de RutinasTest y botón derecho

Veremos que se ejecuta el test y en una ventana nos aparece el resultado

Como vemos, el test (testIsVacio) ha pasado, y solo quedan los test de los métodos que no hemos escrito todavía. A partir de este momento, podemos ir creando cada test e ir probando, solo tened en cuenta que no debemos modificar la clase bajo test, para poder realizar el test, en la clase bajo test, solo deberemos corregir los errores detectados

Aparte del assertTrue y assertFalse que ya habeis visto utilizar, tenemos otros assert como:

  • assertEquals – Se indica la rutina y el valor que espera, y comprueba que sean iguales
    assertEquals(2, calculator.add(1, 1));
  • assertNotNull – Comprueba el parámetro dentro de la funcion no sea nulo
    assertNotNull(lastName);
  • assertThrows – Comprueba que la funcion lance el error indicado
    Exception exception = assertThrows(ArithmeticException.class, () -> calculator.divide(1, 0)); assertEquals(«/ by zero», exception.getMessage());

Las anotaciones

Ya hemos visto que los métodos destinados a ser de test, van precedido por la anotación @Test, pero debemos tener en cuenta algunas otras

  • @BeforeAll – el método anotado se ejecutará antes de todos los @Test y se debe escribir en un método static
  • @AfterAll – el método anotado se ejecutará después de todos los @Test y se debe escribir en un método static
  • @BeforeEach – el método anotado se ejecutará antes cada @Test, @RepeatedTest, @ParameterizedTest o @TestFactory
  • @AfterEach – el método anotado se ejecutará después de  cada @Test, @RepeatedTest, @ParameterizedTest o @TestFactory
  • @ParameterizedTest – El método de test recibirá parámetros
    • @ParameterizedTest(name = «caso año {0] es erróneo.»)
    • @ValueSource(ints = { -1, -4 })
    • void if_it_is_negative(int year) { }
  • @RepeatedTest – Permite repetir un mismo test un numero de veces determinado. Se puede establecer el numero de veces que se autoriza que falle (failureThreshold) antes de dar el test por erróneo. Revisar la documentación de Junit5

Cuando lanzamos un test, no podemos garantizar el orden en que se ejecutaran los distintos métodos, Normalmente, no deberia tener importancia ya que cada test lo deberíamos realizar en un ambiente que garantizase que es único: pero si necesitamos imponer secuencia, podemos anotar el método con

  • @TestMethodOrder – (A nivel de clase) Garantiza la ejecución de los métodos en el orden previsto por la anotación @Order(n) a nivel de método.

Otra anotacion

  • @DisplayName – Podemos asignar nombres adecuados a los test

Podemos desactivar clases y/o métodos concretos, anteponiendo la anotación

  • @Disabled(«motivo por el que esta desactivado la clase o el método concreto»)

Cuando utilizamos una de estas anotaciones, aparte de los parámetros que cada una acepte, podemos incluir un parámetro mas, que es «name«, y que establece de forma dinámica el nombre de test.

En los test parametrizados, podemos añadir con {n} el parámetro que nos interese, y em los test de repetición, podemos indicar {currentRepetition} y {totalRepetition}

El test de correo electrónico

Vamos a realizar el test del método que comprueba el correo electronico. Sabemos que el test solo realiza comprobaciones sintacticas del campo, por lo que debemos generar unas cuantas String que contengan posibles correos electronicos correctos y erroneos, y, para eso, al principio de la clase, puedo añadir líneas como estas


	final String CORREO_ELECTRONICO_CORRECTO = "[email protected]";
	final String CORREO_ELECTRONICO_ERRONEO_1 = "migarcia.recursosformacion.com";
	final String CORREO_ELECTRONICO_ERRONEO_2 = "migarcia@recursosformacion";
	final String CORREO_ELECTRONICO_ERRONEO_3 = "@recursosformacion.com";
	final String CORREO_ELECTRONICO_ERRONEO_4 = "migarcia@";

El nombre de la cadena ya me indica si el literal se tiene que validar como correcto o erróneo, y también os indico que deberia haber previsto mas valores correctos, y eso lo hare en la version de YouTube

Ahora, ya podemos modificar el método testIsEmailValido, para retirar el mensaje de fail y escribir, por ejemplo

        @Test
	void testIsEmailValido() {
		assertAll(() -> assertTrue(Rutinas.isEmailValido(CORREO_ELECTRONICO_CORRECTO)),
		() -> assertFalse(Rutinas.isEmailValido(CORREO_ELECTRONICO_ERRONEO_1)),
		() -> assertFalse(Rutinas.isEmailValido(CORREO_ELECTRONICO_ERRONEO_2)),
		() -> assertFalse(Rutinas.isEmailValido(CORREO_ELECTRONICO_ERRONEO_3)),
		() -> assertFalse(Rutinas.isEmailValido(CORREO_ELECTRONICO_ERRONEO_4)));
	}

Probamos para ver que pasa, y continuamos

Para el resto de métodos, esta todo explicado, por lo que podéis resolverlo vosotros, pero… en el siguiente articulo veremos otras formas mas ingeniosas de resolverlo

Conclusión

Este articulo es parte de  Visión de conjunto con Spring y teneis un desarrollo con mas detalle en youTube, y, aunque es conveniente que intentéis escribirlo TODO vosotros, si queréis renunciar a ello, lo teneis tambien en GitHub

La explicación en YouTube:

En el siguiente, abordaremos otra forma de realizar los test

Deja un comentario

/*Si te ha gustado el artículo
no dudes en compartirlo*/

Facebook
Twitter
LinkedIn

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies

Ver mi IP

Ver ip de mi máquina
tipo valor
Ip: 18.191.216.163
Proxy: 18.191.216.163
Remote host: ec2-18-191-216-163.us-east-2.compute.amazonaws.com
Remote port: 41424
** 18.191.216.163, 172.70.130.136