Algunos tipos de tests en el desarrollo de software

24 de Mayo de 2023 · 8 min de lectura

Bug in software

En la mayoría de tipos de industria es necesario el uso de algún tipo de testeo para garantizar que el producto o servicio resultante cumpla lo que necesita el usuario final o unos determinados requerimientos de calidad. Esto mismo ocurre con el desarrollo de software.

A continuación se enunciarán algunos tipos de tests que se deberían de tener en cuenta en el desarrollo de software, junto a algunos ejemplos hechos en Python y Django.

Test unitario (Unit test)

Los tests unitarios evalúan conceptos y componentes del proyecto de manera aislada. Esto supone depender lo mínimo posible de módulos de terceros, o de elementos del propio proyecto que no se necesiten estrictamente para la correcta comprobación. En relación al manejo de las dependencias, es interesante entender los conceptos de stubbed or mocked. De esta manera se podrá revisar aisladamente si cada funcionalidad testeada, funciona correctamente o no.

Ejemplo:

En el siguiente caso se tiene un modelo con un método que principalmente crea una instancia House con unos parámetros determinados, también está llamando a una tarea Celery.

class User (models.Model):
 def create_house(self, name=default):
  House.objects.create(user=self, name)
  create_room.delay()

Por tanto, para testear este método hay que comprobar que exista una instancia House con dichas características. Luego, hay que mockear la tarea Celery y asegurarse de que se está llamando. En la documentación oficial de unittest, se explica la manera de mockear objetos en Python.

from unittest.mock import patch
 @pytest.mark.django_db
 class TestUser:
  @patch("myAppName.myModuleName.myClassName.create_room.delay")
  def test_create_house(self, mock_create_room user_factory):

   #### Llamar al método a testear de la fixture user_factory.
   user_factory.create_house()

   #### Asegurarse de que se ha llamado al objeto mockeado.
   mock_create_room.assert_called_once()

   #### Comprobar la funcionalidad del método a testear.
   assert House.objects.filter(user=user_factory, name=default) is not None

Test de integración (Integration test)

Este tipo de tests comprueba que determinados elementos del proyecto que interactúan entre sí funcionan correctamente, como podría ser probar que funcione un endpoint, la integración del proyecto a una base de datos o a una API externa, etc.

Ejemplo:

En este ejemplo se busca testear una API en Django, concretamente un endpoint que está disponible. Se ha de verificar tanto el estado de la respuesta como el contenido que se devuelve.

En el ejemplo se usan una serie de fixtures: una para obtener un objeto APIClient (propio de DRF) y así ser capaces de hacer una petición “GET” al endpoint que devuelve la lista de casas relacionadas al usuario que ha hecho la petición, luego otra para disponer de un usuario con al menos tres instancias “House” relacionadas.

def test_user_houses(self, api_client_factory, user_with_houses_factory):
 url = reverse("api:user:houses")
 response = api_client_factory.get(url)
 assert response.status_code == HTTP_200_OK
 assert len(response.json()) == 3

¿Por qué este ejemplo es una prueba de integración?

Porque para comprobar este caso, es necesario de varios componentes del proyecto que conforman el proceso de respuesta del endpoint que se ha usado, desde lo más complejo, como modelos, vistas, serializadores, a lo más simple, como urls, routers, configuración general del proyecto, etc.

Un tipo de test de integración: Prueba de humo (Smoke test)

El nombre de este tipo de tests es objeto de una analogía originaria en el mundo de la electrónica. Esto es porque cuando conectas un circuito electrónico a la corriente eléctrica y ves que empieza a echar humo, sabes que no va a funcionar correctamente.

En el caso del desarrollo de software, basta con llevar a cabo pruebas que revisen de manera general los componentes o funcionalidades más importantes y revisar si están operativas. Su creación suele suponer un gasto menor en recursos y tiempo en comparación a otros test.

Es común su uso en determinados procesos, donde para llevar a cabo los tests funcionales se requiere que hayan pasado satisfactoriamente los tests de humo. Así se demuestra que no hay funcionalidades inoperativas y que por tanto es posible llevar a cabo los tests funcionales. Un ejemplo de operativa de este tipo sería la siguiente:

Ejemplo:

El ejemplo anterior de tipo de test de integración, se podría considerar un ejemplo de smoke test, ya que solo comprueba que el endpoint está operativo. Posiblemente no sería necesario revisar el número de “Houses” que están relacionadas al usuario, ya que solo bastaría con comprobar que el endpoint devuelve un estatus 200 para saber si el endpoint está operativo. Aunque esto último depende de lo que pueda acordar el equipo, no es una definición exacta.

Tests de rendimiento (Performance tests)

Estos revisan el rendimiento del sistema frente a una carga específica de trabajo. De entre varios aspectos, principalmente se busca analizar la capacidad y comportamiento de los elementos evaluados frente a una situación actual o futura. Hay varias herramientas disponibles para llevarlos a cabo: Locust, k6.io, JMeter, etc. A continuación se procederá a explicar brevemente algunos tests dentro de esta categoría.

Test de carga (Load test)

El objetivo del test de carga es analizar la capacidad de rendimiento y estabilidad del proyecto bajo diferentes niveles de carga que pueden ser similares a situaciones reales. Consiste en ir añadiendo carga al sistema hasta el máximo que pueda manejar mientras se monitorea.

Ejemplo:

Un sistema de mensajes tiene un máximo de 2000 usuarios usando alguna funcionalidad del sistema. Un test de ejemplo podría ser el de llevar a cabo 15 transacciones por usuario en una hora, sometiendo al sistema a un total de 30000 transacciones/hora.

Tipo de gráfica:

Test de estrés (Stress test)

En este caso se busca encontrar cuellos de botella y encontrar los límites del sistema. Consiste en ir subiendo la carga hasta que el sistema no sea capaz de dar el servicio con los recursos que se le ha proveído, tras pasar los límites, revisar poco a poco la capacidad de recuperación del sistema.

Ejemplo:

En una aplicación e-commerce, se ha de comprobar el límite al que puede llegar, debido a que siempre hay temporadas donde hay mucho más tráfico y hay que estar preparados para dichas situaciones. Después de alcanzar el límite del sistema y no dar un óptimo servicio al usuario, es importante gestionar la situación de manera adecuada. Se puede informar a través de un modal que la web tiene un gran número de peticiones y que puede esperar unos minutos hasta que el sistema se recupere y pueda aceptar la petición.

Tipo de gráfica:

Test de resistencia (Endurance test)

Consiste en mantener un considerable tamaño de carga en el sistema durante un determinado tiempo y monitorizar el sistema. Principalmente revisa la existencia de “memory leaks”, monitorea la capacidad de carga a lo largo de una gran cantidad de tiempo, revisa si hay degradación del rendimiento, etc.

Ejemplo:

Dado un sistema que se sabe que puede manejar una gran cantidad de carga durante 2 horas, es necesario revisar si es capaz de soportar la misma o una mayor cantidad en caso de que el tiempo aumente a 4 o más horas, ya que debido a un insuficiente espacio de memoria o de número de recursos, puede darse que el sistema colapse o que empeore drásticamente su rendimiento.

Tipo de gráfica:

Test de volumen (Volume test)

En este caso, se enfoca en monitorizar la capacidad que tiene la base de datos frente al constante incremento del volumen de carga. Es similar al test de carga, solo que en vez de enfocarse en cómo se comporta el sistema frente al usuario, lo hace en torno al tratamiento de los datos. Por tanto, monitoriza la BD en relación al manejo de grandes volúmenes de datos, revisando la integridad de la memoria, el rendimiento, los límites, riesgos potenciales, etc.

Ejemplo:

Si en un e-commerce se almacena un determinado volumen de datos por cada año, en 3 años se prevé que el volumen total sea x4 del actual, luego en 5 años se prevé que sea de x7 veces del actual. Por ello se ha de ir midiendo la capacidad que se tiene para evitar futuros problemas y asegurarse de que el sistema sea capaz de soportar determinada cantidad de datos a lo largo del tiempo.

Test de escalabilidad (Scalability test)

A diferencia de los tests de carga, los tests de escalabilidad miden la capacidad mínima y máxima de carga de todos los niveles en su conjunto (software, servidor, BD, etc). Similarmente como en los tests de volumen, se tiene que medir la capacidad que tiene el sistema frente al constante aumento de carga. En relación a los resultados obtenidos del test, el equipo ha de llevar a cabo acciones para que el sistema tenga la capacidad de manejar la futura capacidad de carga.

Ejemplo:

Se da la situación de que se espera una temporada que tenga un mínimo de 20.000 peticiones/minuto en una determinada funcionalidad. Si el test de escalabilidad indica un máximo de 10.000 peticiones/minuto, el equipo ha de trabajar para que el sistema sea capaz de atender el requerido número de peticiones.

Test de picos (Spike test)

Consiste en someter al sistema a un repentino aumento o disminución de carga. De manera que se pueden obtener conclusiones cuando el tráfico es inestable. Se ha de analizar la manera que tiene el sistema de recuperarse, evaluar el rendimiento (ya sea en mínimos o máximos), también se puede detectar la carga máxima que tiene el sistema, etc.

Tipo de gráfica:

Ejemplo:

En las e-commerce es común tener un tráfico repentinamente alto en los Black Fridays. En esos casos el tráfico se suele asemejar a picos altos y, por tanto, se tiene que valorar esa situación previamente para evitar comportamientos no deseados en el sistema.

Conclusion

Se ha dado una visión general de algunos de los tests más importantes y que pueden ser útiles en el desarrollo de software. Aparte de los tipos de tests explicados, hay innumerables más a usar en otras situaciones más concretas.

Comparte este artículo
Artículos recientes