En esta wiki vamos a ver cómo crear un test básico con la herramienta JMeter.
Ésta heramienta nos permitirá crear test de funcionalidad que podremos repetir automáticamente para simular test de carga en nuestros servidores.
Para descargarla basta con ir a la web de Apache JMeter
Manual de creación de test funcionales con Selenium y test de carga con JMeter en formato PDF Manual de pruebas de carga con JMetter
Un test de JMeter está compuesto por un Plan de pruebas que será la estructura principal que contenga todos los elementos necesarios para la ejecución del mismo.
Puedes descargar una plantilla con los apartados que se describen a continuación en plantillaJMeter.
Dentro del Plan de pruebas definiremos un Grupo de hilos que simularán los usuarios concurrentes en nuestra aplicación (número de usuarios, veces que repite el plan de prueba, intervalo entre creación de hilos).
Para crear el grupo de hilos, seleccionamos el Plan de Pruebas, abrimos el menú contextual (se abre con el botón derecho del ratón) y seleccionamos Añadir → Grupo de Hilos
Los elementos más importantes definidos en la pantalla anterior son:
Este elemento será el encargado de controlar y realizar todas las peticiones web/soap/rest que queramos realizar para probar nuestra aplicación. En esta wiki vamos a ver cómo realizar el test sobre una aplicación web. El lanzamiento de test sobre rest y SOAP se ve en las wikis Creación de test REST con JMeter y Creación de test SOAP con JMeter.
Para crear un Controlador Simple para el grupo de hilos seleccionaremos el grupo de hilos, abrimos el menú contextual y seleccionamos Añadir → Controlador Lógico → Controlador Simple
Una vez creado el controlador lo rellenaremos con las peticiones que realice nuestra aplicación. Éstas peticiones pueden insertarse manualmente una a una o bien usar el Proxy de captura de Jmeter para capturar una navegación de usuario y que automáticamente quede registrada en el controlador.
Una vez contenidas todas las peticiones, el resultado debe ser similar a este:
De todas las peticiones capturadas sólo nos interesan las peticiones de navegación en nuestra aplicación, por lo que repasaremos el árbol generado borrando todas las peticiones de ficheros img,css,js, etc.
Para que nuestro test, sea capaz de gestionar las cookies que normalmente una aplicación deja en el navegador, debemos añadir un elemento de gestión de las mismas al grupo de hilos. Para ello, sobre el grupode hilos haremos clic derecho Añadir → Elemento de Configuración → Gestor de Cookies HTTP
Esto permitirá que las cookies que normalmente gestiona el navegador sean gestionadas por JMeter.
En las aplicaciones J2EE, en concreto en las fundeweb, a parte de realizar las peticiones GET/POST correspondientes debemos llevar el control del viewState de jsf y el seamCID que manejan y gestionan la sesión del usuario que está navegando.
Para ello deberemos hacer uso del Extractor de Expresiones Regulares que provee JMeter para extraer los valores de esas propiedades y poder pasárselo a la siguiente petición, de manera que la sesión se mantiene.
Éste extractor de expresiones regulares debe situarse dentro del grupo de hilos, al mismo nivel que el controlador simple.
Guarda el estado de la aplicación en un instante dado para una sesión concreta. Sabiendo qué componentes están activos, que está renderizado, valores que se esperan etc…
En las aplicaciones Fundeweb tenemos dos tipos de peticiones, las normales (GET/POST) y las Ajax, cada tipo requiere una manera diferente de capturar el JSF ViewState.
Para poder capturarlo definiremos una expresión regular con los siguientes valores:
<!-- Peticiones normales --> <input type="hidden" name="javax\.faces\.ViewState" id="javax\.faces\.ViewState" value="([^"]+)" /> <!-- Peticiones ajax --> <update id="javax\.faces\.ViewState"><!\[CDATA\[([^"]+)\]\]></update>
En ocasiones en nuestros proyectos tenemos tanto peticiones normales como ajax, por lo que debemos tener los dos exctractores del JSF ViewState. El criterio que debemos seguir es que el extractor que reciba las peticiones AJAX esté debajo del extrator de las peticiones normales (GET/POST).
Ésto es así ya que JMeter ejecuta los extractores en orden y puede darse el caso que en una petición haya peticiones ajax y (GET/POST) en este caso nos interesa que coja las GET/POST porque son las que generarán la navegación.
El Seam CID es el identificación de conversación de Seam. Como sabemos, los datos dentro de una conversación se mantienen en memoria mientras ésta está activa, por lo que es importante asegurar que las llamadas en nuestra aplicación que estén dentro de una conversación se hagan con el CID correspondiente.
Para ello, al igual que con el JSF ViewState, crearemos un extractor de expresiones regulares que nos permita recuperar y usar el Seam CID.
Para poder capturarlo definiremos una expresión regular con los siguientes valores:
Nombre – indicamos para que es el extractor, el valor es: Extractor ER ID Conversación
Una vez que tenemos bien definidos los extractores tanto para el JSF ViewState como para el Seam CID debemos aplicar las sustituciones en todas las peticiones que se realicen.
Si hacemos clic en cada petición podremos ver las propiedades que se mandan con ella, por lo que deberemos realizar las sustituciones pertinentes haciendo uso de ${nombreVariable}
Para el JSF ViewState la variable, cuyo valor se tiene que sustituir es javax.faces.ViewState. Las columnas Codificar e Incluir equals deben estar marcadas.
Para el Seam CID la variable, cuyo valor se tiene que sustituir es cid. Las columnas Codificar e Incluir equals deben estar marcadas.
Ésta variable no sólo está como parámetro en la petición, sino que también aparece en la URL de la misma y en el gestor de cabeceras asociado a la petición. Se tiene que sustituir en todas las partes donde aparezca.
Gestor de cabeceras HTTP asociado a la petición
Una vez realizadas las sustituciones, se podrá ejecutar la aplicación simulando la funcionalidad indicada por las peticiones, para poder ver y analizar los datos generados por el test debemos seguir la wiki Análisis de resultados de test
Cuidado con los id dinámicos que genera JSF, ya que si el servidor se reinicia el test dejará de funcionar porque habrán cambiado esos id. Para ver cómo gestionar esta causística ver la wiki Gestión de id's dinámicos en peticiones JMeter
Cuando preparamos nuestro test de carga y lo ejecutamos, suponemos que las interacciones de JMeter con el servidor, simulando el usuario, son correctas, pero esta suposición puede no ser cierta.
Si algún parámetro falla o algún dato, por el motivo que sea, no es correcto es posible que la aplicación redirija a una pantalla de error, la cual JMeter no interpretará como un error ya que el servidor le dio una respuesta correcta. Para detectar esas situaciones de error haremos uso de las aserciones.
Una aserción es una comprobación sobre la respuesta del servidor esperando que exista o no exista un determinado valor o patrón, de manera que si no se cumple JMeter detectará esa petición como errónea y podremos darnos cuenta de que el test está fallando.
Nuestro objetivo a la hora de crear una aserción es garantizar que la página a la que vamos a acceder es la que queremos que sea.
Por defecto deberemos crear dos aserciones para la página de error de seam y la de debug.
Si algo falla durante el proceso como, por ejemplo, perder el identificador de CID de seam, se redirigrá a alguna de estas pantallas. Si no creamos las aserciones, como son páginas web válidas y la aplicación sigue funcionando, JMeter no detectará este error; de ahí la importancia de controlar que navegamos a la página que queremos.
Esta aserción permite capturar los errores que se producen en la aplicación y que Seam redirige a su página de error. Debemos crearla bajo el grupo de hilos ya que engloba cualquier petición que se lance en nuestra prueba.
Para añadirlo, seleccionamos el grupo de hilos, abrimos el menú contextual y seleccionamos Añadir → Aserciones → Asserción de Respuesta
Lo siguiente es configurar la aserción para que capture la respuesta a una petición, comprobando si se nos devuelve la página de error. Los datos a introducir son:
Esta aserción comprueba en la URL muestra de una petición o submuestras (redirecciones) si el campo de la URL no contiene el patrón “/error.seam”, lanzándose la aserción en el caso de que sí estuviera y JMeter lo entendería como una petición que ha fallado.
Esta aserción permite capturar los errores que se producen en las aplicaciones cuando no están en producción, ya que en estos casos, cuando se produce un error que la aplicación no controla, se redirige a esta pantalla.
Los parámetros a especificar en esta aserción son:
Esta aserción nos permite capturar los códigos de las respuestas HTTP pasa saber si la respuesta es correcta (código 200) u otros códigos de error (400, 500).
Nota: Estas aserciones, puede que, aunque la respuesta sea 200, la aplicación esté en una página de error, ya que sólo detectan si la respuesta HTTP fue correcta o no. Por ejemplo, la redirección a la página error.seam o debug.seam, que son páginas de error, pero el código HTTP es 200.
Los parámetros a especificar en esta aserción son:
Los códigos 302 y 200 son códigos de respuesta correcta bien por redirección, bien por devolver la página pedida.
En esta sección vamos a ver cómo crear el servidor Proxy de captura de peticiones. Este servidor, captura todas las peticiones que le llegan, y va generando el escenario de prueba de manera similar a como lo hace Selenium.
En las versiones de JMeter anteriores a la 4.0 el servidor de captura se creaba dentro de un componente de tipo Banco de pruebas. En versiones iguales o superior a la 4.0 se crea dentro del mismo Plan de pruebas.
Para crear el servidor seleccionamos Banco de Trabajo o el Plan de pruebas, abrimos el menú contextual, y le damos a Añadir → Elementos NoDePrueba → Servidor Proxy HTTP
El menú de configuración del servidor proxy es el siguiente
En esta ventana para evitar capturar contenido que no nos interesa debemos filtrar patrones de URLs.
El primer paso que debemos realizar es especificar dónde se guardarán las capturas, para ello seleccionamos en el campo Controlador Objetivo el correspondiente Controlador Simple (creado anteriormente).
También debemos asegurar establecer un puerto concreto que será el que configuremos en el navegador para que pase por el proxy. En este apartado podemos dejar el puerto por defecto o poner uno específico, la única restricción es que el puerto no esté en uso y sea el mismo que esté configurado como proxy en el navegador web.
Además bloquearemos los siguientes patrones:
(?i).*\.(bmp|css|js|gif|ico|jpe?g|png|swf|woff|woff2) .*\.(bmp|css|js|gif|ico|jpe?g|png|swf|woff|woff2).*\.seam.* .*\.(bmp|css|js|gif|ico|jpe?g|png|swf|woff|woff2)
El siguiente paso es configurar en el navegador el Proxy para enviarle las peticiones. En nuestro caso utilizamos Firefox. Para configurar el Proxy nos dirigimos a Herramientas → Opciones y hacemos clic en el menú Avanzado.
Una vez estemos en el menú, hacemos clic en Red y en el apartado Conexión hacemos clic en el botón Configuración accediendo al siguiente menú
En este menú seleccionaremos Configuración manual de proxy y pondremos los puertos http y ssl para nuestro servidor localhost los cuales deben coincidir con lo especificado en JMeter.
Importante: La casilla No usar proxy para: debe estar vacía.
Una vez configurado tanto JMeter como el navegador, nos situaremos en el servidor proxy http creado en JMeter y le daremos al botón arrancar.
Una vez arrancado accederemos desde nuestro navegador a nuestra aplicación haciendo un recorrido normal de usuario y veremos como en JMeter se van capturando las peticiones que vamos realizando.
Una vez terminada la captura deberemos seguir con el paso de configuración Gestor de cookies http
En la realización de las pruebas de carga, es posible que sea necesario lanzarlas en varios entornos (desarollo,test), para evitar tener que cambiar manualmente las url de acceso, podemos definirnos un conjunto de variables globales para centralizar para tal fin.
Para ello sobre el Grupo de Hilos botón derecho Añadir → Elemento de Configuraicón → Variables definidas por el Usuario
Una vez creado el elemento definimos las variables para el protocolo, el host y el puerto.
Tras eso, en cada petición que tengamos deberemos sustituir dichos valores
Una vez realizados los cambios en la ejecución cogerá los valores indicados en las variables.
Como mejora, podemos definir un conjunto de variables para test, otro para desarrollo, etc y habilitar/deshabilitar los que necesitemos cada vez en vez de tener que cambiar los valores.
Si nuestra aplicación requiere hacer pruebas con diferentes usuarios, podemos modelarlo en la petición de login de nuestra aplicación.
Para ello deberemos añadir un PreProcesador que se encargue de asignar a cada hilo de ejecución un valor de usuario diferente. En el caso de haber más usuarios que hilos, éstos no se rotan, descartándose los usuarios de más.
Para crear el PreProcesador debermos posicionarnos sobre la petición que hace el POST del login Añadir → Pre Procesador → Parámeros de Usuario
Una vez creado el preprocesador, añadiremos dos variables, una para el nombre de usuario y otra para la contraseña.
Tras crear las variables añadiremos usuarios, cada uno con su nombre de usario y contraseña correspondientes
Una vez configurados los parámetros, cuando lancemos el test cada hilo cogerá un usuario asignado de manera secuencial, repitiéndose cíclicamente si hubiera más hilos que usuarios.