En este tutorial veremos cómo realizar testing funcional con SoapUI y Apache Groovy.
Índice de contenidos
- 1. Introducción
- 2. Entorno
- 3. Definiciones
- 4. Groovy
- 5. API REST a probar
- 6. Scripting con SoapUI
- 7. Conclusiones
- 8. Referencias
1. Introducción
En este tutorial veremos cómo incorporar test funcionales a un API REST con la herramienta open source SoapUI utilizando scripts en Apache Groovy. SoapUI es una potente herramienta con muchas posibilidades, ya os hemos contado algunas de ellas en los diferentes tutoriales, pero hoy os mostraremos la potencia del scripting utilizando Groovy. Desarrollaremos un par de tests funcionales de un API en un escenario end to end.
Disponéis del código fuente en el siguiente enlace.
2. Entorno
El tutorial está escrito usando el siguiente entorno:
- Hardware: Portátil Mac Book Pro 15″ (2,5 Ghz Intel Core i7, 16 GB DDR3)
- Sistema Operativo: Mac OS Sierra 10.12.6
- SoapUI 5.3.0
- Groovy 2.1.7
- H2 versión 1.4.196
3. Definiciones
Dependiendo de con quién hables puede haber ciertos matices con respecto a lo que se entiende por test funcionales. Os hago este pequeño inciso porque muchas veces los test no tienen un objetivo claro y no aportan la seguridad que necesitamos. Para nuestro tutorial me basaré en la definición que se utiliza en la comunidad TDD: “Un test funcional es un subconjunto de los tests de aceptación. Es decir, comprueban alguna funcionalidad con valor de negocio.”
4. Groovy
Groovy es un lenguaje dinámico opcionalmente tipado que se ejecuta sobre la JVM, tiene características que están inspiradas en lenguajes como Python, Ruby y Smalltalk y utiliza una sintaxis similar a Java. Su sintaxis permite reducir la cantidad de código a desarrollar. A diferencia de otros lenguajes alternativos, está diseñado para ser un complemento, no un sustituto de Java. Y no… no es Java sin los puntos y coma. 😉
5. API REST a probar
En este tutorial utilizaremos un API REST para la gestión de usuarios securizada con JWT. Disponéis de los detalles de la misma en el siguiente enlace. En esta ocasión utilizaremos una base de datos H2 en modo servidor (estará escuchando en un puerto) para simular un servidor real de BD y poder acceder directamente por JDBC.
Nuestro testing funcional verificará que el API está debidamente securizada y que registra la información correctamente en la BD. Como hemos dicho anteriormente estas pruebas se centran en los requisitos de negocios.
Para comenzar, necesitaremos iniciar la base de datos en modo servidor. En la web de H2 podemos ver todos los detalles acerca de la misma, para nuestro ejemplo basta con arrancarla en modo servidor. A continuación, arrancaremos nuestra API con Spring Boot
# Se descarga H2, se descomprime y desde el directorio $H2_HOME/bin lanzamos el servidor en background cd $H2_HOME/bin java -cp h2*.jar org.h2.tools.Server & # Descargamos el proyecto demo y a continuacion arrancamos el API REST cd $DEMO_API_REST/ mvn spring-boot:run
Por último, tendremos que copiar el jar de H2 en las librerías de SoapUI para que podamos acceder por JDBC a la BD. Consultad la ruta concreta, en mi caso está en $SOAPUI_HOME/Contents/java/app/lib/ . Ya podemos arrancar SoapUI.
#Copiamos el driver de la BD, dentro de las librerías de SoapUI para poder establecer la conexión JDBC cp $H2_HOME/bin/h2-1.4.196.jar $SOAPUI_HOME/Contents/java/app/lib/ #Ya podemos arrancar SoapUI
Estructura del proyecto SoapUI
6. Scripting con SoapUI
Para realizar las pruebas generamos un proyecto de tipo REST y declaramos las URLs (recursos) que se utilizan en el API. A continuación, creamos el testsuite y los testcase que se van a utilizar. Como podéis observar en la siguiente imagen, los test están compuestos de llamadas y scripts. A continuación, podemos ver la estructura del proyecto.
Por ejemplo, en el testcase de login, lanzamos una llamada de login y validamos con el script la respuesta devuelta. El script verifica las cabeceras de la respuesta para poder afirmar que disponemos de un token (JWT) tras la autenticación. En el script ValidarLogin podéis observar cómo se accede al API Java de SoapUI para recuperar la repuesta HTTP e incorporar las validaciones correspondientes. ¡Todo ello en 4 líneas!
ValidarLogin
/* * Accede a la petición lanzada y revisa la respuesta. * * Para ello accedemos al API java que nos proporciona SoapUI * https://www.soapui.org/apidocs/index.html?overview-summary.html */ def httpResponseHeaders = context.testCase.testSteps["HTTP Login"].testRequest.response.responseHeaders def authorizationHeaders = httpResponseHeaders.get("Authorization") /* * Se valida que existe la cabecera y que incluye un token. * Cualquier array vacío, objeto a null en groovy equivale a false (esta característica se llama groovy truth). * Si authorizationHeaders NO existe se genera una excepción con el literal */ assert authorizationHeaders : "No se recupera la cabecera Authorization" /* * Podemos acceder a cualquier objecto de un array por el índice */ assert authorizationHeaders[0].startsWith("Bearer") : "No se recibe un token válido"
En el test de alta de Usuario observamos cómo se realiza primeramente el login y se utiliza el token proporcionado por el login para realizar el alta de un usuario y para recuperar la información del mismo.
Recuperar JWT del Login
def httpResponseHeaders = context.testCase.testSteps["HTTP Login"].testRequest.response.responseHeaders def authorizationHeaders = httpResponseHeaders.get("Authorization") // Se valida que existe la cabecera y que incluye un token. assert authorizationHeaders : "No se recupera la cabecera Authorization" // Se modifica la petición de alta y se incorpora el token que nos ha devuelto el login def headers = testRunner.testCase.testSteps["HTTP Get Usuario"].getHttpRequest().getRequestHeaders() headers["Authorization"] = authorizationHeaders; testRunner.testCase.testSteps["HTTP Get Usuario"].getHttpRequest().setRequestHeaders(headers)
En el script ValidarListado podemos acceder al JSON devuelto en la consulta de un usuario y navegar por el resultado de una forma sencilla.
ValidarListado
import groovy.json.JsonSlurper /* * Intentamos acceder al código de la respuesta HTTP */ def httpResponseHeaders = context.testCase.testSteps["HTTP Get Usuario"].testRequest.response.responseHeaders def httpStatus = httpResponseHeaders["#status#"] // Se valida que el servicio devuelve un código HTTP 200 -> OK. assert httpStatus == ['HTTP/1.1 200 '] : "No ha podido recuperar el listado de usuarios" // Se recupera los datos de la respuesta def responseBody = context.expand('${HTTP Get Usuario#Response}') def jsonResponse = new JsonSlurper().parseText(responseBody) // Se valida el alta assert jsonResponse.id : "No existe el atributo id" assert jsonResponse.username == "daenerys" : "El usuario no existe"
Para concluir con el script de limpieza restauramos el estado inicial eliminando el usuario dado de alta accediendo por JDBC directamente a la base de datos. ¡ Imaginad que tuviésemos que realizar este mismo script con Java !
Limpieza BD
import groovy.sql.Sql; import java.sql.*; //Se establece una conexión JDBC a la BD def con = Sql.newInstance("jdbc:h2:tcp://localhost/~/demo-jwt", "sa","","org.h2.Driver"); // Se ejecuta el comando SQL con.execute("DELETE FROM USUARIO WHERE USERNAME = 'daenerys'") // Se cierra la conexión con.close()
7. Conclusiones
Aunque una parte de las validaciones desarrolladas se pueden realizar utilizando directamente los formularios de SoapUI (puede que haga falta la versión de pago), hemos visto que con Groovy podemos realizar dichas validaciones de una forma muy simple. Groovy permite acceder a todo el ecosistema Java e incorpora funcionalidades que simplifican el desarrollo de los scripts.
Los test funcionales son una pequeña parte de los test a realizar e intentan reproducir la interacción con el usuario. Tened en cuenta que son frágiles en la medida que cualquier cambio externo (cambio en la password del usuario, modificación en la base de datos…etc.) rompe dicho test pero son muy útiles para verificar que todas las piezas encajan. Además, con el plugin para Maven podéis incorporar estos test al ciclo de vida de Maven para que se ejecuten en el momento y entorno adecuado.
Espero que os sirva e incentive el uso de test en vuestros desarrollos.
8. Referencias
- Código fuente del API REST.
- Código fuente del proyecto SoapUI.
- Terminología en la comunidad TDD.
- Documentación sobre SoapUI.
- Documentación sobre Groovy.
- Documentación sobre H2.
- Introducción SoapUI.
- Integración SoapUI con Maven