Mejorar el mantenimiento de tu suite de regresión

Compartir esta publicación

Compartir en facebook
Compartir en linkedin
Compartir en twitter
Compartir en email

Los informes de ejecución de las pruebas de regresión demuestran su importancia y el valor que aportan al producto, más aún si están automatizadas y se ejecutan continuamente. Un plan de regresión se compone de todas las pruebas destinadas a validar las implementaciones y los flujos de negocio de forma continua, a medida que la aplicación crezca también lo hará el plan de regresión, mientras que otros planes como smoke que comprueba los principales flujos de negocio se mantendrán sin cambios mientras existan estos flujos.

Para tener un correcto proceso a nivel de pruebas, se deben realizar primero las correspondientes pruebas de las funcionalidades a nivel de código a través de Pruebas Unitarias y de API tests, mientras que las pruebas de negocio (smoke, regresión) se realizarán en una fase posterior para seguir aumentando el valor de las pruebas realizadas sobre la aplicación.

Sin embargo, en muchas ocasiones el alto valor de las pruebas de regresión viene acompañado de un alto coste en tiempo de mantenimiento. Toda la automatización de QA se ha enfrentado a muchas horas y días de trabajo escarbando en los logs de las ejecuciones de las pruebas e investigando el código intentando averiguar si el error de la prueba se debe a un posible bug, a un error de programación o a falsos negativos y positivos. En este artículo desarrollamos las principales pautas para tratar de corregir las causas que dificultan el mantenimiento de nuestro plan de regresión.

(Re)considerar la estrategia de automatización de pruebas

Una de las principales razones por las que generalmente nos cuesta mantener la regresión es porque nuestras pruebas tienden a realizar demasiadas acciones y comprobaciones al mismo tiempo que tienden a recorrer los flujos de usuario de nuestra aplicación, muchas de ellas innecesariamente. Esta clase de pruebas llamadas end-to-end tests tienden a ser por definición difíciles de mantener, lentas y frágiles. Representan sobre todo un agujero negro de tiempo en el mantenimiento de la regresión.a

Minimizar el número de pruebas e2e y maximizar el número de pruebas funcionales debería ser siempre el primer punto de partida de cualquier suite de regresión.

Los <a href=»https://en.wikipedia.org/wiki/Functional_testing»>Functional tests</a> (feature tests) son el antónimo de e2e, nos permiten verificar que una implementación o característica de la aplicación funciona, simple y llanamente. Dado que una aplicación está llena de cientos de pequeñas implementaciones, probar cada una de ellas por separado siempre garantizará la cobertura, el mantenimiento y los resultados fiables sobre el estado de la aplicación.

Consideremos el siguiente ejemplo:

Escenario: El usuario descarga una factura

Given que el usuario entra en la aplicación

And el usuario crea una nueva factura

And el usuario abre la factura creada

When el usuario pulsa la opción de descarga

Then, se descarga la factura

Este es un ejemplo de una «prueba de fallos». El objetivo de esta prueba es comprobar la funcionalidad de ‘Descarga’ de la aplicación, para lo cual es necesaria una factura como condición previa. ¿Es necesario crear una nueva factura para descargarla? ¿Qué ocurre si la implementación de crear factura falla? En este caso, no sólo fallaría otra posible prueba de crear una factura, sino que esta prueba fallaría específicamente porque no se ha podido crear la factura, cuando en este caso crear la factura no es el objetivo de la prueba sino descargarla. Debemos intentar reducir al máximo todas aquellas precondiciones que sean innecesarias para lo que queremos comprobar.

Por lo tanto, el ejemplo anterior podría ajustarse de la siguiente manera:

Escenario: El usuario descarga una factura

Given que el usuario entra en la aplicación

And el usuario abre la factura ‘X1023’

When el usuario pulsa la opción de descarga

Then, se descarga la factura

Dado que en nuestro hipotético escenario sigue siendo necesario abrir la factura para descargarla, debemos abrirla antes de pulsar la opción, pero en este caso la factura ya está en el sistema en el que ejecutamos la prueba, por lo que minimizamos la posibilidad de que una condición previa provoque un fallo en nuestra prueba.

Apoya tus pruebas con llamadas a la API en su beneficio

Otra posibilidad que tiende a olvidarse es la de utilizar llamadas a la API para apoyar nuestros tests de UI, en otras ocasiones directamente se evitan bajo el argumento de «utilizar tests de UI fieles a la experiencia de usuario». Obviamente las pruebas de UI deben interactuar en la medida de lo posible tal y como lo haría un usuario real, pero hay que tener cuidado a la hora de manejar las precondiciones ya que son una fuente potencial de errores no deseados que comprometen la validación real de nuestra prueba. Además, en nuestra suite de regresión ya habría pruebas cuya validación final ya comprobará (fiel a la experiencia del usuario) lo que serían precondiciones en otras pruebas.

Apoyarnos en las llamadas a la API para nuestros tests de UI no sólo hará que la ejecución de los mismos sea mucho más rápida, sino que además no estaremos alterando el comportamiento de la aplicación, ya que detrás de cada formulario que interactúe con la parte del Backend siempre se estará haciendo una llamada desde un endpoint pasándole cierta información. Podemos utilizar directamente el mismo endpoint enviándole la información que enviaríamos a través del formulario.

Supongamos el siguiente escenario: Para verificar la cuenta de un usuario en el sistema, la cuenta debe ser nueva, por lo que no podemos tener una cuenta de usuario almacenada en el sistema como en el ejemplo anterior.

Escenario: El usuario verifica una cuenta creada

Given el usuario abre el formulario de inscripción

And el usuario envía el formulario de inscripción

And el usuario entra en la aplicación con el usuario creado

When el usuario verifica la cuenta

Then el usuario ve un mensaje de verificación completada

Para crear una nueva cuenta, el usuario debe acceder al formulario de registro, rellenar todos los campos del formulario y enviar la información para crear el nuevo usuario. Conociendo la información que enviamos a través del endpoint, podemos definir el test de la siguiente manera:

Escenario: El usuario verifica una cuenta creada

Given que se crea una cuenta aleatoria con los siguientes datos

| field | value |

| firstname | John |

| lastname | Doe |

| email | [email protected] |

| password | Test123456 |

And el usuario entra en la aplicación con el usuario creado

When el usuario verifica la cuenta

Then el usuario ve un mensaje de verificación completada

El endpoint utilizado en el paso Given llamará al mismo endpoint que se utiliza en el formulario de registro, y la información utilizada es la misma que se enviaría a través del formulario. Al final del paso se obtendría el correo electrónico generado con el que el usuario podría acceder al sistema.

Aunque la implementación de esta llamada a la API en el framework de automatización puede parecer compleja a primera vista, los beneficios de utilizar la API de la aplicación para las pruebas de UI en soporte superan ampliamente la inversión inicial de preparar el framework con esta capacidad. Además, por otro lado, también permite la posibilidad de realizar pruebas de backend en el mismo framework, algo que sin duda es realmente beneficioso para garantizar el correcto funcionamiento de la API del sistema.

Habla con los desarrolladores para una estrategia de localización coherente: ID sobre Xpath

Sin duda, la comunicación entre el equipo de control de calidad y el de desarrollo es clave a la hora de conseguir pruebas fiables y robustas. Entre las diferentes formas de seleccionar los elementos de la interfaz de usuario de una aplicación, destacan sobre todo las siguientes:

  • ID
  • Xpath 

Los IDs son identificadores únicos de los elementos UI de la aplicación. Si se definen correctamente, los ID son nombres inmutables, fácilmente accesibles y utilizados por las principales herramientas de prueba de software, como Selenium. En cambio, requieren una definición y un mantenimiento explícitos por parte del equipo de desarrollo.

Xpath (XML Path Language) es un lenguaje que permite construir expresiones que recorren y procesan un documento XML. Los elementos del árbol DOM de una aplicación se construyen como un documento XML y herramientas como Selenium nos permiten seleccionar los elementos de la aplicación con esa estructura, sin necesidad de la intervención explícita del equipo de desarrollo y permitiéndonos automatizar rápidamente la prueba a través de esos elementos.

Sin embargo, el uso de Xpath también tiene sus inconvenientes. Mirando el ejemplo de abajo:

<form>
   <div>
      <span>Email</span>
      <input type="text">
   </div>
   <div>
      <span>Password</span>
      <input type="password">
   </div>
   <div>
      <input type="checkbox"><span>I agree to the <a href="https://www.test.com/terms" target="_blank">privacy policy</a>of this website.</span>
   <div>
   <div>
      <input type="checkbox"><span>I want to subscribe to the newsletter.</span>
   <div>
      <button type="submit">Sign up</button>
</form>

<form>
   <div>
      <span>Email</span>
      <input type="text">
   </div>
   <div>
      <span>Password</span>
      <input type="password">
   </div>
   <div>
      <input type="checkbox"><span>I agree to the <a href="https://www.test.com/terms" target="_blank">privacy policy</a>of this website.</span>
   <div>
   <div>
      <input type="checkbox"><span>I want to subscribe to the newsletter.</span>
   <div>
      <button type="submit">Sign up</button>
</form>

Teniendo esta estructura, nuestros selectores podrían obtenerse a través de XPath de esta manera:

@FindBy(xpath = "//span[text() = 'Email']/input")
 public static WebElement email;

@FindBy(xpath = "//span[text() = 'Password']/input")
 public static WebElement password;

@FindBy(xpath = "//input[@type = 'checkbox'][last() - 1]")
 public static WebElement termsCheckbox;

@FindBy(xpath = "//input[@type = 'checkbox'][last()]")
 public static WebElement subsCheckbox;

@FindBy(xpath = "//button[text() = 'Sign up']")
 public static WebElement submitButton;

Aunque los selectores son funcionales, los localizadores pueden ser fácilmente «rotos» por cualquier cambio introducido en la estructura del formulario, ya sea cambiando los componentes que dan lugar a la estructura span > input, añadiendo nuevos elementos como casillas de verificación o cambiando el texto del formulario en el ‘front’ de la app. Cualquier cambio hará que la prueba falle y añadirá tiempo de mantenimiento ajustando los selectores.

<form>
   <div>
      <span>Email</span>
      <input type="text" id="email">
   </div>
   <div>
      <span>Password</span>
      <input type="password" id="password">
   </div>
   <div>
      <input type="checkbox" id="terms"><span>I agree to the <a href="https://www.test.com/terms" target="_blank">privacy policy</a>of this website.</span>
   <div>
   <div>
      <input type="checkbox" id="newsletter"><span>I want to subscribe to the newsletter.</span>
   <div>
      <button type="submit" id="submit">Sign up</button>
</form>

<form>
   <div>
      <span>Email</span>
      <input type="text" id="email">
   </div>
   <div>
      <span>Password</span>
      <input type="password" id="password">
   </div>
   <div>
      <input type="checkbox" id="terms"><span>I agree to the <a href="https://www.test.com/terms" target="_blank">privacy policy</a>of this website.</span>
   <div>
   <div>
      <input type="checkbox" id="newsletter"><span>I want to subscribe to the newsletter.</span>
   <div>
      <button type="submit" id="submit">Sign up</button>
</form>
@FindBy(id = "email")
 public static WebElement email;

@FindBy(id = "password")
 public static WebElement password;

@FindBy(id = "terms")
 public static WebElement termsCheckbox;

@FindBy(id = "newsletter")
 public static WebElement subsCheckbox;

@FindBy(id = "submit")
 public static WebElement submitButton;

Gracias a los identificadores introducidos por el equipo de desarrollo, los selectores son ahora mucho más robustos y sólidos, inquebrantables ante cualquier cambio en función del diseño, ya sea editando los elementos del formulario o añadiendo otros nuevos.

Debemos pedir al equipo de desarrollo que defina identificadores (ID) para todos aquellos elementos con los que interactuamos en nuestras pruebas.

Utiliza un entorno y un conjunto de datos específicos para realizar sus pruebas

Por último, pero no por ello menos importante, cabe destacar las enormes ventajas de utilizar un entorno dedicado a las ejecuciones de pruebas de regresión, además de trabajar con un conjunto de datos específico para ellas. Trabajar con estos elementos proporciona enormes beneficios:

Entorno dedicado

  • Consistent performances when testing in a controlled environment.
  • Un entorno dedicado le permite aislar el código y verificar el comportamiento de la aplicación mientras se asegura de que ninguna otra actividad o fuente interfiera con los resultados.
  • Posibilidad de representar fielmente un entorno de producción para realizar las pruebas, lo que proporciona seguridad sobre la realidad de los resultados obtenidos.

Dataset

  • Control de los datos utilizados en las pruebas para cada ejecución.
  • Disponer de un conjunto de datos evita que las pruebas tengan que crear datos para ejecutar sus validaciones, lo que reduce la posibilidad de que los resultados se alteren en caso de error durante la creación de los datos de la prueba.

Estos elementos constituyen el punto de partida sobre el que debe ejecutarse cualquier conjunto de pruebas de regresión. Además, tanto el entorno como el conjunto de datos pueden desplegarse mediante tareas automatizadas en servicios como Jenkins o Gitlab, lo que permitiría tener un estado «limpio» antes de cada ejecución de las pruebas de regresión.

Conclusiones

El mantenimiento de la regresión es esencial para verificar el estado del producto, sin embargo es una tarea que fácilmente puede ser muy costosa en términos de tiempo dedicado al QA, reduciendo la capacidad en otras tareas como la definición/refinamiento de nuevas pruebas o la automatización. de nuevas pruebas que a su vez se añadirían al plan de regresión. Por ello, debemos llevar a cabo buenas prácticas que nos ayuden a limitar el tiempo invertido en el mantenimiento de la regresión.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Suscríbete a nuestro boletín de noticias

Recibe actualizaciones de los últimos descubrimientos tecnológicos

Acerca de Apiumhub

Apiumhub reúne a una comunidad de desarrolladores y arquitectos de software para ayudarte a transformar tu idea en un producto potente y escalable. Nuestro Tech Hub se especializa en Arquitectura de Software, Desarrollo Web & Desarrollo de Aplicaciones Móviles. Aquí compartimos con usted consejos de la industria & mejores prácticas, basadas en nuestra experiencia.

Posts populares
Obtén nuestro Libro: Software Architecture Metrics

Global Software Architecture Summit '22

Reserva tu plaza!

Reserva

¿Tienes un proyecto desafiante?

Podemos trabajar juntos

Secured By miniOrange