Tipo de pruebas de software ¿De frontend o de backend?
Artículo de Meritxell Rodríguez
¿Te has preguntado alguna vez si en lugar de simular las acciones que haría el usuario para realizar los test se hiciesen las llamadas a la API directamente para analizar la respuesta?
Si es así, en las siguientes líneas intentaremos mostrarte las ventajas e inconvenientes de ambos casos según nuestra experiencia.
¿Qué son las pruebas funcionales de Frontend?
Son test que se hacen realizando las mismas acciones que haría el usuario, pero de forma automática. Comprueban los efectos que tienen a nivel visual y funcional. También se pueden hacer para comprobar si el proceso que tiene que seguir el usuario es intuitivo.
public void loginAs(String user, String password) {
loginPage.usernameTextbox.sendKeys(user);
loginPage.passwordTextbox.sendKeys(password);
loginPage.loginButton.click();
}
¿Qué són las pruebas de API?
En este tipo de test se realizan las mismas acciones que se llevan a cabo a nivel de frontend pero contra la API directamente, enviando la llamada correspondiente y tratando la respuesta.
@Step("Authenticate")
public void authenticateAs(String id, String secret) {
/* set session variable used for json's template placeholders */
Serenity.getCurrentSession().put("clientId", id);
Serenity.getCurrentSession().put("clientSecret", secret);
given()
.body(PebbleTemplateMethods.evaluate("testdata/authenticate.json", extractAuthenticateData()))
.when()
.post(ScenarioHooks.authUrl);
}
Comparando las pruebas funcionales de frontend y backend
Uno de los mayores pros a favor de los tests de API es la velocidad de ejecución de los test que es notablemente más rápida dado que no tenemos que esperar los tiempos de carga de los elementos de la página web. Sin embargo, a veces es necesario esperar una respuesta del servidor que puede tardar segundos. En ese caso al utilizar Serenity tuvimos que añadir un await().untilAsserted()
, lo que supuso tener que importar una librería extra.
Para poder realizar los test de la API de forma satisfactoria, es un requisito tener una muy buena documentación con todas las llamadas que se pueden realizar, las configuraciones y los parámetros necesarios. Este no es el caso de los test de frontend, ya que por intuición o por lógica se puede saber la ruta a seguir sin la ayuda de ninguna documentación.
Tests de API usando Postman
Con esto en mente, nos dimos cuenta de que los test de API eran mucho más rápidos de programar, ya que no hay que buscar buenos identificadores para los elementos concretos de la página con los que se quiere interactuar. Además, realizar acciones en el frontend suele suponer más de una interacción con la página, lo que se puede evitar haciendo la llamada directamente.
Esto nos lleva a no tener que preocuparnos de que los objetos estén bien identificados para que los test sean más robustos y no se vean afectados por las actualizaciones de posición de la página.
Por ejemplo, en este caso el identificador depende de la posición:
@FindBy(css = "#root > section > div > div.core-section.col-12.col-lg-9 > div.post_list > div:nth-child(1) > div > a")
WebElementFacade previewImage;
Si en una nueva versión de la página el objeto sigue teniendo la misma funcionalidad pero diferente ubicación, el test fallaría, generando un falso negativo, por lo que el código sería más inestable y difícil de mantener. Sin embargo, una llamada a la API no suele cambiar, por lo que no tendremos que actualizar nuestro código con frecuencia.
Un aspecto que también nos parece una ventaja de los test de API es que al ejecutarlos no es necesario tener el navegador abierto, cosa que no se puede hacer con algunos de los frameworks existentes, a no ser que tengan la opción headless, en cuyo caso tendríamos un empate entre ambas opciones.
Una desventaja de estos test es que no se pueden simular el 100% de las interacciones que haría el usuario contra la página ya que hay veces que no todas las acciones generan una petición a la API. Por ejemplo, en el proceso de compra, en los pasos de rellenar los datos y seleccionar el método de envío, no se suele hacer una llamada a la API hasta que se completa todo el proceso.
Tests de frontend usando Cypress
Otra desventaja a tener en cuenta es que cuando no estás probando la interacción con el frontend estás confiando en que las llamadas a la API se disparan correctamente cuando se realizan las acciones específicas. Esto es una gran desventaja para nosotros porque la API puede funcionar perfectamente, pero si el botón que debería activarla no funciona como se espera, no detectaríamos el error.
Esto nos lleva al siguiente contrapunto, que tiene que ver con las comprobaciones. En los test de API son más limitadas ya que a veces una acción provoca múltiples cambios en el frontend que en la API sólo se muestran con un cambio de parámetro. Esto se puede resolver de dos maneras: la primera sería simplemente comprobar el cambio de parámetro en la respuesta y esperar que esto afecte correctamente al frontend y la segunda sería añadir alguna comprobación en el propio frontend.
Por ejemplo en este caso:
$ ~ http http://localhost:4000/tags
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 352
Content-Type: application/json; charset=utf-8
Date: Wed, 29 Jul 2020 14:03:28 GMT
ETag: W/"160-maNWQR6ptXu2EC2MrZrPjhs9CL4"
X-Powered-By: Express
[
{
"Tag": "Ruby",
"Usages": 3
},
{
"Tag": "Javascript",
"Usages": 5
},
{
"Tag": "Sonar",
"Usages": 3
}
]
Con un test hacia el backend no podemos ver cómo afecta visualmente el parámetro Usages
en el frontend.
Otro punto que nos gustaría destacar es que a nivel de código el cuerpo de las llamadas a la API suele ser algo difícil de reutilizar, ya que cada acción tiene unas características determinadas. Esto significa que se necesita un archivo casi para cada acción y a veces para la misma acción pero con diferentes escenarios. De este modo almacenamos muchos archivos similares, mientras que con el frontend necesitaríamos simplemente hacer clic en diferentes lugares. En su momento intentamos resolver este problema usando la librería Pebble pero creemos que hizo el código más ilegible y difícil de mantener.
Y por último, a nivel de informes nos dimos cuenta de que Serenity sólo mostraba los nombres de los endpoints en los pasos. Lo que en nuestro caso, al usar json-rpc, no era muy informativo porque todos los endpoints eran iguales, así que tuvimos que añadir más código para mostrar algunos títulos específicos en los pasos del informe. Por otro lado, para los test del frontend, las capturas de pantalla se guardan en el informe justo en el momento de realizar la acción, por lo que si hay un error de carga o visual, se puede detectar rápidamente.
Conclusión: ¿Qué tipos de pruebas escojo?
Para nosotros, la conclusión sería que lo mejor es mezclar las dos opciones. Lo que haríamos la primera vez que tengamos que probar una interacción con la web sería probar las interacciones con el frontend. En los siguientes test, como ya hemos comprobado que el componente envía las llamadas correctamente a la API, enviaremos las llamadas directamente sin pasar por el frontend para ganar velocidad sin perder fiabilidad.
Por ejemplo, la primera vez que se hace el login se debe comprobar desde el frontend, pero una vez probada esa funcionalidad, las siguientes veces se puede hacer el login directamente vía API, siendo así el acceso a la página mucho más rápido.
Es cierto que al principio puede parecer que el código se vuelve más complejo al tener que implementar la misma funcionalidad para la web y para la API pero esto se puede remediar con una buena organización del código.
También queremos destacar que disponer de buena documentación para realizar los test de la API ayudará al mantenimiento y posterior desarrollo del proyecto.
Finalmente, habiendo comparado las dos opciones creemos que ambas tienen sus pros y sus contras por lo que dependerá de los requerimientos u objetivos del proyecto elegir una u otra o, como hicimos en nuestro caso, elegir una mezcla de ambas.
Si aún así no sabes cuál de las dos opciones es mejor para ti, si las pruebas funcionales o las pruebas de API escríbenos un mensaje y estaremos encantados de ayudarte a definir la mejor estrategia. Ponte en contacto con Redsauce