Open Source 28 January 2021

Comparando k6 y JMeter para pruebas de carga

Nicole van der Hoeven, k6 Developer Advocate

📖Lo que aprenderás

  • Puntos fuertes y débiles de JMeter y de k6
  • Cosas a tener en cuenta al elegir una herramienta de pruebas de carga
  • ¿Qué herramienta es mejor para diferentes situaciones?

Introducción

Cuando me uní al equipo de K6 a finales de noviembre, la pregunta más importante en mi mente fue "¿Cómo se compara esto con JMeter?" Verás, yo vengo de una consultoría de pruebas de rendimiento, y en los últimos años, JMeter ha sido de lejos mi herramienta de elección.

Entonces, ¿qué estoy haciendo en el sitio K6, hablando de lo mucho que me gusta JMeter? Bueno, en primer lugar, resulta que el equipo de K6 es bastante abierto y transparente, especialmente en lo que respecta a las posibles mejoras en K6. En segundo lugar, quiero compartir mis razones para querer explorar k6 como una herramienta de pruebas de carga, las mismas razones que en última instancia me convenció de unirme al equipo que lo construye.

¿Qué es JMeter?

JMeter es una herramienta de pruebas de carga de código abierto construida completamente en Java por la Fundación Apache. Fue lanzada por primera vez en 1998, y causó sensación por su audacia al enfrentarse a herramientas de pruebas de carga más populares pero propietarias. JMeter tomó lo que otras empresas cobraban mucho dinero y lo publicó en línea para que todo el mundo lo utilizara, de forma gratuita. Aunque los scripts también pueden ser extendidos usando código, la mayoría de los scripts en JMeter se hacen usando la UI. En el momento de escribir este artículo, la última versión de JMeter es la 5.4.

¿Qué es K6?

K6 es una herramienta de pruebas de carga de código abierto lanzada por LoadImpact en 2017. LoadImpact había consistido previamente en la plataforma SaaS (ahora Grafana Cloud k6) y los servicios profesionales. K6 está escrito en Go, pero los scripts están escritos en Javascript. Al contrario que JMeter, la principal ventaja de K6 es su código basado en scripts y la fuerte prioridad de la experiencia del desarrollador. La última versión de K6 es la 0.30.

¿Cuál es mejor?

Este artículo no trata sobre qué herramienta es mejor, porque por mucho que prefiramos una respuesta clara, no hay una "mejor herramienta". Todo depende de la situación en la que se encuentre tu equipo: qué, cómo, por qué y cuándo estás probando.

La pregunta que quiero responder aquí es: ¿En qué situaciones destaca cada herramienta?


¿Cuándo destaca JMeter?

Cuando se quiere empezar rápidamente

JMeter tiene una GUI

Muchos equipos de pruebas toman decisiones sobre las herramientas de pruebas de carga basándose únicamente en este hecho. A veces, si usted está en una situación en la que la gente no ha hecho pruebas de carga antes y necesita aprender una nueva herramienta, una herramienta con GUI como JMeter es simplemente la opción más fácil. Una herramienta con una interfaz gráfica de usuario será menos desalentadora para muchos probadores que están acostumbrados a la mayoría de las interfaces de usuario sin código similares a Postman o SOAPUI.

JMeter's starting screen: a fresh new test plan

Siempre he pensado que JMeter es fácil de usar, pero un amigo desarrollador señaló recientemente que la pantalla del plan de pruebas que te saluda cuando inicias JMeter por primera vez no proporciona ninguna indicación de cómo crear un muestreo HTTP. Ninguno de los iconos añade elementos al plan de pruebas. Hay que explorar un poco para darse cuenta de que haciendo clic con el botón derecho del ratón en el plan de pruebas, o yendo a Editar > Añadir, aparecerá el menú "Añadir" que necesita. Tiene razón: La interfaz de usuario es subjetiva hasta cierto punto. Sin embargo, yo diría que es definitivamente más fácil para los no desarrolladores explorar una interfaz de usuario que un poco de código.

K6 no tiene una GUI (interfaz de usuario gráfica) en la versión Open Source, pero el Constructor de pruebas de K6 está disponible de forma gratuita. Es una forma de crear pruebas con una interfaz GUI, y a pesar de su inclusión en la nube de K6, no requiere ninguna suscripción para su uso. Sin embargo, no es tan completo como JMeter.

JMeter soporta muchos protocolos y características listos para usar

Aquí está la lista oficial de los protocolos que JMeter soporta:

  • Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, ...)
  • SOAP / REST Webservices
  • FTP
  • Base de datos a través de JDBC
  • LDAP
  • Middleware orientado a mensajes (MOM) a través de JMS
  • Correo - SMTP(S), POP3(S) e IMAP(S)
  • Comandos nativos o scripts de shell
  • TCP
  • Objetos Java

En cambio, K6 soporta los siguientes protocolos:

Los protocolos anteriores son los que se soportan de forma nativa. Sin embargo, ambas herramientas permiten el desarrollo de plugins de terceros, añadiendo soporte para más protocolos. El número de K6 community extensions, a través de xk6, está creciendo, pero los plugins de JMeter siguen siendo más numerosos. En muchos casos, los protocolos que utiliza su aplicación pueden decidir por usted qué herramienta utilizar.

JMeter también tiene la mayoría de las características que necesitarás para una prueba de carga básica, y no tienes que codificar nada de ello tú mismo. Su estructura de elementos padre-hijo significa que puede modificar un elemento específico, como una solicitud HTTP, o modificar todas las solicitudes HTTP, con la misma facilidad. Añadir el "think time" a todas las peticiones es tan fácil como añadir un Temporizador Aleatorio Uniforme a su grupo de hilos, y todas las peticiones dentro de ese grupo lo heredarán. Con las herramientas de pruebas de carga basadas en código, puede ser un poco más difícil averiguar lo que es posible sin una interfaz de usuario. Sin embargo, parte de la brecha puede ser salvada por un IDE con un buen autocompletado.

Cuando quieres una comunidad madura con toneladas de documentación

JMeter es viejo, y a veces eso es algo bueno. Ha existido desde 1998, así que en este punto, ha tenido 22 años para mejorar y construir un seguimiento. JMeter está presente en casi todos los sitios de redes comunitarias, y no importa lo específico que sea tu caso de uso para JMeter, lo más probable es que ya se haya hecho antes. Buscando "cómo cargar la prueba X con JMeter" es probable que aparezcan miles de resultados y algunos vídeos que muestran exactamente cómo hacerlo.

El Componente de referencia de JMeter es una prueba de la extensa y exhaustiva documentación de JMeter. Cada elemento, función y propiedad se discute con más detalle de lo que la mayoría de la gente podría desear, y eso es sólo la documentación "oficial" que está en el sitio de Apache. Hay miles de libros, tutoriales y cursos sobre JMeter realizados por sus apasionados usuarios.

El repositorio de JMeter en GitHub tiene 17.290 commits a fecha de diciembre de 2020, lo que demuestra que existe una comunidad de desarrolladores que han dedicado tiempo y experiencia a JMeter durante las últimas dos décadas.

En comparación, la comunidad de K6 está creciendo, pero sigue siendo pequeña. Hay un foro oficial - central community forum que permite a los usuarios compartir sus experiencias con K6, algo que falta en la comunidad de JMeter. El repositorio de K6 tiene más estrellas, pero significativamente menos commits, con 3.795. Gran parte de la disparidad, por supuesto, se debe a que K6 es muy nuevo: la herramienta de código abierto K6 no se publicó hasta 2017.

Cuando necesitas una forma rentable de hacer pruebas de carga distribuidas

Una de las mejores características absolutas de JMeter es que te da un marco para ejecutar pruebas de carga distribuidas con él. Esto es bastante especial para una herramienta gratuita y de código abierto.

Las pruebas distribuidas significan aumentar la cantidad de carga que está generando con sus pruebas de carga, generalmente aumentando el número de usuarios virtuales y ejecutando múltiples instancias de su script en otros generadores de carga. JMeter logra esto designando un nodo controlador y permitiéndole configurar los "worker nodes". Cada "worker nodes" necesita tener una copia de jmeter-server, una utilidad incluida con cada instalación de JMeter (en jmeter/bin).

JMeter comes with a native distributed testing mode

Fuente: Apache JMeter

Estos "worker nodes" ejecutan copias de su plan de pruebas y ejercen la carga contra su servidor de aplicaciones. Puede utilizar máquinas locales o en la nube como "worker nodes". Una ejecución distribuida como esta requiere un poco de configuración, pero funciona sorprendentemente bien.

K6 tiene un modo de prueba de carga distribuida usando un operador de Kubernetes: K6 Operator se permite crear un objeto de k6 dentro de un cluster de Kubernetes. Aparte de su utilidad para las aplicaciones que ya funcionan dentro de Kubernetes, el operador también permite pruebas distribuidas sencillas.

Es importante tener en cuenta que JMeter puede consumir muchos recursos, y por lo tanto es más probable que requiera múltiples generadores de carga para generar carga que K6. Dependiendo de los recursos del generador de carga, JMeter puede ejecutar alrededor de mil usuarios virtuales en promedio, y escalar su prueba más allá de ese punto requerirá una configuración de ejecución distribuida. Una sola instancia de K6, por otro lado, puede ejecutar decenas de miles de usuarios virtuales si se le proporcionan los mismos recursos. Más adelante hablaremos de ello.

Cuando quiera informes enlatados incorporados a su herramienta de pruebas de carga

Los numerosos listeners de JMeter le permiten decidir exactamente en qué formato quiere ver los resultados. ¿Depuración? Utilice el árbol de visualización de resultados. ¿Desea obtener métricas para su prueba de carga? Utilice el informe resumido o agregado.

Adding listeners like View Results Tree in JMeter lets you visualize results in different ways

Además, JMeter puede generar informes HTML basados en tus pruebas de carga. Actualmente son bastante limitados, pero funcionales, y tienen varios gráficos por defecto para ayudarte a analizar tu prueba de carga. No son interactivos, pero son bastante fáciles de generar y un buen punto de partida para armar una plantilla de informe para sus pruebas.

JMeter's built-in HTML dashboard is limited but functional

K6 no tiene informes integrados. Su naturaleza modular se presta mejor a la integración con muchas otras herramientas de análisis de datos, incluyendo Grafana, Datadog, New Relic, Amazon CloudWatch, y K6 Cloud - todos los cuales son mejores herramientas de análisis y pueden proporcionar más información que los informes de JMeter pueden proporcionar, pero requieren que usted configure otra herramienta para analizar sus pruebas. Si tienes poco tiempo y puedes conformarte con sus informes, JMeter es realmente bueno en proporcionar ese valor extra.

¿Cuándo sobresale K6?

Cuando quieres empezar rápidamente

Sí, he puesto esto tanto en la sección de JMeter como en la de K6. Tanto JMeter como K6 pueden ser fáciles de empezar, pero por razones muy diferentes.

Instalación

K6 se instala extremadamente rápido, en mi primera instalación en macOS, tomó 7 segundos vía brew install k6. Tampoco requiere nodeJS ni ninguna otra dependencia.

JMeter en sí mismo es bastante fácil de instalar, pero antes de instalar JMeter, es necesario instalar Java. Especialmente si se utiliza Windows, es un poco un rito de paso para un nuevo usuario de JMeter encontrarse con problemas para añadir las variables de entorno necesarias para que Java funcione.

También puede ser confuso determinar qué versión de Java es la correcta. Hay JDK, JRE, y recientemente Oracle ha añadido a la confusión anunciando que algunas versiones de Java (pero no todas) van a requerir una licencia.

Oracle's changing Java licensing can cause confusion for JMeter users

Fuente: Oracle Java

Aunque JMeter sigue siendo gratuito a través de OpenJDK, he hablado con algunos probadores que pensaron erróneamente que tendrían que pagar por JMeter. Es un poco desconcertante ver a Oracle flexionando sus músculos, especialmente si has construido toda una suite de pruebas de rendimiento en Java a través de JMeter.

Plugins

K6 soporta plugins, pero no son necesarios. Para la mayoría de los casos de uso, la funcionalidad integrada de K6 debería ser más que suficiente. Esto contrasta con JMeter, donde todo es un plugin... ¡incluso el Plugin Manager!

La mayoría de los usuarios de JMeter argumentarían que hay un conjunto estándar de plugins que deberías descargar antes de empezar a usarlo. Un nuevo usuario de JMeter no tiene por qué saber dónde encontrarlos y puede tener una experiencia poco satisfactoria desde el principio.

Estas son algunas de las cosas que no tendrá si se queda con una instalación de JMeter sin plugins:

  • Grupos de hilos: No hay perfil de carga personalizado, etapas, rendezvous
  • Controladores: No hay controlador paralelo para ejecutar peticiones en paralelo
  • Samplers: No hay soporte para HTTP/2
  • Datos de prueba: No hay aleatorización de líneas dentro de un archivo CSV (sólo secuencial)
  • Temporizadores: No hay temporizador de conformación de rendimiento para establecer el rendimiento en etapas

Todas estas funciones están disponibles en K6 desde el principio.

Scripts

Los scripts de K6 están escritos en javascript, por lo que son fáciles de escribir y ejecutar. Todo lo que necesita es un instalador (en Microsoft Windows) o un único comando en su terminal y cualquier editor de texto. Para JMeter, necesitarás instalar algunas cosas localmente antes de empezar: Java, el propio JMeter y el conjunto estándar de plugins que necesitará. Esto puede ser confuso para los nuevos usuarios. ¿Quién no ha tenido problemas con las variables de entorno en algún momento al aprender a usar JMeter, especialmente en Windows?

También se necesita tiempo para aprender cualquier nueva interfaz de usuario, mientras que javascript es casi omnipresente y es un buen lenguaje para aprender cuando se está probando sitios web de carga de todos modos.

Cuando quieres maximizar el rendimiento y la eficiencia

¡Prueba tus herramientas de prueba!

¿Por qué es importante todo esto?

Cuando hablamos de simular muchos usuarios virtuales, un rendimiento lento = un coste elevado. El número de generadores de carga que utilices tiene un coste, ya sea el coste de adquirirlos y mantenerlos (on-prem) o el coste de un servicio en la nube.

Tiene sentido considerar las limitaciones de rendimiento de su herramienta de pruebas de carga antes de utilizarla para mejorar el rendimiento de su propia aplicación.

K6 se basa en el rendimiento estelar de Go

K6 está escrito en Go, y Go está construido con el rendimiento en mente. "Go es un lenguaje compilado y no necesita ser interpretado, a diferencia de Java o Python. No hay ninguna capa de complejidad añadida". Tampoco tiene dependencias externas, lo cual es bueno. Menos partes móviles para un probador de rendimiento significa menos fuentes potenciales de un cuello de botella.

La forma más sencilla y común de que una herramienta de pruebas de carga ejecute un usuario virtual es asignar un usuario virtual a un núcleo o hilo del sistema operativo. Sin embargo, el paradigma de 1 hilo: 1 usuario virtual tiene un grave defecto: cuando un usuario virtual está esperando una respuesta o ejecutando un sleep() programado, el hilo también está bloqueado, y no puede procesar otro trabajo.

En K6, cada usuario virtual se ejecuta en una goroutine, no en un hilo. ¿Qué diferencia supone esto? Bueno, las goroutines pueden ser controladas por algo llamado Go Scheduler, que actúa como un policía de tráfico. Reutiliza los hilos ociosos y asigna el trabajo de forma inteligente, permitiendo el "robo de trabajo" y el traspaso de trabajo entre hilos. ¿Te suena esto? Este es el mismo principio en el que se basan los balanceadores de carga: Un monitor externo que supervisa el flujo de trabajo mejora el rendimiento general. El propio Go está intrínsecamente equilibrado en cuanto a la carga de una manera que muchos lenguajes de programación no lo están, lo que lo convierte en la base perfecta para una herramienta de pruebas de carga.

Ser capaz de aprovechar las optimizaciones de rendimiento innatas de Go también se traduce en una utilización significativamente menor de la memoria. Un hilo ejecutando K6 no supera los 100 kb, mientras que un hilo de JVM como JMeter, utiliza el valor por defecto de 1MB. ¡Eso es un 1000% más que k6! Por supuesto, Java permite al usuario ajustar la utilización de la memoria de una aplicación, por lo que la diferencia no suele ser tan marcada, pero sigue siendo interesante observar que Go tiene un punto de partida mucho más bajo.

... crear un nuevo hilo en Java no es eficiente en cuanto a la memoria. Ya que cada hilo consume aproximadamente 1MB del tamaño de la memoria de la pila y, eventualmente, si empiezas a hacer girar miles de hilos, pondrán una tremenda presión en la pila y causarán el cierre debido a la falta de memoria. Además, si quieres comunicarte entre dos o más hilos, es muy difícil. - Keval Patel

Ventajas de rendimiento en la práctica

Se necesitan menos generadores de carga

El rendimiento comparativamente mejor de K6 significa que necesita menos generadores de carga para ejecutar una cantidad determinada de carga. Rafaela Azevedo hizo una comparación de la memoria utilizada por K6 y JMeter, y aquí están sus resultados:

JMeter ocupaba 760 MB de memoria.

In an independent test by Rafaela Azevedo, JMeter took up 760 MB of memory

Fuente: Rafaela Azevedo

Mientras tanto, en K6 ocupaba 256 MB de memoria.

In an independent test by Rafaela Azevedo, k6 took up 256 MB of memory compared to JMeter's 760 MB for the same test

Fuente: Rafaela Azevedo

Las conclusiones de Rafaela se ven confirmadas por nuestras propias referencias.

A comparison of maximum throughput and memory for the most popular open-source load testing tools

Fuente: Ragnar Lönn, en nuestra Comparación de herramientas de pruebas de carga

El bajo uso de memoria de K6 es la razón por la que puede ejecutar más usuarios virtuales y generar más carga que la media. Tanto si utiliza generadores de carga locales como en la nube, pagará menos por los costes de aprovisionamiento cuando utilice K6. Este ahorro de costes hace que K6 sea una gran herramienta para los equipos preocupados por el presupuesto.

La idea errónea de muchos probadores de carga es que la ejecución distribuida (capacidad de lanzar una prueba de carga en múltiples máquinas) es necesaria para generar una gran carga. Este no es el caso con K6. - Rafaela Azevedo](https://azevedorafaela.com/2020/07/06/load-tests-jmeter-vs-k6/)

K6 es diferente de muchas otras herramientas de pruebas de carga en la forma en que maneja los recursos de hardware. Un solo proceso de k6 utilizará eficientemente todos los núcleos de la CPU en una máquina generadora de carga. Una sola instancia de K6 suele ser suficiente para generar una carga de 30.000-40.000 usuarios simultáneos (VUs). Esta cantidad de VUs puede generar más de 300.000 peticiones por segundo (RPS).

A menos que necesite más de 100.000-300.000 peticiones por segundo (6-12M peticiones por minuto), una sola instancia de K6 será probablemente suficiente para sus necesidades. - documentación de K6

No hay errores de memoria. K6 también es bueno para cuando se tiene poco tiempo. Usar JMeter significa familiarizarse con la forma de ajustar el rendimiento de Java y cómo solucionar los problemas de rendimiento más comunes de Java, porque hay varios. El que más me he encontrado personalmente al usar JMeter es:

ERROR - jmeter.threads.JMeterThread: Test failed! java.lang.OutOfMemoryError:
Java heap space.

No eres realmente un probador de carga de JMeter hasta que hayas visto este error. :)

La causa de este error suele ser que había una cantidad insuficiente de memoria Heap asignada a JMeter. Sí, además de monitorizar el uso de memoria de tu generador de carga, también tendrás que monitorizar el uso de memoria de la JVM. Puede establecer la cantidad de memoria heap asignada a JMeter modificando el propio binario de JMeter y cambiando esta línea:

# Este es el tamaño base de la pila, puede aumentarlo o disminuirlo para adaptarlo a
#la disponibilidad de memoria del sistema:
: "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"

Incluso la documentación oficial de JMeter sugiere que aumente el tamaño de Java Heap más allá de 1GB antes de ejecutar su primera prueba de carga.

Aumente el tamaño del Heap de Java. Por defecto JMeter se ejecuta con un heap de 1 GB, esto podría no ser suficiente para su prueba y depende de su plan de prueba y el número de hilos que desea ejecutar - Apache JMeter

Sin GUI significa que no hay sobrecarga de recursos durante las pruebas de carga.

Las GUIs suelen añadir una sobrecarga significativa a una aplicación, que es una de las razones por las que K6 no tiene una.

Cuando se ejecuta una prueba de carga, la mejor práctica es ejecutarla desde la línea de comandos de todos modos porque de lo contrario, interfiere con sus resultados. Las herramientas de pruebas de carga basadas en código son performantes desde el principio.

JMeter está salpicado de advertencias sobre el efecto de la GUI en el rendimiento. Aquí hay una de la "documentación de JMeter":

¡No ejecute la prueba de carga usando el modo GUI! - Apache JMeter

Y aquí hay un mensaje que ocurre al iniciar JMeter: JMeter's startup screen warns users not to use the GUI mode for load testing

No tener una interfaz gráfica de usuario significa que hay un problema menos. Todos los scripts de pruebas de carga que cree en K6 están listos para ser ejecutados en tiempo real cuando usted lo desee.

Cuando quiera hacer pruebas orientadas a objetivos

La pregunta más importante que un probador de carga puede hacer cuando comienza un nuevo proyecto de prueba de carga es "¿Por qué? Los planes de prueba deben hacerse para abordar directamente las razones de un equipo para querer hacer pruebas de carga, y eso debe reflejarse en los requisitos no funcionales. Los requisitos no funcionales, a su vez, deben dar alguna orientación en cuanto a los límites del rendimiento aceptable. Un ejemplo común de estos límites, o umbrales, es un tiempo medio de respuesta inferior a 3 segundos para todas las transacciones durante la prueba. k6 hace esto de forma nativa con umbrales globales incorporados en el script, y también puede crear su propia métrica para utilizarla en un umbral:

import http from 'k6/http';
import { Rate } from 'k6/metrics';
const myFailRate = new Rate('failed requests');
export const options = {
thresholds: {
'failed requests': ['rate<0.1'], // umbral en una métrica personalizada
'http_req_duration': ['p(95)<500'], // umbral en una métrica estándar
},
};
export default function () {
const res = http.get('https://test-api.k6.io/public/crocodiles/1/');
myFailRate.add(res.status !== 200);
}

Fuente: documentación de K6

JMeter no soporta de forma nativa los umbrales a nivel de prueba. Hay algunas formas en las que he podido solucionar esto:

  • Aserción de duración: Se puede añadir una aserción de duración a cualquier muestreador en JMeter, lo que permite establecer un tiempo de respuesta aceptable para esa solicitud en milisegundos, más allá del cual la solicitud (y la transacción que la engloba) se marcaría como fallida. Sin embargo, esto sigue siendo sólo a nivel de solicitud individual, e incluso poniendo el elemento de aserción de duración en el nivel del Plan de Pruebas sólo aplica el mismo umbral a cada solicitud secundaria. No constituye un criterio de aprobado/desaprobado para la prueba en su conjunto.

  • Tiempos: Para los criterios relacionados con el rendimiento, puede utilizar el temporizador de rendimiento constante o el temporizador de ajuste de rendimiento (plugin). Este enfoque controla el número de peticiones por segundo. En mi experiencia, vale la pena probar cómo se comportan estos temporizadores cuando se utilizan controladores de transacciones anidados - puede tomar algún reordenamiento para hacerlo bien.

  • Performance Plugin: Al integrar JMeter con Jenkins, puedes utilizar el plugin de rendimiento para establecer umbrales de error y marcar las ejecuciones de prueba ("builds") como inestables o fallidas dentro de Jenkins.

  • Código personalizado: Puedes utilizar el JSR223 Sampler para escribir un poco de código Groovy o BeanShell que recoja y analice las métricas de respuesta.

El problema es que aunque estas opciones hacen posible establecer umbrales en JMeter, siguen siendo soluciones que no vienen con JMeter fuera de la caja o no abordan adecuadamente la creación de diferentes tipos de umbrales (error, tiempo de respuesta, rendimiento, CPU, memoria). Lo que acabo haciendo, la mayoría de las veces, es exportar los datos en bruto de JMeter y hacer el análisis yo mismo utilizando otra herramienta.

Cuando eres parte de un equipo de desarrolladores

K6 brilla en situaciones en las que más de una persona podría estar haciendo el scripting.

Se trata de un punto intermedio en el que los desarrolladores y los probadores pueden comprometerse.

La calidad del software no debería ser responsabilidad exclusiva de los probadores; la calidad debería estar presente en todas las actividades de creación de software. Sin embargo, uno de los retos a la hora de aplicar este concepto es que tradicionalmente ha habido una segmentación en las herramientas y lenguajes utilizados por los miembros del equipo con diferentes funciones. Los desarrolladores utilizan una herramienta; los probadores, otra. Es difícil animar a los desarrolladores a probar y a los probadores a codificar en este entorno, y muchas herramientas de prueba sólo fomentan esta división. Un desarrollador no puede utilizar una herramienta como JMeter para nada más que para hacer pruebas, por lo que el incentivo para invertir el esfuerzo en aprenderla es menor.

K6 salva la brecha trayendo conceptos y características de pruebas a un entorno y lenguaje en el que los desarrolladores ya han dedicado tiempo. Javascript es útil para algo más que para escribir scripts de pruebas de carga, y K6 funciona bien con cualquier IDE o editor de texto. Una experiencia de desarrollador sin fricciones es fundamental para la filosofía de K6.

Es más fácil colaborar en los scripts.

Una vez que ha convencido a los desarrolladores y a los probadores para que contribuyan a los scripts de pruebas de carga, ¿cómo puede hacer un seguimiento de los cambios? ¿Cómo se gestionan los scripts en los que trabajan varias personas al mismo tiempo? Con las pruebas como código, la forma más sencilla es utilizar herramientas de control de versiones como Git, de la misma forma que probablemente ya esté utilizando para el código de su aplicación. Una vez más, no hay que aprender ningún marco o proceso nuevo. La concisión y la portabilidad de K6 realmente demuestran ser una ventaja en situaciones de colaboración. Para ilustrar esto, consideremos un simple script de prueba que contiene algunas cosas: macos/deepLFree.translatedWithDeepL.text

  • Una solicitud GET a nuestro sitio de prueba, https://test.k6.io.
  • Una transacción que llame a esta petición 01_Home.
  • Una comprobación para fallar las respuestas que no sean HTTP 200 o que no tengan el texto Colección de páginas web sencillas adecuadas para las pruebas de carga.
  • Variable think time
  • Lo ejecutaremos como un solo usuario, para una sola iteración. Este es el aspecto de ese script en K6:
import http from 'k6/http';
import { sleep, check } from 'k6';
export default function () {
const res = http.get('https://test.k6.io', { tags: { name: '01_Home' } });
check(res, {
'is status 200': (r) => r.status === 200,
'text verification': (r) =>
r.body.includes('Collection of simple web-pages suitable for load testing'),
});
sleep(Math.random() * 5);
}

También puedes seguir los scripts de JMeter en Git. Este es el aspecto del mismo script en JMeter:

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.3">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</ThreadGroup>
<hashTree>
<TransactionController guiclass="TransactionControllerGui" testclass="TransactionController" testname="01_Home" enabled="true">
<boolProp name="TransactionController.includeTimers">false</boolProp>
<boolProp name="TransactionController.parent">true</boolProp>
</TransactionController>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">test.k6.io</stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.protocol">https</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path"></stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree>
<ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true">
<collectionProp name="Asserion.test_strings">
<stringProp name="-745788246">Collection of simple web-pages suitable for load testing</stringProp>
</collectionProp>
<stringProp name="Assertion.custom_message"></stringProp>
<stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
<boolProp name="Assertion.assume_success">false</boolProp>
<intProp name="Assertion.test_type">16</intProp>
</ResponseAssertion>
<hashTree/>
</hashTree>
</hashTree>
<UniformRandomTimer guiclass="UniformRandomTimerGui" testclass="UniformRandomTimer" testname="Uniform Random Timer" enabled="true">
<stringProp name="ConstantTimer.delay">1000</stringProp>
<stringProp name="RandomTimer.range">4000</stringProp>
</UniformRandomTimer>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>

¿Cuál es más fácil de entender? Si tuviera que modificar el script para añadir una solicitud, ¿en qué formato elegiría hacerlo?

Los scripts en XML hacen que los conflictos en Git sean más probables y cambios en pipelines automatizadas sean mucho más difíciles de localizar.

He colaborado con otros en scripts de JMeter en el pasado, y siempre abrimos los scripts en la GUI. Es mucho más fácil detectar los cambios allí pero eso también creó algunos nuevos problemas.

Cuando quieres algo fácil de mantener

Versión para pruebas de carga

Cuando se incrementan las pruebas de carga a más de un generador de carga, mantener un seguimiento de las versiones de los componentes necesarios asegura que el tráfico de un generador de carga es el mismo que el de otro. El valor de reducir las variables en los experimentos científicos es válido para las pruebas de carga.

Con K6, sólo hay que preocuparse de la versión de K6 y del script. No se requieren otras dependencias. Si usted está usando plugins, usted tendría que seguir esos también, pero como se mencionó anteriormente, los plugins en K6 no son tan necesarios como lo son en algunas otras herramientas y K6 está disponible como una imagen Docker para reducir esos problemas.

Con algo como JMeter, hay más niveles a considerar. Está la versión de JMeter en sí, Java, las versiones de los plugins, y luego el script. Cada nueva capa introduce más cambios para las incompatibilidades. En proyectos anteriores en los que he trabajado, inevitablemente alguien probaba un nuevo plugin y se olvidaba de comentarlo con el equipo, y cualquiera que intentara abrir ese script en su copia de JMeter veía este error:

This is the error that JMeter throws when you attempt to open a test plan that includes a plugin you don't have installed locally El error significa que hay un plugin que el script utiliza y que JMeter no reconoce, pero dependiendo del plugin, no siempre es tan fácil determinar cuál es (en este caso era el Ultimate Thread Group). No querrás que esto ocurra en medio de tu prueba de carga porque has olvidado añadir un plugin a alguno de tus generadores de carga.

Es más fácil vincular el código de prueba con el código de la aplicación.

Si el código de su aplicación está en Javascript, K6 es una herramienta de pruebas de carga que no tiene rival. Puede construir pruebas que estén estrechamente integradas con el código de la aplicación importando objetos y haciendo que sus pruebas interactúen con ellos directamente. Este enfoque reduciría mucho el tiempo dedicado a refactorizar los scripts de prueba cuando se cambian los objetos.

Si ya estás usando VS Code, K6 incluso tiene un plugin para VS Code.

La prueba como el código le da el control

Tener tus scripts como código puro reduce las ambigüedades en el sentido de que no estás limitado por un mal diseño de la interfaz de usuario o por errores en los plugins de terceros. Los scripts de K6 están tipificados en Typescript, por lo que la mayoría de los IDEs soportan el autocompletado mientras estás haciendo scripts - el equivalente en código a los útiles tooltips, excepto que mucho más universal. Los scripts de k6 te dan la libertad de importar y utilizar bibliotecas JS, por lo que puedes construir sobre el código que otros ya han escrito. Aunque K6 no es NodeJS, hay incluso algunos paquetes de NodeJS que puedes agrupar para usarlos con tus scripts.

No hay dependencias externas

K6 no requiere NodeJS ni nada más para ejecutarse, lo que también reduce la probabilidad de errores que puedan afectar a tus scripts. Por ejemplo, como JMeter se ejecuta en Java, también depende de Java. Cuando Java recibe una nueva versión, eso a menudo requiere una actualización de JMeter también. Es comprensible que las versiones de JMeter vayan un poco por detrás de las versiones de Java a medida que los desarrolladores refactorizan el código, pero este desfase puede dar lugar a posibles problemas de seguridad en una versión anterior de Java que pueden quedar sin parchear mientras tanto.

Con K6, el desarrollo puede proceder independientemente de cualquier componente de terceros, por lo que los problemas más importantes pueden abordarse más fácilmente.

Tabla de comparación: JMeter vs K6

FuncionalidadJMeterK6
Escrito enJavaGo
Lenguaje de programaciónLimitado: algo de Java (Groovy, Beanshell, etc.)Javascript
ProtocolosSoporta la mayoría de los protocolos a través de plugins (soporte nativo para HTTP/1.1, SOAP, FTP, JDBC, LDAP, MOM vía JMS, SMTP, POP3, IMAP, shell scripts, TCP, objetos Java).Soporta menos protocolos modernos de forma nativa (HTTP/1.1, HTTP/2, WebSockets, gRPC)
Browser automationSí, usando Selenium/WebDriverSí, usando xk6-browser
Dependencias externasJavaninguna
Utilización de los recursosBajo; Un generador de carga puede simular varios miles de usuarios virtualesMuy bueno; Un generador de carga puede simular decenas de miles de usuarios virtuales
Gestión de la memoriaLa "heap memory" de la JVM debe estar configurada;Utiliza la memoria del generador de carga de forma nativa.
Modelo de hilos1 hilo: 1 usuario virtual; rendimiento más lento, mayor coste de recursos1 Goroutine: 1 Usuario Virtual; Rendimiento más rápido, menor coste de recursos
Facilidad de scriptingCon interfaz gráfica de usuario, con bloques de códigocode-driven; plugin de VSCode
Los umbrales a nivel de pruebaNo, sólo solicitud individual
Formato de los scriptsXMLjavascript.
ColaboraciónDifícil de trabajar simultáneamente; amigable para el probador; necesita la aplicación GUI para editarAmigable para el desarrollador, fácil de versionar; el formato javascript promueve la colaboración
MantenimientoGuiones muy extensos, el formato XML es difícil de leer;Guiones más concisos, JavaScript es fácil de leer.
ComunidadDesde 1998; Muchos tutoriales de terceros; Amplia documentación; No hay comunidad centralDesde 2017; Amplia documentación; Menos tutoriales de terceros; Comunidad oficial
Soporte de pluginsRequiere de plugins para muchas características, pero hay muchos plugins disponiblesLa mayoría de las características son soportadas de forma nativa, pero el soporte de plugins es nuevo y la disponibilidad es escasa
Generación de carga distribuida nativaSí, usando k6 Operator
Informes pre-generadosInformes HTML predeterminados y personalizados; registro a través de escuchasNo hay informes pregenerados incorporados; integración con herramientas de análisis con cuadros de mando de terceros
Sitio webjmeter.apache.orgk6.io
Código fuenteEnlaceEnlace

Conclusión

El mejor consejo, cuando se trata de elegir una herramienta de pruebas de carga, es hacer una prueba de concepto con los candidatos más prometedores. Algunas características o errores pueden resultar más o menos importantes cuando se utilizan en un ciclo de pruebas real. Sin embargo, no hay que dar demasiada importancia a las comparaciones de los resultados de las pruebas de carga de dos herramientas diferentes: cada herramienta registra las métricas de forma diferente, y es más significativo comparar los resultados con ejecuciones anteriores con la misma herramienta. Cuando cambie de herramienta, vuelva a establecer una línea de base en la nueva herramienta cada vez.

Este es un resumen que puede ayudarle a decidir entre JMeter y K6.

Ambas herramientas son buenas para

  • Generar carga a nivel de protocolo en un servidor de aplicaciones mediante el scripting de flujos de usuarios complejos
  • Scripts bien similares a la realidad con el uso de think time dinámico, generación y reutilización de datos de prueba y modelos de carga de trabajo personalizables
  • Documentación de características y consistencia de las versiones

Ninguna de las dos herramientas admite

  • Análisis de resultados detallados (JMeter tiene informes HTML pregenerados y escuchas, pero están lejos de ser ideales). Los usuarios deben esperar integrar los resultados con bases de datos y software de visualización de datos.

JMeter es mejor para:

  • Equipos de pruebas tradicionales
  • Aquellos que buscan una herramienta de pruebas impulsada por la interfaz gráfica de usuario con toneladas de tutoriales de terceros y un amplio soporte de protocolos
  • Usuarios anteriores de herramientas comerciales como LoadRunner y NeoLoad

K6 es mejor para:

  • Equipos de ingeniería colaborativos y multifuncionales donde las pruebas se extienden a través de múltiples roles
  • Aquellos que buscan una herramienta de pruebas de carga sencilla y ligera, pero con todas las funciones
  • Los equipos que buscan integrar las pruebas en los flujos de trabajo de desarrollo existentes y herramienta de integración continua (CI/CD)

Las herramientas de secuencias de comandos de pruebas de carga no son en absoluto la consideración más importante para el éxito de las pruebas de carga. Saber por qué se están realizando las pruebas, cuáles son los requisitos, entender y comunicar los resultados son posiblemente más importantes. La herramienta adecuada le permitirá abordar estas cuestiones con la menor fricción posible. No existe la "mejor" herramienta, sino la más adecuada para su proyecto y su contexto.

Véase también

< Back to all posts