Translate

Mostrando las entradas con la etiqueta Locust. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Locust. Mostrar todas las entradas

jueves, 8 de octubre de 2026

Locust desde cero: nuestro primer test de carga


Cuando desarrollamos una API REST normalmente hacemos tests para comprobar que funciona correctamente.


Por ejemplo:

¿El GET devuelve los productos?

¿El POST crea correctamente un producto?

¿El DELETE elimina el recurso?


Pero hay otra pregunta importante: ¿Qué pasa si 100 usuarios utilizan nuestra API al mismo tiempo?

Ahí entran las pruebas de carga.

En este post vamos a conocer Locust y hacer nuestro primer test de carga sobre una API REST.

No vamos a construir una API complicada. Vamos a suponer que ya tenemos una API CRUD de productos y nos vamos a concentrar exclusivamente en probarla.


¿Qué es Locust? Locust es una herramienta para realizar pruebas de carga.

Una de sus características más interesantes es que los escenarios de prueba se escriben en Python.

En lugar de tener que configurar un montón de archivos, podemos describir el comportamiento de nuestros usuarios directamente mediante código.


La idea es sencilla: Locust crea usuarios virtuales que realizan requests contra nuestra aplicación y nos permite observar cómo responde el sistema bajo carga.


Para el ejemplo vamos a utilizar una API CRUD para administrar productos.

Un producto tiene:

Product

 ├── id

 ├── name

 ├── price

 └── stock


Y la API expone las operaciones habituales:


GET    /products

GET    /products/{id}

POST   /products

PUT    /products/{id}

DELETE /products/{id}


Por ejemplo:


GET /products


podría devolver:

[

  {

    "id": 1,

    "name": "Notebook",

    "price": 1200,

    "stock": 10

  },

  {

    "id": 2,

    "name": "Mouse",

    "price": 30,

    "stock": 50

  }

]


Para nuestro primer test solamente vamos a utilizar:

GET /products


Locust es una aplicación Python.

Podemos instalarlo con:

pip install locust


Comprobamos que quedó instalado:

locust --version


Ahora creemos un archivo:

locustfile.py


Este archivo contendrá nuestro escenario de prueba.

Comencemos con algo muy simple:


from locust import HttpUser, task, between


class ProductUser(HttpUser):


    wait_time = between(1, 3)


    @task

    def get_products(self):

        self.client.get("/products")


Aunque son pocas líneas, acá ya estamos describiendo un usuario virtual.

Veamos qué significa cada parte.


class ProductUser(HttpUser):


HttpUser representa un usuario que realizará requests HTTP.

Cuando Locust ejecute nuestra prueba, creará usuarios virtuales basándose en esta clase.


Tenemos:

wait_time = between(1, 3)


Esto indica que el usuario esperará entre 1 y 3 segundos entre una tarea y otra.

Es importante porque normalmente un usuario real no realiza requests continuamente sin esperar.


Ahora tenemos:


@task

def get_products(self):

    self.client.get("/products")


La anotación @task indica que este método representa una acción que nuestro usuario puede realizar.

En este caso, la acción es: consultar productos


Y finalmente:

self.client.get("/products")


realiza el request HTTP.

Es decir, nuestro escenario completo básicamente dice: "Soy un usuario que consulta la lista de productos y espero entre 1 y 3 segundos antes de volver a hacerlo."


Supongamos que nuestra API está corriendo en: http://localhost:8080

Podemos iniciar Locust con:


locust -f locustfile.py --host http://localhost:8080


Locust levantará su interfaz web.

Por defecto podremos acceder a: http://localhost:8089

Desde ahí podemos configurar nuestra prueba.


Por ejemplo:

Number of users: 10

Spawn rate:      2


Estamos diciendo: Queremos simular 10 usuarios y crear 2 usuarios nuevos por segundo hasta llegar a los 10.

Cada uno de esos usuarios ejecutará el comportamiento que definimos en ProductUser.


Locust nos permite hacer este tipo de preguntas:

  • ¿Cuánto tarda?
  • ¿Cuántos requests por segundo soporta?
  • ¿Cuántos requests fallan?
  • ¿Qué ocurre cuando aumentamos la cantidad de usuarios?
  • ¿Cuánto tarda el 95% de los requests?


Por ejemplo, podríamos obtener resultados similares a:


GET /products


Requests:        10.000

Failures:             0

Average:            42 ms

Median:             35 ms

95%:                80 ms

99%:               120 ms

Requests/sec:       85


El dato que más llama la atención puede ser el percentil 95.


Si tenemos:

95% → 80 ms


significa que el 95% de los requests respondió en 80 ms o menos.


El 5% restante tardó más.

Esto suele ser mucho más útil que mirar únicamente el promedio.

Pero una aplicación real no tiene usuarios que solamente ejecutan un GET.


Un usuario podría:


GET /products

      ↓

GET /products/10

      ↓

POST /products

      ↓

GET /products


Y probablemente algunas operaciones ocurran con mayor frecuencia que otras.


Por ejemplo:

80% → GET /products

15% → GET /products/{id}

 5% → POST /products


Locust nos permite modelar ese comportamiento mediante diferentes @task.

Pero eso lo dejamos para el próximo paso.


La idea fundamental que quiero llevarme de este primer ejemplo es muy simple: Locust no prueba solamente endpoints.


Podemos utilizar Python para describir el comportamiento de usuarios virtuales y luego ejecutar ese comportamiento contra nuestra aplicación bajo diferentes niveles de carga.


Dejo link: https://locust.io/