¿Qué es Apache JMeter?

Apache JMeter es una aplicación open-source basada en Java diseñada para pruebas de carga y medición del rendimiento de aplicaciones web. Originalmente creada para probar aplicaciones web, JMeter se ha expandido para cubrir una amplia variedad de protocolos incluyendo HTTP, HTTPS, SOAP, REST, FTP, JDBC, LDAP, JMS y SMTP.

JMeter es una de las herramientas de performance testing más utilizadas en la industria. Su popularidad se debe a que es gratuita, extensible mediante plugins y tiene una gran comunidad. Si trabajas en QA, casi con seguridad te encontrarás con JMeter en algún momento de tu carrera.

Arquitectura de JMeter

JMeter utiliza una estructura basada en árbol para organizar los planes de prueba. Comprender los componentes principales es esencial antes de crear tu primera prueba.

graph TD TP[Test Plan] --> TG1[Thread Group 1] TP --> TG2[Thread Group 2] TG1 --> S1[HTTP Sampler: Login] TG1 --> S2[HTTP Sampler: Explorar Productos] TG1 --> S3[HTTP Sampler: Agregar al Carrito] S1 --> A1[Response Assertion] S1 --> PP1[Regular Expression Extractor] TG1 --> T1[Constant Timer] TG1 --> L1[View Results Tree] TG1 --> L2[Summary Report] TG1 --> CE1[HTTP Cookie Manager] TG1 --> CE2[CSV Data Set Config]

Test Plan

El Test Plan es el elemento raíz. Contiene todos los elementos de tu prueba. Un plan de prueba define qué probar y cómo hacerlo. Puedes pensarlo como un contenedor para todo el escenario de prueba de carga.

Thread Groups

Un Thread Group es el punto de entrada de tu prueba. Controla:

  • Number of Threads (usuarios): Cuántos usuarios virtuales ejecutarán la prueba simultáneamente
  • Ramp-Up Period: Cuánto tiempo tarda JMeter en iniciar todos los hilos. Un ramp-up de 60 segundos con 100 hilos significa que JMeter inicia aproximadamente 1.67 usuarios por segundo
  • Loop Count: Cuántas veces cada hilo ejecuta el plan de prueba. Configúralo como “Infinite” para pruebas basadas en duración
  • Duration: Tiempo máximo de ejecución (útil con loops infinitos)

Samplers

Los Samplers le indican a JMeter que envíe solicitudes a un servidor. El más común es el HTTP Request Sampler, que envía solicitudes HTTP/HTTPS. Otros samplers incluyen JDBC Request (bases de datos), FTP Request y SMTP Sampler (correo electrónico).

Campos clave del HTTP Request Sampler:

  • Protocol: HTTP o HTTPS
  • Server Name or IP: El servidor destino
  • Port Number: Generalmente 80 (HTTP) o 443 (HTTPS)
  • Method: GET, POST, PUT, DELETE, etc.
  • Path: La ruta del endpoint (ej., /api/users)
  • Body Data: Cuerpo de la solicitud para POST/PUT

Listeners

Los Listeners recopilan y muestran los resultados de las pruebas. Los más comunes incluyen:

ListenerPropósito
View Results TreeVista detallada de cada solicitud/respuesta (solo para depuración)
Summary ReportTabla de estadísticas agregadas
Aggregate ReportEstadísticas con percentiles
Graph ResultsGráfico visual de tiempos de respuesta
Simple Data WriterGuarda resultados en archivo para análisis externo

Importante: View Results Tree consume mucha memoria. Desactívalo durante las pruebas de carga reales y úsalo solo para depuración con pocos hilos.

Assertions

Los Assertions verifican que las respuestas cumplen con criterios esperados. Si un assertion falla, JMeter marca el sampler como fallido.

  • Response Assertion: Verifica cuerpo, encabezados o código de estado de la respuesta
  • Duration Assertion: Falla si el tiempo de respuesta supera un umbral
  • Size Assertion: Valida el tamaño de la respuesta
  • JSON Assertion: Valida el contenido de respuestas JSON
  • XPath Assertion: Valida el contenido de respuestas XML

Timers

Los Timers agregan retrasos entre solicitudes para simular comportamiento realista de usuarios. Sin timers, JMeter envía solicitudes lo más rápido posible, lo cual no es realista.

  • Constant Timer: Retraso fijo entre solicitudes
  • Gaussian Random Timer: Retraso aleatorio con distribución normal
  • Uniform Random Timer: Retraso aleatorio dentro de un rango

Config Elements

Los Config Elements configuran valores predeterminados y variables para los samplers:

  • HTTP Cookie Manager: Maneja cookies automáticamente (esencial para aplicaciones con sesiones)
  • HTTP Header Manager: Agrega encabezados a todas las solicitudes
  • CSV Data Set Config: Lee datos de prueba desde archivos CSV para parametrización
  • HTTP Request Defaults: Establece valores predeterminados compartidos entre múltiples HTTP samplers

Grabación de Solicitudes HTTP

JMeter incluye un Test Script Recorder (anteriormente HTTP Proxy Server) que captura el tráfico del navegador y lo convierte en samplers de JMeter. Esta es la forma más rápida de crear un escenario de prueba realista.

Pasos para grabar:

  1. Agrega un Thread Group a tu Test Plan
  2. Agrega HTTP(S) Test Script Recorder bajo el Test Plan
  3. Configura el puerto (predeterminado: 8888)
  4. Configura tu navegador para usar localhost:8888 como proxy
  5. Haz clic en Start en el grabador
  6. Navega por tu aplicación en el navegador
  7. Detén el grabador — JMeter crea samplers para cada solicitud capturada

Después de grabar, limpia el script eliminando solicitudes innecesarias (recursos estáticos, llamadas de analytics) y agrega parametrización para valores dinámicos.

Parametrización

La parametrización reemplaza valores fijos con variables para que cada usuario virtual pueda usar datos diferentes. El enfoque más común usa CSV Data Set Config.

Crea un archivo CSV (users.csv):

username,password
user1,pass123
user2,pass456
user3,pass789

Agrega un elemento CSV Data Set Config con:

  • Filename: Ruta a tu archivo CSV
  • Variable Names: username,password
  • Delimiter: ,
  • Recycle on EOF: True (reinicia desde el principio cuando termina el archivo)
  • Sharing Mode: All threads (cada hilo lee la siguiente línea)

Referencia las variables en los samplers usando ${username} y ${password}.

Correlación

La correlación consiste en extraer valores dinámicos de las respuestas del servidor y usarlos en solicitudes posteriores. Esto es crítico para aplicaciones que usan tokens de sesión, tokens CSRF o IDs dinámicos.

Usa Regular Expression Extractor o JSON Extractor como post-procesador en el sampler que retorna el valor dinámico:

  • Reference Name: Nombre de la variable (ej., sessionToken)
  • Regular Expression: Patrón a buscar (ej., "token":"(.+?)")
  • Template: $1$ (primer grupo de captura)
  • Match No.: 1 (primera coincidencia)

Luego usa ${sessionToken} en las solicitudes posteriores.

Ejecutar JMeter desde Línea de Comandos

Para pruebas de carga reales, siempre usa el modo línea de comandos (no-GUI). La GUI consume demasiados recursos y distorsiona los resultados.

jmeter -n -t test_plan.jmx -l results.jtl -e -o report_folder

Flags:

  • -n — Modo no-GUI
  • -t — Archivo del plan de prueba
  • -l — Archivo de registro de resultados
  • -e -o — Generar reporte HTML después de la prueba

Ejercicio: Prueba de Carga a una REST API con JMeter

Crea un plan de prueba en JMeter que simule 50 usuarios navegando una API de librería durante 5 minutos.

Escenario

Estás probando una REST API para una librería en línea con estos endpoints:

EndpointMétodoDescripción
/api/booksGETListar todos los libros
/api/books/{id}GETObtener detalles de un libro
/api/auth/loginPOSTAutenticar usuario
/api/cartPOSTAgregar libro al carrito

Requisitos

  1. Crea un Thread Group con 50 usuarios, ramp-up de 120 segundos, duración de 5 minutos
  2. Agrega HTTP Request Defaults con el nombre del servidor
  3. Agrega HTTP Cookie Manager para manejo de sesiones
  4. Crea HTTP Samplers para cada endpoint
  5. Parametriza las credenciales de usuario desde un archivo CSV
  6. Correlaciona el token de autenticación desde la respuesta del login
  7. Agrega Response Assertions para validar códigos de estado
  8. Agrega un Constant Timer (1-3 segundos) entre solicitudes
  9. Agrega listeners Summary Report y Aggregate Report
  10. Ejecuta en modo no-GUI y genera un reporte HTML
Pista: Estructura del Test Plan

Tu árbol del plan de prueba debería verse así:

Test Plan
├── HTTP Request Defaults (server: api.bookstore.example.com)
├── HTTP Cookie Manager
├── CSV Data Set Config (users.csv)
├── Thread Group (50 usuarios, 120s ramp-up, duración: 300s)
│   ├── HTTP Request: Login (POST /api/auth/login)
│   │   ├── JSON Extractor (token de la respuesta)
│   │   └── Response Assertion (status = 200)
│   ├── HTTP Header Manager (Authorization: Bearer ${token})
│   ├── Constant Timer (2000ms)
│   ├── HTTP Request: Listar Libros (GET /api/books)
│   │   └── JSON Extractor (bookId de la respuesta)
│   ├── Constant Timer (2000ms)
│   ├── HTTP Request: Detalles del Libro (GET /api/books/${bookId})
│   │   └── Response Assertion (status = 200)
│   ├── Constant Timer (1000ms)
│   ├── HTTP Request: Agregar al Carrito (POST /api/cart)
│   │   └── Response Assertion (status = 201)
│   ├── Summary Report
│   └── Aggregate Report
Solución: Detalles Clave de Configuración

CSV Data Set Config:

Filename: users.csv
Variable Names: username,password
Delimiter: ,
Recycle on EOF: True

Cuerpo de la Solicitud de Login:

{
  "username": "${username}",
  "password": "${password}"
}

JSON Extractor en la Respuesta de Login:

Reference Name: token
JSON Path: $.token
Match No.: 1
Default Value: TOKEN_NOT_FOUND

HTTP Header Manager:

Authorization: Bearer ${token}

JSON Extractor en Listar Libros:

Reference Name: bookId
JSON Path: $.books[0].id
Match No.: 0 (coincidencia aleatoria)

Análisis de Resultados — Qué Buscar:

  • Tiempo de Respuesta Promedio: Debe estar bajo tu SLA (ej., < 500ms)
  • Tasa de Error: Debe ser 0% bajo carga normal
  • Throughput: Solicitudes por segundo que el servidor puede manejar
  • Percentil 90: El 90% de las solicitudes se completan dentro de este tiempo
  • Si los errores aumentan durante el ramp-up: El servidor puede tener dificultades con conexiones concurrentes
  • Si los tiempos de respuesta aumentan linealmente con los usuarios: El servidor está alcanzando su capacidad

Comando para ejecutar:

jmeter -n -t bookstore_test.jmx -l results.jtl -e -o ./report

Abre report/index.html para ver el dashboard HTML interactivo con gráficos de tiempos de respuesta, throughput y tasas de error a lo largo del tiempo.

Tips Profesionales

  • Testing Distribuido: Para pruebas a gran escala, usa el modo distribuido de JMeter con múltiples máquinas esclavas. Un controlador envía el plan de prueba a múltiples generadores de carga.
  • JMeter Plugins Manager: Instala el Plugins Manager (jmeter-plugins.org) para listeners adicionales como el gráfico de Transactions per Second y el Ultimate Thread Group para perfiles de carga complejos.
  • BeanShell vs JSR223: Siempre usa JSR223 + Groovy para scripting en lugar de BeanShell. Groovy se compila a bytecode y es significativamente más rápido bajo carga.
  • Think Time: Los usuarios reales pausan entre acciones. Agrega timers con retrasos aleatorios (Gaussian Random Timer con 2000ms de desviación y 1000ms de offset) para simulación realista.
  • Assertions a Escala: Desactiva View Results Tree durante pruebas de carga. Usa solo Summary Report o escribe resultados en un archivo JTL para análisis posterior.