29. Cómo escribir un complemento para JMeter

Introducción de Peter Lin

En más de una ocasión, los usuarios se han quejado de que la documentación para desarrolladores de JMeter está desactualizada y no es muy útil. En un esfuerzo por hacerlo más fácil para los desarrolladores, decidí escribir un sencillo tutorial paso a paso. Cuando le mencioné esto a Mike, tuvo algunas ideas sobre lo que debería cubrir el tutorial.

Antes de sumergirnos en el tutorial, me gustaría decir que escribir un complemento no es necesariamente fácil, incluso para alguien con varios años de experiencia en Java. La primera extensión que escribí para JMeter fue una utilidad simple para analizar los registros de acceso HTTP y generar solicitudes en formato XML. No era realmente un complemento, ya que era una utilidad de línea de comandos independiente. Mi primer complemento real para JMeter fue el muestreador de servicios web. Estaba trabajando en un proyecto .NET y necesitaba hacer una prueba de esfuerzo de un servicio web. La mayoría de las herramientas comerciales disponibles para probar los servicios web .NET apestan y cuestan demasiado. En lugar de gastar varios cientos de dólares en una herramienta de prueba aburrida, o un par de miles de dólares en una buena, decidí que era más fácil y económico escribir un complemento para JMeter.

Después de dos semanas de codificación en mi tiempo libre, tenía un prototipo funcional usando el controlador Apache Soap. Lo envié de nuevo a JMeter y Mike me preguntó si quiero ser un confirmador. Había contribuido parches para Jakarta JSTL y tomcat en el pasado, así que lo consideré un honor. Desde entonces, he escrito la muestra de registros de acceso, el monitor Tomcat 5 y el gráfico de distribución. Desde entonces, Mike ha mejorado enormemente la muestra de registro de acceso y la ha hecho mucho más útil.

Introducción de Mike Stover

Uno de mis principales objetivos al diseñar JMeter era facilitar la escritura de complementos para mejorar tantas funciones de JMeter como fuera posible. Parte del beneficio de ser de código abierto es que muchas personas podrían potencialmente prestar sus esfuerzos para mejorar la aplicación. Tomé la decisión consciente de sacrificar algo de simplicidad en el código para hacer que la escritura de complementos sea una forma de vida para un desarrollador de JMeter.

Si bien algunas personas han profundizado con éxito en el código y han realizado mejoras en JMeter, faltaba un tutorial real sobre cómo hacer esto. Intenté hace mucho tiempo escribir alguna documentación al respecto, pero la mayoría de la gente no lo encontró útil. Con suerte, con la ayuda de Peter, este intento tendrá más éxito.

29.1 Estructura básica de JMeter

JMeter está organizado por protocolos y funcionalidad. Esto se hace para que los desarrolladores puedan crear nuevos archivos jar para un único protocolo sin tener que crear toda la aplicación. Entraremos en los detalles de la construcción de JMeter más adelante en el tutorial. Dado que la mayoría de los desarrolladores de JMeter usan eclipse, el artículo usará el directorio de eclipse como punto de referencia.

Directorio raíz - /eclipse/workspace/apache-jmeter/

Las carpetas dentro de apache-jmeter

compartimiento
contiene los archivos .bat y .sh para iniciar JMeter. También contiene ApacheJMeter.jar y el archivo de propiedades.
construir/docs
El directorio contiene los archivos de documentación de JMeter.
extras
Archivos adicionales relacionados con hormigas
liberación
contiene los archivos jar necesarios para JMeter
libre/ext
contiene los archivos jar principales para JMeter y los protocolos
origen
contiene un subdirectorio para cada protocolo y componente
src/*/prueba
directorio relacionado con la prueba unitaria
xdocs
Archivos XML para documentación. JMeter genera su documentación a partir de XML.

A medida que avanza el tutorial, se proporcionará una explicación de los subdirectorios. Por ahora, concentrémonos en el directorio src .

Las carpetas dentro de src

bshclient
código para el cliente basado en BeanShell
tornillo
código para el protocolo Bolt
componentes
contiene componentes no específicos del protocolo como visualizadores, aserciones, etc.
centro
el código central de JMeter, incluidas todas las interfaces principales y las clases abstractas.
dist
crea un script que crea una distribución
dist-control
código relacionado con la prueba de la distribución. Es el lugar que debe buscar cuando desea actualizar el contenido del archivo fuente/binario resultante.
ejemplos
muestra de ejemplo que demuestra cómo usar el nuevo marco de bean
funciones
funciones estándar utilizadas por todos los componentes
generador
código para generar un plan de prueba con todos los elementos. Se utiliza para probar la distribución.
jorfan
clases de utilidad que proporcionan funciones de utilidad comunes
lanzacohetes
código para ayudar a iniciar y detener JMeter a través de la API
licencias
contiene información sobre las licencias utilizadas en las dependencias de JMeters
protocolo
contiene los diferentes protocolos que admite JMeter
liberar
código relacionado con la liberación de la distribución de JMeter
kit de prueba
código de utilidad para probar
testkit-wiremock
código de utilidad para probar con WireMock

Dentro del directorio de protocolos , se encuentran los componentes específicos del protocolo.

Las carpetas dentro del protocolo.

ftp
componentes para pruebas de carga de servidores ftp
http
componentes para pruebas de carga de servidores web
Java
componentes para pruebas de carga componentes java
jdbc
componentes para pruebas de carga de servidores de bases de datos utilizando JDBC
jms
componentes para pruebas de carga de servidores JMS
junta
componentes para pruebas de carga usando pruebas JUnit
junit-muestra
ejemplos de implementaciones de prueba basadas en JUnit
ldap
componentes para pruebas de carga de servidores LDAP
correo
componentes para pruebas de carga de servidores de correo
nativo
componentes para pruebas de carga OS comandos nativos
tcp
componentes para pruebas de carga de servicios TCP

Como regla general, todas las muestras relacionadas con HTTP residirán en el directorio http . La excepción a la regla es el monitor Tomcat5. Está separado, porque la funcionalidad del monitor es ligeramente diferente a la prueba de esfuerzo o funcional. Eventualmente puede ser reorganizado, pero por ahora está en su propio directorio. En términos de dificultad, escribir visualizadores es probablemente uno de los complementos más difíciles de escribir.

29.2 JMeter Gui – Contrato TestElement

Al escribir cualquier componente de JMeter, hay ciertos contratos que debe tener en cuenta: las formas en que se espera que se comporte un componente de JMeter si se ejecuta correctamente en el entorno de JMeter. Esta sección describe el contrato que debe cumplir la parte GUI de su componente.

El código GUI en JMeter está estrictamente separado del código del elemento de prueba. Por lo tanto, cuando escriba un componente, habrá una clase para el elemento de prueba y otra para la presentación de la GUI. La clase de presentación de GUI no tiene estado en el sentido de que nunca debe aferrarse a una referencia al elemento de prueba (aunque hay excepciones a esto).

Un elemento GUI debe extender la clase abstracta adecuada proporcionada:

  • AbstractSamplerGui
  • ResumenAfirmaciónGui
  • ResumenConfigGui
  • ResumenControladorGui
  • ResumenPostProcesadorGui
  • AbstractPreProcessorGui
  • ResumenVisualizador
  • AbstractTimerGui

Estas clases abstractas proporcionan tanto trabajo de plomería que no extenderlas y, en su lugar, implementar las interfaces directamente no es una opción. Si tienes alguna necesidad urgente de no extender estas clases, entonces puedes unirte a mí en IRC donde puedo convencerte de lo contrario :-).

Entonces, ha extendido la clase GUI apropiada, ¿qué queda por hacer? Sigue estos pasos:

  1. Implementar getLabelResource()
    1. Este método debería devolver el nombre del recurso que representa el título/nombre del componente. El recurso deberá ingresarse en el archivo de propiedades de mensajes de JMeters (y posiblemente también en las traducciones).
  2. Cree su interfaz gráfica de usuario. Sea cual sea el estilo que te guste, diseña tu GUI. Su clase finalmente extiende JPanel , por lo que su diseño debe estar en el ContentPane de su propia clase . No conecte elementos GUI a su clase TestElement a través de acciones y eventos. Deje que el modelo interno de swing se aferre a todos los datos tanto como le sea posible.
    1. Se deben agregar algunas cosas estándar de la GUI a todos los componentes de la GUI de JMeter:
      1. Llama a setBorder(makeBorder()) para tu clase. Esto le dará el borde estándar de JMeter
      2. Agregue el panel de título a través de makeTitlePanel() . Por lo general, esto es lo primero que se agrega a su GUI y debe hacerse en un esquema de diseño vertical de Box, o con la clase VerticalLayout de JMeter. Aquí hay un ejemplo del método init() :
        init vacío privado () {
            setLayout(nuevo BorderLayout());
            establecerBorde(hacerBorde());
            Caja caja = Caja.createVerticalBox();
            box.add(makeTitlePanel());
            box.add(makeSourcePanel());
            agregar (caja, diseño de borde. NORTE);
            add(makeParameterPanel(),BorderLayout.CENTER);
        }
        
  3. Implementar configuración de vacío público (TestElement el)
    1. Asegúrese de llamar a super.configure(e) . Esto completará algunos de los datos por usted, como el nombre del elemento.
    2. Utilice este método para configurar datos en sus elementos GUI. Ejemplo:
      configurar vacío público (elemento de prueba el) {
          super.configure(el);
          useHeaders.setSelected(
                  el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
          useBody.setSelected(
                  !el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
          camporegex.setText(
                  el.getPropertyAsString(RegexExtractor.REGEX));
          templateField.setText(
                  el.getPropertyAsString(RegexExtractor.TEMPLATE));
          campopredeterminado.setText(
                  el.getPropertyAsString(RegexExtractor.DEFAULT));
          MatchNumberField.setText(
                  el.getPropertyAsString(RegexExtractor.MATCH_NUM));
          refNombreCampo.setText(
                  el.getPropertyAsString(RegexExtractor.REFNAME));
      }
      
    3. Implemente public void modifyTestElement(TestElement e) . Aquí es donde mueve los datos de sus elementos GUI al TestElement . Es el reverso lógico del método anterior.
      1. Llame a super.configureTestElement(e) . Esto se encargará de algunos datos predeterminados por usted.
      2. Ejemplo:
        public void modificarTestElement(TestElement e) {
            super.configureTestElement(e);
            e.setProperty(nueva propiedad booleana(
                    RegexExtractor.USEHEADERS,
                    useHeaders.isSelected()));
            e.setProperty(RegexExtractor.MATCH_NUMBER,
                    MatchNumberField.getText());
            if (e instancia de RegexExtractor) {
                RegexExtractor expresión regular = (RegexExtractor)e;
                expresión regular.setRefName(refNameField.getText());
                Regex.setRegex(regexField.getText());
                regex.setTemplate(templateField.getText());
                regex.setDefaultValue(defaultField.getText());
            }
        }
        
    4. Implemente TestElement público createTestElement() . Este método debería crear una nueva instancia de su clase TestElement y luego pasarla al método modifyTestElement(TestElement) que creó anteriormente
      elemento de prueba público createTestElement () {
          Extractor RegexExtractor = nuevo RegexExtractor();
          modificar elemento de prueba (extractor);
          extractor de retorno;
      }
      

La razón por la que no puede mantener una referencia para su elemento de prueba es porque JMeter reutiliza instancias de objetos de clase GUI para múltiples elementos de prueba. Esto ahorra mucha memoria. También hace que sea increíblemente fácil escribir la parte de la GUI de su nuevo componente. Todavía tiene que luchar con el diseño en Swing, pero no tiene que preocuparse por crear los eventos y acciones correctos para obtener los datos de los elementos de la GUI en TestElement , donde puede ser útil. JMeter sabe cuándo llamar a su configuración y modificar los métodos TestElement donde puede hacerlo de una manera muy sencilla.

Sin embargo, Escribir visualizadores es un caso especial.

29.3 Escribiendo un Visualizador

La prueba de carga en modo GUI es una mala práctica, no debe desarrollar dicho complemento. Eche un vistazo a componentes más actualizados como:

De los tipos de componentes, los visualizadores requieren mayor profundidad en Swing que algo como controladores, funciones o muestreadores. Puede encontrar la fuente completa del gráfico de distribución en components/org/apache/jmeter/visualizers/ . El visualizador gráfico de distribución se divide en dos clases.

DistribuciónGraphVisualizerDistributionGraphVisualizer
visualizador que instancia JMeter
Gráfico de distribución
JComponent que dibuja el gráfico real

La forma más fácil de escribir un visualizador es hacer lo siguiente:

  1. Extienda org.apache.jmeter.visualizers.gui.AbstractVisualizer
  2. Implemente cualquier necesidad de interfaz adicional para devolución de llamada y notificación de eventos. Por ejemplo, DistributionGraphVisualizer implementa las siguientes interfaces:
    • Visualizador de imágenes
    • ItemListener : según los comentarios en la clase, ItemListener está desactualizado y ya no se usa.
    • GraphListener
    • Borrable

AbstractVisualizer proporciona algunas funciones comunes, que utilizan la mayoría de los visualizadores como Graph Results . La funcionalidad común proporcionada por la clase abstracta incluye:

  • Configurar elementos de prueba: esto significa que crea un nuevo ResultCollector , establece el archivo y establece el registro de errores
  • Crear el menú de stock
  • Actualice el elemento de prueba cuando se realicen cambios
  • Crear un panel de archivos para el archivo de registro
  • Crear el panel de título

En algunos casos, es posible que no desee mostrar el menú del cuadro de texto del archivo. En ese caso, puede anular el método init() . Aquí está la implementación de DistributionGraphVisualizer .

/**
 * Inicializar la GUI.
 */
init vacío privado () {
    this.setLayout(nuevo BorderLayout());

    // PANEL PRINCIPAL
    Margen de borde = new EmptyBorder(10, 10, 5, 10);
    this.setBorder(margen);

    // Configure el gráfico con encabezado, pie de página, eje Y y visualización del gráfico
    JPanel graphPanel = new JPanel(new BorderLayout());
    GraphPanel.add(createGraphPanel(), BorderLayout.CENTER);
    graphPanel.add(createGraphInfoPanel(), BorderLayout.SOUTH);

    // Agrega el panel principal y el gráfico
    this.add(makeTitlePanel(), BorderLayout.NORTE);
    this.add(graphPanel, BorderLayout.CENTER);
}

Lo primero que hace el método init es crear un nuevo BorderLayout . Dependiendo de cómo desee diseñar los widgets, es posible que desee utilizar un administrador de diseño diferente. Tenga en cuenta que usar diferentes administradores de diseño es para expertos.

Lo segundo que hace el método init es crear un borde. Si desea aumentar o disminuir el borde, cambie los cuatro valores enteros. Cada valor entero representa píxeles. Si desea que su visualizador no tenga bordes, omita las líneas 8 y 9. La línea 13 llama a createGraphPanel , que es responsable de configurar y agregar DistributionGraph al visualizador.

componente privado createGraphPanel() {
    PanelGráfico = new JPanel();
    GraphPanel.setBorder(BorderFactory.createBevelBorder(
    BevelBorder.LOWERED,Color.lightGray,Color.darkGray));
    panelgrafo.add(grafo);
    panelgrafo.setBackground(Color.blanco);
    volver panel gráfico;
}

En la línea 5, el componente gráfico se agrega al panel de gráficos. El constructor es donde se crea una nueva instancia de DistributionGraph .

Public DistributionGraphVisualizer() {
    modelo = new SamplingStatCalculator("Distribución");
    gráfico = nuevo gráfico de distribución (modelo);
    gráfico.setBackground(Color.blanco);
    en eso();
}

El constructor de DistributionGraphVisualizer es responsable de crear el modelo y el gráfico. Cada vez que se completa un nuevo resultado, el motor pasa el resultado a todos los oyentes llamando a add(SampleResult res) . El visualizador pasa el nuevo SampleResult al modelo.

agregar vacío sincronizado público (SampleResult res) {
    modelo.addSample(res);
    updateGui(modelo.getCurrentSample());
}

En el caso de DistributionGraphVisualizer , el método add en realidad no actualiza el gráfico. En su lugar, llama a updateGui en la línea tres.

updateGui nulo sincronizado público (Muestra s) {
    // Hemos recibido una muestra más
    si (retraso == contador) {
        actualizarGui();
        contador = 0;
    } más {
        contador++;
    }
}

A diferencia de GraphVisualizer , el gráfico de distribución intenta mostrar cómo se agrupan los resultados; por lo tanto, DistributionGraphVisualizer retrasa la actualización. El retraso predeterminado es de 10 resultados de muestra.

public sincronizado void updateGui() {
    si (gráfico.obtenerAncho() < 10) {
        gráfico.setPreferredSize(
                nueva Dimensión (getWidth() - 40,
                obtenerAltura() - 160));
    }
    panelgrafo.updateUI();
    gráfico.repintar();
}

Se supone que las líneas 2 a 3 cambian el tamaño del gráfico, si el usuario cambia el tamaño de la ventana o arrastra el divisor. La línea 7 actualiza el panel que contiene el gráfico. La línea 8 activa la actualización de DistributionGraph . Antes de cubrir la escritura de gráficos, hay un par de métodos importantes que debe implementar el visualizador.

cadena pública getLabelResource() {
    devuelve "distribution_graph_title";
}

El recurso de etiqueta recupera el nombre del visualizador del archivo de propiedades. El archivo se encuentra en core/org/apache/jmeter/resources . Es mejor no codificar el nombre del visualizador. El archivo Message.properties está organizado alfabéticamente, por lo que agregar una nueva entrada es fácil.

vacío sincronizado público claro () {
    este.gráfico.claro();
    modelo.claro();
    repintar();
}

Cada componente en JMeter debe implementar la lógica para el método clear() . Si esto no se hace, el componente no borrará la interfaz de usuario o el modelo cuando el usuario intente borrar los últimos resultados y ejecutar una nueva prueba. Si no se implementa clear, puede provocar una pérdida de memoria.

JComponent público getPrintableComponent() {
    devuelve este.graphPanel;
}

El último método que deben implementar los visualizadores es getPrintableComponent() . El método es responsable de devolver el JComponent que se puede guardar o imprimir. Esta función se agregó recientemente para que los usuarios puedan guardar una captura de pantalla de cualquier visualizador.

29.4 Escuchador de gráficos

La prueba de carga en modo GUI es una mala práctica, no debe desarrollar dicho complemento. Eche un vistazo a componentes más actualizados como:

Los visualizadores deben implementar GraphListener . Esto se hace para simplificar la adición de nuevas instancias de muestra a los oyentes. Como regla general, si el gráfico personalizado no traza cada muestra individual, no necesita implementar la interfaz.

interfaz pública GraphListener {
    public void updateGui(Muestra s);
    public void updateGui();
}

El método importante en la interfaz es updateGui(Sample s) . Desde DistributionGraphVisualizer , vemos que llama a graph.repaint() para actualizar el gráfico. En la mayoría de los casos, la implementación de updateGui(Sample s) debería hacer exactamente eso. ItemListenerVisualizers generalmente no necesita implementar esta interfaz. La interfaz se utiliza con cuadros combinados, casillas de verificación y listas. Si su visualizador usa uno de estos y necesita saber cuándo se actualizó, el visualizador deberá implementar la interfaz. Para ver un ejemplo de cómo implementar la interfaz, consulte GraphVisualizer .

29.5 Escribir gráficos personalizados

La prueba de carga en modo GUI es una mala práctica, no debe desarrollar dicho complemento. Eche un vistazo a componentes más actualizados como:

Para aquellos nuevos en Swing y que aún no han escrito JComponents personalizados, sugeriría obtener un libro sobre Swing y tener una buena idea de cómo funcionan los widgets de Swing. Este tutorial no intentará explicar los conceptos básicos de Swing y asume que el lector ya está familiarizado con el patrón de diseño Swing API y MVC (Model View Controller). Desde el constructor de DistributionGraphVisualizer , vemos que se crea una nueva instancia de DistributionGraph con una instancia del modelo.

Gráfico de distribución público (modelo SamplingStatCalculator) {
    este();
    establecerModelo(modelo);
}

La implementación del método setModel es sencilla.

setModel vacío privado (modelo de objeto) {
    this.model = (SamplingStatCalculator) modelo;
    repintar();
}

Observe que el método llama a repintar después de establecer el modelo. Si no se llama a repintar , puede hacer que la GUI no dibuje el gráfico. Una vez que comience la prueba, el gráfico se volverá a dibujar, por lo que llamar a repintar no es crítico.

public void paintComponent(Gráficos g) {
    super.paintComponent(g);
    final SamplingStatCalculator m = este.modelo;
    sincronizado (m) {
        dibujarMuestra(m, g);
    }
}

El otro aspecto importante de actualizar el widget es colocar la llamada a drawSample dentro de un bloque sincronizado. Si drawSample no estuviera sincronizado, JMeter lanzaría una ConcurrentModificationException en tiempo de ejecución. Según el plan de prueba, puede haber una docena o más de subprocesos que agreguen resultados al modelo. El bloque sincronizado no afecta la precisión de cada solicitud individual y la medición del tiempo, pero sí afecta la capacidad de JMeter para generar grandes cargas. A medida que aumenta la cantidad de subprocesos en un plan de prueba, aumenta la probabilidad de que un subproceso tenga que esperar hasta que el gráfico termine de volver a dibujarse antes de iniciar una nueva solicitud. Aquí está la implementación de drawSample .

drawSample vacío privado (modelo SamplingStatCalculator, Gráficos g) {
    ancho = obtenerAncho();
    altura doble = (doble)obtenerAltura() - 1.0;

    // primero dibujemos la grilla
    para (int y=0; y < 4; y++){
        int q1 = (int)(altura - (altura * 0.25 * y));
        g.setColor(Color.gris claro);
        g.drawLine(xborder,q1,ancho,q1);
        g.setColor(Color.negro);
        g.drawString(String.valueOf((25 * y) + "%"),0,q1);
    }
    g.setColor(Color.negro);
    // dibujar el eje X
    g.drawLine(xborder,(int)alto,ancho,(int)alto);
    // dibujar el eje Y
    g.drawLine(xborder,0,xborder,(int)altura);
    // el plan de prueba debe tener más de 200 muestras
    // para que genere una distribución medianamente decente
    // grafico. Cuanto mayor sea la muestra, mejor será
    // resultados.
    if (modelo != nulo && modelo.getCount() > 50) {
        // ahora dibuja el gráfico de barras
        Número noventa = modelo.getPercentPoint(0.90);
        Número cincuenta = modelo.getPercentPoint(0.50);
        total = modelo.getCount();
        Valores de colección = model.getDistribution().values();
        Objeto[] objval = nuevo Objeto[valores.tamaño()];
        objval = valores.toArray(objval);
        //ordenamos los objetos
        Arrays.sort(objval,new NumberComparator());
        int len ​​= objval.length;
        for (int cuenta=0; cuenta < len; cuenta++) {
            // calcular la altura
            Número[] num = (Número[])objval[cuenta];
            doble iper = (doble)num[1].intValue() / (doble)total;
            doble ialtura = altura * iper;
            // si la altura es menor que uno, lo establecemos
            // a un píxel
            si (ialtura < 1) {
                ialtura = 1,0;
            }
            int ix = (cuenta * 4) + xborder + 5;
            int daltura = (int)(altura - ialtura);
            g.setColor(Color.azul);
            g.drawLine(ix -1,(int)altura,ix -1,daltura);
            g.drawLine(ix,(int)altura,ix,daltura);
            g.setColor(Color.negro);
            // dibuja una línea roja para el 90% del punto
            if (num[0].longValue() == noventa.longValue()) {
                g.setColor(Color.rojo);
                g.drawLine(ix,(int)altura,ix,55);
                g.drawLine(ix,(int)35,ix,0);
                g.drawString("90%",ix - 30,20);
                g.drawString(
                        Cadena.valueOf(num[0].longValue()),
                        ix + 8, 20);
            }
            // dibuja una línea naranja para el 50% del punto
            if (num[0].longValue() == cincuenta.longValue()) {
                g.setColor(Color.naranja);
                g.drawLine(ix,(int)altura,ix,30);
                g.drawString("50%",ix - 30,50);
                g.drawString(
                        Cadena.valueOf(num[0].longValue()),
                        ix + 8, 50);
            }
        }
    }
}

En general, la representación del gráfico debería ser bastante rápida y no debería ser un cuello de botella. Como regla general, es una buena idea perfilar complementos personalizados. La única forma de asegurarse de que un visualizador no sea un cuello de botella es ejecutarlo con una herramienta como Borland OptimizeIt. Una buena manera de probar un complemento es crear un plan de prueba simple y ejecutarlo. El comportamiento de recolección de basura y montón debe ser regular y predecible.

29.6 Crear un complemento TestBean para JMeter

En esta parte, pasaremos por el proceso de creación de un componente simple para JMeter que utiliza el nuevo marco TestBean .

Este componente será un elemento de lectura de archivos CSV que permitirá a los usuarios variar fácilmente sus datos de entrada utilizando archivos CSV. Para usar este tutorial de manera más efectiva, abra los tres archivos que se especifican a continuación (que se encuentran en el directorio src/components de JMeter ).

  1. Elija un paquete y cree tres archivos:
    • [Nombre del componente].java (org.apache.jmeter.config.CSVDataSet.java)
    • [Nombre del componente]BeanInfo.java (org.apache.jmeter.config.CSVDataSetBeanInfo.java)
    • [Nombre del componente]Resources.properties (org.apache.jmeter.config.CSVDataSetResources.properties)
  2. CSVDataSet.java debe implementar la interfaz TestBean . Además, extenderá ConfigTestElement e implementará LoopIterationListener .
    • TestBean es una interfaz de marcador, por lo que no hay métodos para implementar.
    • Extender ConfigTestElement hará que nuestro componente sea un elemento de configuración en un plan de prueba. Al extender diferentes clases abstractas, puede controlar el tipo de elemento que será su componente (es decir , AbstractSampler , AbstractVisualizer , GenericController , etc.) más fácil).
  3. CSVDataSetBeanInfo.java debe extender org.apache.jmeter.testbeans.BeanInfoSupport
    • crea un constructor de parámetro cero en el que llamamos super(CSVDataSet.class);
    • volveremos a esto.
  4. CSVDataSetResources.properties : en blanco por ahora
  5. Implemente su lógica especial para su clase de complemento.
    1. CSVDataSet leerá un solo archivo CSV y almacenará los valores que encuentre en el contexto de ejecución de JMeter. El usuario definirá el archivo, definirá los nombres de las variables para cada " columna ". CSVDataSet abrirá el archivo cuando comience la prueba y lo cerrará cuando finalice (por lo tanto, implementamos TestListener ). El CSVDataSet actualizará el contenido de las variables para cada subproceso de prueba y para cada iteración a través de su controlador principal, leyendo nuevas líneas en el archivo. Cuando lleguemos al final del archivo, comenzaremos de nuevo desde el principio. Al implementar un TestBean, preste mucha atención a sus propiedades. Estas propiedades se convertirán en la base de un formulario GUI mediante el cual los usuarios configurarán el elemento CSVDataSet .
    2. JMeter clonará su elemento cuando comience la prueba. Cada hilo obtendrá su propia instancia. Sin embargo, tendrá la oportunidad de controlar cómo se realiza la clonación, si lo necesita.
    3. Propiedades: nombre de archivo , nombres de variables . Con getters y setters públicos.
      • el nombre del archivo se explica por sí mismo, contendrá el nombre del archivo CSV que leeremos
      • variableNames es una cadena que permitirá a un usuario ingresar los nombres de las variables a las que asignaremos valores. ¿Por qué una cadena? ¿Por qué no una colección? ¿Seguramente los usuarios necesitarán ingresar múltiples (y un número desconocido de) nombres de variables? Cierto, pero si usáramos una Lista o una Colección, tendríamos que escribir un componente GUI para manejar las colecciones, y solo quiero hacer esto rápidamente. En su lugar, dejaremos que los usuarios ingresen una lista de nombres de variables delimitada por comas.
    4. Luego implementé el método IterationStart de la interfaz LoopIterationListener . El punto de este "evento" es que su componente recibe una notificación cuando la prueba ha ingresado a su controlador principal. Para nuestros propósitos, cada vez que se ingrese el controlador principal de CSVDataSet , leeremos una nueva línea del archivo de datos y estableceremos las variables. Por lo tanto, para un controlador regular, cada bucle a través de la prueba dará como resultado la lectura de un nuevo conjunto de valores. Para un controlador de bucle, cada iteración hará lo mismo. Cada subproceso de prueba también obtendrá valores diferentes.
  6. Configuración de sus elementos GUI en CSVDataSetBeanInfo :
    • Puede crear agrupaciones para las propiedades de su componente. Cada agrupación que cree necesita una etiqueta y una lista de nombres de propiedades para incluir en esa agrupación. Es decir:
      createPropertyGroup("csv_data",
              new String[] { "nombre de archivo", "nombres de variables" });
      
    • Crea una agrupación denominada csv_data que incluirá elementos de entrada de la GUI para las propiedades filename y variableNames de CSVDataSet . Luego, necesitamos definir qué tipo de propiedades queremos que sean:
      p = propiedad ("nombre de archivo");
      p.setValue(NO_UNDEFINED, Boolean.TRUE);
      p.setValue(DEFAULT, "");
      p.setValue(NOT_EXPRESSION, Boolean.TRUE);
      
      p = propiedad("nombresdevariable");
      p.setValue(NO_UNDEFINED, Boolean.TRUE);
      p.setValue(DEFAULT, "");
      p.setValue(NOT_EXPRESSION, Boolean.TRUE);
      
      Básicamente, esto crea dos propiedades cuyo valor no puede ser nulo y cuyos valores predeterminados son "" . Hay varios atributos de este tipo que se pueden establecer para cada propiedad. Aquí hay un resumen:
      NO_INDEFINIDO
      La propiedad no se dejará nula .
      DEFECTO
      Se deben proporcionar valores predeterminados si NOT_UNDEFINED es verdadero .
      NOT_EXPRESSION
      El valor no se analizará para las funciones si esto es cierto .
      NO OTRO
      Este no es un campo de entrada de formato libre: se debe proporcionar una lista de valores.
      ETIQUETAS
      Con un String[] como valor, esto configura una lista predefinida de valores aceptables, y JMeter creará una selección desplegable.
      Además, se puede especificar un editor de propiedades personalizado para una propiedad:
      p.setPropertyEditorClass(FileEditor.class);
      
      Esto creará una entrada de texto más un botón de exploración que abre un cuadro de diálogo para buscar un archivo. Por lo general, no se necesitan configuraciones de propiedades complejas, como ahora. Para ver un ejemplo más complejo, consulte org.apache.jmeter.protocol.http.sampler.AccessLogSamplerBeanInfo
  7. Definición de sus cadenas de recursos. En CSVDataSetResources.properties tenemos que definir todos nuestros recursos de cadena. Para proporcionar traducciones, se crearían archivos adicionales como CSVDataSetResources_ja.properties y CSVDataSetResources_de.properties . Para nuestro componente, debemos definir los siguientes recursos:
    nombre para mostrar
    Esto proporcionará un nombre para el elemento que aparecerá en los menús.
    csv_data.displayName
    creamos una agrupación de propiedades llamada csv_data , por lo que debemos proporcionar una etiqueta para la agrupación
    nombre de archivo.displayName
    una etiqueta para el elemento de entrada de nombre de archivo.
    filename.breveDescripción
    una propaganda de texto de ayuda similar a una información sobre herramientas.
    NombresDeVariables.displayName
    una etiqueta para el elemento de entrada de nombre de variable.
    variableNames.breveDescripción
    información sobre herramientas para el elemento de entrada variableNames .
  8. Depure su componente.

29.6 Construyendo JMeter

JMeter usa Gradle para compilar y construir la distribución. JMeter tiene varias tareas definidas, lo que facilita a los desarrolladores la construcción del proyecto completo. Para aquellos que no están familiarizados con Gradle, es una herramienta de compilación similar a la de Unix. Se proporciona una lista de las tareas de Gradle con una breve descripción en gradle.md , que se puede encontrar en el directorio de origen raíz.

Aquí hay algunos comandos de ejemplo.

./gradlew runGui
Cree e inicie la GUI de JMeter
./gradlew createDist
Cree el proyecto y copie los archivos jar relevantes en la carpeta ./lib
./gradlew :src:dist:vista previaSitio
Crea una vista previa de un sitio en ./build/docs/site
Go to top