Funciones Nativas de JMeter parte 2

title

Bienvenidos a la segunda parte de las funciones nativas de JMeter, espero con esta publicación terminar de describir las funciones que tanto apoyo nos pueden dar al momento de estar resolviendo lógica compleja para nuestras requerimientos de pruebas, sin más por el momento dejo la tabla de funciones que cubriremos en esta publicación:

funciones

4. Funciones con lenguajes de programación

Este es probablemente el conjunto de funciones más controvertido de JMeter, porque la programación las hace demasiado amplias y pueden conducir a un sin fin de posibilidades. No podemos profundizar tanto, porque la cantidad de formas de usarlas es innumerable, pero me gustaría mostrar algunos casos beneficiosos de estas funciones emparejadas con los controladores IF y WHILE.

Las opciones para lenguajes de programación son: Beanshell, Groovy, JavaScript y JEXL. Así es que podemos seleccionar nuestra arma predilecta para lidiar con cualquier lógica compleja o simple. Sin embargo, probablemente solo usemos un par de líneas de código como máximo. ¿Por qué? Porque si desea utilizar más que eso, te recomiendo mejor utilizar el pre-procesador, muestreador o post-procesador.

Beanshell

Beanshell es un intérprete de Java creado hace 20 años y la última actualización conocida fue lanzada en 2003. Obviamente, es obsoleto pero aún funcional. Aprendí JMeter emparejado con Beanshell a inicios del 2012 lo utilicé hasta 2017 cuando Groovy tomó la delantera y su eficiencia y rapidez desbancaron rápidamente a Beanshell, especialmente si el código de compilación está en caché. Durante más de 5 años, utilicé Beanshell para lidiar con casi todas los requerimientos de lógica en los flujos, principalmente como preprocesador o postprocesador, raras veces como muestreador, pues no gustaba su efecto mis resultados.

Groovy

Por muy extraño que parezca, Groovy fue lanzado el mismo año en que se lanzó la última versión estable de Beanshell, en el año 2003. Desde entonces Groovy se ha convertido en el lenguaje de scripting de JMeter más popular. Algunas de sus ventajas más importantes son:

  • Es un lenguaje orientado a objetos.
  • Se compila en código de bytes directamente, tan rápido como el código Java.
  • Almacena en caché el código compilado.
  • Se mantiene y actualiza constantemente.

Hoy en día, no hay lugar para la comparación entre Groovy y Beanshell porque Beanshell no se ha actualizado en más de 16 años. Sin embargo, el único escenario en el que recomendaría usar Beanshell sería en scripts JMeter legados que no se pueden migrar a versiones más nuevas de JMeter. En caso contrario recomendaría migrar a Groovy dado que este es más rápido y no es necesario cambiar mucho código, pues Groovy reconoce casi en su totalidad la sintaxis de Beanshell.

JavaScript

JavaScript o ECMAScript es otro lenguaje interpretado que se puede utilizar en JMeter. Básicamente, los controladores IF y WHILE evalúan la sentencia con este lenguaje, para permitir que el hilo continúe, salga del ciclo o salte a alguna ramificación. Aunque es un gran lenguaje, el muestreador para JSR223 solo admite el almacenamiento en caché para Groovy, lo que hace que JavaScript sea menos eficiente en grandes repeticiones. En mi opinión, es mejor utilizarlo para evaluaciones pequeñas pero no para tareas complejas.

JEXL

JEXL son las siglas de Java Expression Language. Es el lenguaje de programación más limitado, pero eso es exactamente lo que lo hace tan popular, su simplicidad. El código es pequeño y rápido que evalúa una expresión en booleano, y es probablemente el uso más común de JEXL en JMeter, aunque también se puede usar en modelos de carga o sentencias de evaluación.

Ejemplos de las funciones con lenguajes de programación:

Función Ejemplo Resultado esperado
groovy ${__groovy(props.get("START.MS").substring(0\,2),)} Imprime la subcadena 0-2 de la propiedad START.MS
BeanShell ${__BeanShell(123*456,)} Imprime el resultado de la multiplicación de 123x456
javaScript ${__javaScript(new Date(),)} Imprime una nueva fecha en formato extendido
jexl2 ${__jexl2(1 < 1,)} Imprime el resultado booleano de la evaluación: False
jexl3 ${__jexl2(1 >= 1,)} Imprime el resultado booleano de la evaluación: True

Todos los lenguajes de programación tienen acceso a los recursos de JMeter. La siguiente tabla describe la relación recursos con los lenguajes de programación: lenguajes

Usos populares:

Si estas utilizando controladores IF o WHILE, esos controladores requieren una sentencia de expresión basada en un valor booleano para decidir si continuar o descartar, por lo tanto, las mejores opciones para esa tarea serían JavaScript y JEXL, aunque pudieramos utilizar cualquiera. Pero siempre tener cuidado de seleccionar la opción para evaluar la sentencia como variable de expresión. Algunas usos populares serian:

if-while-controller

Aquí hay un ejemplo del script de WebTours que tiene un modelo de carga utilizando IF Controllers. El script de JMeter con ejemplos del uso IF controller para modelación y distribución de carga requiere Java 1.8+, JMeter 5+ and JMeter plugins.

¿ Porqué utilizar IF Controller en lugar de Throughput Controller ?

Esta es una buena pregunta, pero responderla no es nada sencillo. En mi opinión personal el Throughput Controller realiza muchos cálculos para resolver si una parte del flujo deba o no ser ejecutada, basándose pen ejecuciones previas, conteo de iteraciones por medio de propiedades y evaluaciones para corregir los valores. Esto en conjunto consume muchos recursos de CPU y Memoria, y en mayor medida si se tienen varios Throughput Controllers, en un mismo script para modelar la carga. En cambio el IF Controller solo realizará una evaluación con JEXL para calcular y decidir, si el valor del porcentaje generado por la variable aleatoria se encuentra en el rango o no. Además de que el Throughput Controller requiere un numero base de ejecuciones para corregir el rumbo, si detienes la prueba por alguno motivo antes de lo esperado, este será incapaz de corregirse. Caso contrario con IF Controller en cualquier instante de tiempo el numero generado aleatoriamente debiera o no satisfacer la lógica debido a que los numeros aleatorios tiene una distribución uniforme.

funciones

5. Funciones de propiedades

Las propiedades en JMeter, son como variables pero en un entorno global. Esto significa que todos los hilos pueden acceder a estos valores y también pueden ser actualizados, la mayoría de estos valores "propiedades" se establecen desde los archivos .properties ubicados en la carpeta bin como user.properties y jmeter.properties. Tengan en cuenta que si actualizan algunos des estos valores, se deberá reiniciar JMeter para que surta efecto.

No recomendaría modificar ningún parámetro a menos que tengan el conocimiento preciso lo que está haciendo, porque podrían afectar negativamente el comportamiento de JMeter, y en consecuencia sus resultados. A pesar de este peligro latente al modificar las propiedades, la ventaja de usar estos parámetros es bastante amplia, y uno de los usos más comunes es configurar el número de hilos, rampa o duración de los scripts, como lo pudimos apreciar en este artículo

Puede aprovechar esos parámetros localmente utilizando la CLI de JMeter.

jmeter.sh -n -t TestPlan.jmx -Jthreads=100 -Jrampup=100 -Jduration=600 -l TestPlan.jtl

propiedades

Otro gran ejemplo es configurar objetos globalmente, y no hablo solo de cadenas, enteros o booleanos. Podemos configurar matrices, vectores, colas, listas y cualquier tipo de estructura de datos que puedas necesitar para la lógica de tu prueba. Publiqué hace mucho tiempo un artículo de Grafana en LinkedIn, donde estaba usando una lista para recopilar varios renglones de resultados para enviarlos hacia InfluxDB en una sola solicitud HTTP, aqui puedes consultar el artículo.

Ejemplos de las funciones de propiedades:
propiedades
threads: 1
rampup: 1
duration: 60

Función Ejemplo Resultado esperado
isPropDefined ${__isPropDefined(threads)} Imprime el valor booleano en caso de estar definida la propiedad, en este caso true
property ${__property(threads)} Imprime el valor de la propiedad threads: 1
P ${__P(duration)} Imprime el valor de la propiedad: 60
P ${__P(duration,90)} Actualiza el valor de la propiedad a 90
setProperty ${__setProperty(propname,propvalue,)} Asigna el valor a una propiedad

Así mismo incluimos imágenes de los ejemplos y el archivo lo puedes descargar abajo: propiedades-setup
propiedades-response

El script de JMeter con ejemplos de funciones de propiedades requiere Java 1.8+, JMeter 5+ and JMeter plugins.

6. Funciones de variables

Las variables en JMeter, son simplemente variables locales, lo que significa que se crean y destruyen en cada iteración del hilo. La mayoría de los datos que usamos en la ejecución de un hilo (como las correlaciones) se almacenan en variables que desaparecerán una vez que el hilo finalice y se inicie una nueva iteración. Si hay algún valor que necesites guardar, la mejor opción es guardarlo en una propiedad, aunque los valores de propiedades también desaparecerán cuando se detenga la prueba, en esa situación lo mejor es guardar los valores en un archivo.

Ejemplos de las funciones de variables:
variables
Test_1: Flood
Test_2: io
Vars: 12345|67890|10293848576|5647382910
Variable: Test_1 es "${Test_1}" y Test_2 es "${Test_2}"
Numero: 2

Función Ejemplo Resultado esperado
split ${__split(${Vars},splitVar,|)} Divide la variable Vars con el delimitador pipe, y los resultados son almacenado en splitVar
eval ${_eval(Test\1 es "${Test_1}" y Test_2 es "${Test_2}")} Imprime la cadena: Test_1 es "Flood" y Test_2 es "io"
evalVar ${__evalVar(Variable)} Imprime la evaluación de Variable: Test_1 es "Flood" y Test_2 es "io"
isVarDefined ${__isVarDefined(Variable)} Imprime el valor booleano en caso de estar definida la variable, en este caso true
V ${_V(Test\${Numero})} Imprime la cadena: io que es el contenido de la variable Test_2
V ${_V(splitVar\${Numero})} Imprime la cadena: 67890 que es el contenido de la variable splitVar_2

Así mismo incluimos imágenes de los ejemplos y el archivo lo puedes descargar abajo: vars-setup
vars-response

El script de JMeter con ejemplos de funciones de variables requiere Java 1.8+, JMeter 5+ and JMeter plugins.

7. Funciones de cadenas

Es muy común en el entorno de las pruebas modificar y actualizar valores de cadenas de caracteres, es posible también realizar transformaciones, conversiones, cortes o divisiones de las mismas. Algunos de los usos más común es la codificación y descodificación de URL con las funciones urlencode y urldecode, ambas funciones son realmente útiles cuando se trata de páginas web y parámetros de publicación. Aunque las funciones de cadena están destinadas a la conversión, tenemos dos funciones que probablemente no estén tan relacionadas a dichas tareas. Como por ejemplo regexFunction, que es un extractor de expresiones regulares muy similar al post-procesador, y dateTimeConvert, la cual nos ayuda a transformar diferentes formatos de tiempo.

Ejemplos de las funciones de cadenas:

Función Ejemplo Resultado esperado
char ${__char(165)} Imprime el caracter 165: ¥
char ${__char(182)} Imprime el caracter 182: ¶
changeCase ${__changeCase(Mayusculas,UPPER,Tmp)} Cambia el formato a mayúsculas: MAYUSCULAS y lo guarda en la variable Tmp
changeCase ${__changeCase(Minusculas,LOWER,Tmp)} Cambia el formato a minúsculas: minusculas y lo guarda en la variable Tmp
escapeOroRegexpChars ${__escapeOroRegexpChars([0-9].+?,)} Imprime la cadena: [0-9].+?
escapeXml ${__escapeXml("Valor"+&+’Value’)} Imprime la cadena: "Valor"+&+?Value?
regexFunction ${__regexFunction(min(.+),$1$,1,,,,Tmp)} Regresa la evaluación de la expresion regular en la variable Tmp: sculas
escapeHtml ${__escapeHtml("Comillas Dobles"+'sencillas')} Imprime la cadena: "Comillas Dobles"+'sencillas'
unescapeHtml ${__unescapeHtml("Comillas Dobles"+'sencillas')} Imprime la cadena: "Comillas Dobles"+'sencillas'
unescape ${__unescape(\ttabulador)} Imprime la cadena: tabulador
urlencode ${__urldecode(%5Bflood%5D%3D%28element%29)} Imprime la cadena: [flood]=(element)
urldecode ${__urlencode([flood]=(element))} Imprime la cadena: %5Bflood%5D%3D%28element%29
TestPlanName ${__TestPlanName()} Imprime la cadena: Strings-functions.jmx
dateTimeConvert ${__dateTimeConvert(1589794881,,dd/MM/yyyy HH:mm,)} Imprime la cadena: 18/05/2020 04:41

Así mismo incluimos imágenes de los ejemplos y el archivo lo puedes descargar abajo: strings-setup
strings-response

El script de JMeter con ejemplos de funciones de cadenas requiere Java 1.8+, JMeter 5+ and JMeter plugins.

Conclusión

Las funciones de JMeter han crecido en número y valor, aunque también existen las funciones extendidas que se pueden incluir utilizando el aditamento Custom JMeter Functions y son de extrema utilidad, sobre todo las de Base64 cuando requerimos calcular autenticación básica en headers. No las cubrí en esta publicación pero creo que hay que enseñar a pescar no dar el pescado, basta con instalar los aditamentos, seleccionar Custom JMeter Functions del menú y reiniciar. Espero esta información haya sido de utilidad. Diviertanse utilizando las funciones de JMeter.

-Antonio