29. Como escrever um plugin para JMeter

Introdução de Peter Lin

Em mais de uma ocasião, os usuários reclamaram que a documentação do desenvolvedor do JMeter está desatualizada e não é muito útil. Em um esforço para tornar isso mais fácil para os desenvolvedores, decidi escrever um tutorial passo a passo simples. Quando mencionei isso para Mike, ele teve algumas ideias sobre o que o tutorial deveria cobrir.

Antes de mergulharmos no tutorial, gostaria de dizer que escrever um plugin não é necessariamente fácil, mesmo para alguém com vários anos de experiência em Java. A primeira extensão que escrevi para o JMeter foi um utilitário simples para analisar logs de acesso HTTP e produzir solicitações no formato XML. Não era realmente um plugin, já que era um utilitário de linha de comando autônomo. Meu primeiro plugin real para o JMeter foi o webservice sampler. Eu estava trabalhando em um projeto .NET e precisava fazer um teste de estresse em um webservice. A maioria das ferramentas comerciais disponíveis para testar webservices .NET são ruins e custam muito caro. Em vez de gastar várias centenas de dólares por uma ferramenta de teste ruim, ou alguns milhares de dólares por uma boa, decidi que era mais fácil e barato escrever um plugin para o JMeter.

Após duas semanas de codificação no meu tempo livre, eu tinha um protótipo funcional usando o driver Apache Soap. Enviei de volta ao JMeter e Mike me perguntou se eu quero ser um committer. Eu havia contribuído com patches para Jakarta JSTL e tomcat no passado, então considerei uma honra. Desde então, escrevi o amostrador de log de acesso, o monitor Tomcat 5 e o gráfico de distribuição. Desde então, Mike melhorou tremendamente o amostrador de log de acesso e o tornou muito mais útil.

Introdução de Mike Stover

Um dos meus principais objetivos ao projetar o JMeter foi facilitar a escrita de plugins para aprimorar o maior número possível de recursos do JMeter. Parte do benefício de ser de código aberto é que muitas pessoas podem dedicar seus esforços para melhorar o aplicativo. Tomei uma decisão consciente de sacrificar um pouco de simplicidade no código para tornar a escrita de plugins um modo de vida para um desenvolvedor JMeter.

Embora algumas pessoas tenham cavado com sucesso direto no código e feito melhorias no JMeter, falta um tutorial real sobre como fazer isso. Há muito tempo tentei escrever alguma documentação sobre isso, mas a maioria das pessoas não achou útil. Espero que, com a ajuda de Peter, essa tentativa seja mais bem-sucedida.

29.1 Estrutura básica do JMeter

JMeter é organizado por protocolos e funcionalidades. Isso é feito para que os desenvolvedores possam construir novos jars para um único protocolo sem ter que construir o aplicativo inteiro. Entraremos nos detalhes da construção do JMeter posteriormente no tutorial. Como a maioria dos desenvolvedores do JMeter usa o eclipse, o artigo usará o diretório do eclipse como ponto de referência.

Diretório raiz - /eclipse/workspace/apache-jmeter/

As pastas dentro do apache-jmeter

caixa
contém os arquivos .bat e .sh para iniciar o JMeter. Ele também contém ApacheJMeter.jar e arquivo de propriedades
compilação/documentos
contém os arquivos de documentação do JMeter
extras
arquivos extras relacionados a formigas
lib
contém os arquivos jar necessários para o JMeter
lib/ext
contém os arquivos jar principais para JMeter e os protocolos
src
contém subdiretório para cada protocolo e componente
src/*/teste
diretório relacionado ao teste de unidade
xdocs
Arquivos XML para documentação. O JMeter gera sua documentação a partir de XML.

À medida que o tutorial avança, será fornecida uma explicação dos subdiretórios. Por enquanto, vamos focar no diretório src .

As pastas dentro do src

bshclient
código para o cliente baseado em BeanShell
parafuso
código para o protocolo Bolt
componentes
contém componentes não específicos do protocolo, como visualizadores, asserções, etc.
essencial
o código principal do JMeter, incluindo todas as interfaces principais e classes abstratas.
distância
constrói script que cria uma distribuição
verificação de distância
código relacionado ao teste da distribuição. É o local a procurar quando pretende actualizar o conteúdo do arquivo fonte/binário resultante
exemplos
amostrador de exemplo demonstrando como usar a nova estrutura de bean
funções
funções padrão usadas por todos os componentes
gerador
código para gerar um plano de teste com todos os elementos. Usado para testar a distribuição
jorphan
classes utilitárias que fornecem funções utilitárias comuns
lançador
código para ajudar a iniciar e parar o JMeter através da API
licenças
contém informações sobre as licenças usadas nas dependências do JMeters
protocolo
contém os diferentes protocolos que o JMeter suporta
liberar
código relacionado ao lançamento da distribuição JMeter
kit de teste
código utilitário para teste
testkit-wiremock
código utilitário para teste com WireMock

Dentro do diretório do protocolo , estão os componentes específicos do protocolo.

As pastas dentro do protocolo

ftp
componentes para testes de carga de servidores ftp
http
componentes para servidores web de teste de carga
Java
componentes para testes de carga de componentes java
jdbc
componentes para servidores de banco de dados de teste de carga usando JDBC
jms
componentes para testes de carga de servidores JMS
junho
componentes para teste de carga usando testes JUnit
amostra-junta
exemplos para implementações de teste baseadas em JUnit
ldap
componentes para testes de carga de servidores LDAP
correspondência
componentes para servidores de e-mail de teste de carga
nativo
componentes para testes de carga de comandos nativos do SO
tcp
componentes para testes de carga de serviços TCP

Como regra geral, todos os samplers relacionados ao HTTP residirão no diretório http . A exceção à regra é o monitor Tomcat5. É separado, porque a funcionalidade do monitor é ligeiramente diferente do teste de estresse ou funcional. Pode eventualmente ser reorganizado, mas por enquanto está em seu próprio diretório. Em termos de dificuldade, escrever visualizadores é provavelmente um dos plugins mais difíceis de escrever.

29.2 JMeter Gui – Contrato TestElement

Ao escrever qualquer componente JMeter, existem certos contratos que você deve estar ciente – maneiras como um componente JMeter deve se comportar se for executado corretamente no ambiente JMeter. Esta seção descreve o contrato que a parte GUI de seu componente deve cumprir.

O código GUI no JMeter é estritamente separado do código do Elemento de Teste. Portanto, quando você escreve um componente, haverá uma classe para o Elemento de Teste e outra para a apresentação da GUI. A classe de apresentação da GUI é sem estado no sentido de que nunca deve se prender a uma referência ao Elemento de Teste (existem exceções para isso).

Um elemento GUI deve estender a classe abstrata apropriada fornecida:

  • AbstractSamplerGui
  • AbstractAssertionGui
  • AbstractConfigGui
  • AbstractControllerGui
  • AbstractPostProcessorGui
  • AbstractPreProcessorGui
  • Visualizador abstrato
  • AbstractTimerGui

Essas classes abstratas fornecem tanto trabalho de encanamento para você que não estendê-las e, em vez disso, implementar as interfaces diretamente dificilmente é uma opção. Se você tiver alguma necessidade urgente de não estender essas aulas, então você pode se juntar a mim no IRC onde eu posso convencê-lo do contrário :-).

Então, você estendeu a classe GUI apropriada, o que resta fazer? Siga esses passos:

  1. Implemente getLabelResource()
    1. Este método deve retornar o nome do recurso que representa o título/nome do componente. O recurso terá que ser inserido no arquivo JMeters messages.properties (e possivelmente traduções também).
  2. Crie sua GUI. Seja qual for o estilo que você gosta, faça o layout de sua GUI. Sua classe finalmente estende JPanel , então seu layout deve estar no próprio ContentPane de sua classe . Não conecte elementos GUI à sua classe TestElement por meio de ações e eventos. Deixe o modelo interno do swing agarrar-se a todos os dados o máximo que puder.
    1. Algumas coisas padrão da GUI devem ser adicionadas a todos os componentes da GUI do JMeter:
      1. Chame setBorder(makeBorder()) para sua classe. Isso dará a borda JMeter padrão
      2. Adicione o painel de título via makeTitlePanel() . Normalmente esta é a primeira coisa adicionada à sua GUI, e deve ser feita em um esquema de layout vertical Box, ou com a classe VerticalLayout do JMeter. Aqui está um exemplo de método init() :
        private void init() {
            setLayout(new BorderLayout());
            setBorder(fazerBorder());
            Caixa caixa = Caixa.createVerticalBox();
            box.add(makeTitlePanel());
            box.add(makeSourcePanel());
            add(caixa,BorderLayout.NORTH);
            add(makeParameterPanel(),BorderLayout.CENTER);
        }
        
  3. Implemente a configuração public void (TestElement el)
    1. Certifique-se de chamar super.configure(e) . Isso preencherá alguns dos dados para você, como o nome do elemento.
    2. Use este método para definir dados em seus elementos GUI. Exemplo:
      public void configure(TestElement el) {
          super.configure(el);
          useHeaders.setSelected(
                  el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
          useBody.setSelected(
                  !el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
          regexField.setText(
                  el.getPropertyAsString(RegexExtractor.REGEX));
          templateField.setText(
                  el.getPropertyAsString(RegexExtractor.TEMPLATE));
          defaultField.setText(
                  el.getPropertyAsString(RegexExtractor.DEFAULT));
          matchNumberField.setText(
                  el.getPropertyAsString(RegexExtractor.MATCH_NUM));
          refNomeCampo.setText(
                  el.getPropertyAsString(RegexExtractor.REFNAME));
      }
      
    3. Implemente public void modifyTestElement(TestElement e) . É aqui que você move os dados de seus elementos GUI para o TestElement . É o inverso lógico do método anterior.
      1. Chame super.configureTestElement(e) . Isso cuidará de alguns dados padrão para você.
      2. Exemplo:
        public void modifiqueTestElement(TestElement e) {
            super.configureTestElement(e);
            e.setProperty(new BooleanProperty(
                    RegexExtractor.USEHEADERS,
                    useHeaders.isSelected()));
            e.setProperty(RegexExtractor.MATCH_NUMBER,
                    matchNumberField.getText());
            if (e instanceof RegexExtractor) {
                RegexExtractor regex = (RegexExtractor)e;
                regex.setRefName(refNameField.getText());
                regex.setRegex(regexField.getText());
                regex.setTemplate(templateField.getText());
                regex.setDefaultValue(defaultField.getText());
            }
        }
        
    4. Implemente público TestElement createTestElement() . Este método deve criar uma nova instância de sua classe TestElement e, em seguida, passá-la para o método modifyTestElement(TestElement) que você criou acima
      public TestElement createTestElement() {
          Extrator RegexExtractor = new RegexExtractor();
          modifiqueTestElement(extrator);
          extrator de retorno;
      }
      

A razão pela qual você não pode manter uma referência para seu Elemento de Teste é porque o JMeter reutiliza a instância de objetos de classe GUI para vários Elementos de Teste. Isso economiza muita memória. Também torna incrivelmente fácil escrever a parte GUI do seu novo componente. Você ainda tem que lutar com o layout no Swing, mas não precisa se preocupar em criar os eventos e ações corretos para obter os dados dos elementos da GUI no TestElement , onde isso pode ser útil. O JMeter sabe quando chamar seus métodos configure e modifyTestElement onde você pode fazer isso de uma maneira muito direta.

No entanto, escrever visualizadores é um caso especial.

29.3 Escrevendo um Visualizador

O teste de carga no modo GUI é uma prática ruim, você não deve desenvolver esse plug-in. Dê uma olhada em componentes mais atualizados como:

Dos tipos de componentes, os visualizadores requerem maior profundidade no Swing do que algo como controladores, funções ou amostradores. Você pode encontrar a fonte completa do gráfico de distribuição em components/org/apache/jmeter/visualizers/ . O visualizador de gráfico de distribuição é dividido em duas classes.

DistributionGraphVisualizer
visualizador que o JMeter instancia
Gráfico de distribuição
JComponent que desenha o gráfico real

A maneira mais fácil de escrever um visualizador é fazer o seguinte:

  1. Estender org.apache.jmeter.visualizers.gui.AbstractVisualizer
  2. Implemente quaisquer interfaces adicionais necessárias para retorno de chamada e notificação de eventos. Por exemplo, o DistributionGraphVisualizer implementa as seguintes interfaces:
    • ImageVisualizer
    • ItemListener – de acordo com os comentários da classe, o ItemListener está desatualizado e não é mais usado.
    • GraphListener
    • Apagável

O AbstractVisualizer fornece algumas funcionalidades comuns, que a maioria dos visualizadores, como o Graph Results , usam. A funcionalidade comum fornecida pela classe abstrata inclui:

  • Configurar elementos de teste – Isso significa que ele cria um novo ResultCollector , define o arquivo e define o log de erros
  • Crie o menu de ações
  • Atualize o elemento de teste quando as alterações forem feitas
  • Crie um painel de arquivo para o arquivo de log
  • Criar o painel de título

Em alguns casos, talvez você não queira exibir o menu da caixa de texto do arquivo. Nesse caso, você pode substituir o método init() . Aqui está a implementação para DistributionGraphVisualizer .

/**
 * Inicialize a GUI.
 */
private void init() {
    this.setLayout(new BorderLayout());

    // PAINEL PRINCIPAL
    Margem da borda = new EmptyBorder(10, 10, 5, 10);
    this.setBorder(margem);

    // Configura o gráfico com cabeçalho, rodapé, eixo Y e exibição de gráfico
    JPanel gráficoPanel = new JPanel(new BorderLayout());
    graphPanel.add(createGraphPanel(), BorderLayout.CENTER);
    graphPanel.add(createGraphInfoPanel(), BorderLayout.SOUTH);

    // Adiciona o painel principal e o gráfico
    this.add(makeTitlePanel(), BorderLayout.NORTH);
    this.add(graphPanel, BorderLayout.CENTER);
}

A primeira coisa que o método init faz é criar um novo BorderLayout . Dependendo de como você deseja fazer o layout dos widgets, você pode usar um gerenciador de layout diferente. Lembre-se de que usar diferentes gerenciadores de layout é para especialistas.

A segunda coisa que o método init faz é criar uma borda. Se você quiser aumentar ou diminuir a borda, altere os quatro valores inteiros. Cada valor inteiro representa pixels. Se você quiser que seu visualizador não tenha borda, pule as linhas 8 e 9. A linha 13 chama createGraphPanel , que é responsável por configurar e adicionar DistributionGraph ao visualizador.

Componente privado createGraphPanel() {
    gráficoPanel = new JPanel();
    graphPanel.setBorder(BorderFactory.createBevelBorder(
    BevelBorder.LOWERED,Color.lightGray,Color.darkGray));
    graphPanel.add(gráfico);
    graphPanel.setBackground(Color.white);
    retornar gráficoPanel;
}

Na linha 5, o componente gráfico é adicionado ao painel gráfico. O construtor é onde uma nova instância de DistributionGraph é criada.

public DistributionGraphVisualizer() {
    model = new SamplingStatCalculator("Distribution");
    gráfico = new DistributionGraph(model);
    graph.setBackground(Cor.branco);
    iniciar();
}

O construtor de DistributionGraphVisualizer é responsável por criar o modelo e o gráfico. Sempre que um novo resultado é concluído, o mecanismo passa o resultado para todos os ouvintes chamando add(SampleResult res) . O visualizador passa o novo SampleResult para o modelo.

public sincronizado void add(SampleResult res) {
    model.addSample(res);
    updateGui(model.getCurrentSample());
}

No caso do DistributionGraphVisualizer , o método add não atualiza o gráfico. Em vez disso, ele chama updateGui na linha três.

public sincronizado void updateGui(Sample s) {
    // Recebemos mais uma amostra
    if (atraso == contador) {
        atualizarGui();
        contador = 0;
    } senão {
        contador++;
    }
}

Ao contrário do GraphVisualizer , o gráfico de distribuição tenta mostrar como os resultados se agrupam; portanto, o DistributionGraphVisualizer atrasa a atualização. O atraso padrão é de 10 resultados de amostra.

public sincronizado void updateGui() {
    if (graph.getWidth() < 10) {
        graph.setPreferredSize(
                new Dimension(getWidth() - 40,
                getAltura() - 160));
    }
    graphPanel.updateUI();
    gráfico.repintar();
}

As linhas 2 a 3 devem redimensionar o gráfico, se o usuário redimensionar a janela ou arrastar o divisor. A linha 7 atualiza o painel que contém o gráfico. A linha 8 aciona a atualização do DistributionGraph . Antes de abordarmos a escrita de gráficos, existem alguns métodos importantes que o visualizador deve implementar.

public String getLabelResource() {
    return "distribution_graph_title";
}

O recurso label recupera o nome do visualizador do arquivo de propriedades. O arquivo está localizado em core/org/apache/jmeter/resources . É melhor não codificar o nome do visualizador. O arquivo Message.properties é organizado em ordem alfabética, portanto, é fácil adicionar uma nova entrada.

public sincronizado void clear() {
    this.graph.clear();
    model.clear();
    repintar();
}

Cada componente no JMeter deve implementar a lógica para o método clear() . Se isso não for feito, o componente não limpará a interface do usuário ou o modelo quando o usuário tentar limpar os últimos resultados e executar um novo teste. Se clear não for implementado, pode resultar em um vazamento de memória.

public JComponent getPrintableComponent() {
    return this.graphPanel;
}

O último método que os visualizadores devem implementar é getPrintableComponent() . O método é responsável por retornar o JComponent que pode ser salvo ou impresso. Esse recurso foi adicionado recentemente para que os usuários possam salvar uma captura de tela de qualquer visualizador.

29.4 GraphListener

O teste de carga no modo GUI é uma prática ruim, você não deve desenvolver esse plug-in. Dê uma olhada em componentes mais atualizados como:

Os visualizadores devem implementar GraphListener . Isso é feito para simplificar a adição de novas instâncias de amostra aos ouvintes. Como regra geral, se o gráfico personalizado não plotar todas as amostras, ele não precisará implementar a interface.

interface pública GraphListener {
    public void updateGui(Sample s);
    public void updateGui();
}

O método importante na interface é updateGui(Sample s) . De DistributionGraphVisualizer , vemos que ele chama graph.repaint() para atualizar o gráfico. Na maioria dos casos, a implementação de updateGui(Sample s) deve fazer exatamente isso. Os ItemListenerVisualizers geralmente não precisam implementar essa interface. A interface é usada com caixas de combinação, caixa de seleção e listas. Se o seu visualizador usa um desses e precisa saber quando foi atualizado, o visualizador precisará implementar a interface. Para obter um exemplo de como implementar a interface, consulte GraphVisualizer .

29.5 Escrevendo Gráficos Personalizados

O teste de carga no modo GUI é uma prática ruim, você não deve desenvolver esse plug-in. Dê uma olhada em componentes mais atualizados como:

Para aqueles que são novos no Swing e ainda não escreveram JComponents personalizados, sugiro comprar um livro sobre Swing e ter uma boa ideia de como os widgets Swing funcionam. Este tutorial não tentará explicar os conceitos básicos do Swing e pressupõe que o leitor já esteja familiarizado com o padrão de design Swing API e MVC (Model View Controller). No construtor de DistributionGraphVisualizer , vemos que uma nova instância de DistributionGraph é criada com uma instância do modelo.

public DistributionGraph(modelo SamplingStatCalculator) {
    isto();
    setModel(modelo);
}

A implementação do método setModel é direta.

private void setModel(modelo de objeto) {
    this.model = modelo (SamplingStatCalculator);
    repintar();
}

Observe que o método chama repaint depois de definir o modelo. Se o repaint não for chamado, pode fazer com que a GUI não desenhe o gráfico. Assim que o teste for iniciado, o gráfico será redesenhado, portanto, chamar repaint não é crítico.

public void paintComponent(Gráficos g) {
    super.paintComponent(g);
    final SamplingStatCalculator m = this.model;
    sincronizado (m) {
        desenharAmostra(m, g);
    }
}

O outro aspecto importante da atualização do widget é colocar a chamada para drawSample dentro de um bloco sincronizado. Se drawSample não fosse sincronizado, JMeter lançaria um ConcurrentModificationException em tempo de execução. Dependendo do plano de teste, pode haver uma dúzia ou mais de threads adicionando resultados ao modelo. O bloco sincronizado não afeta a precisão de cada solicitação individual e medição de tempo, mas afeta a capacidade do JMeter de gerar grandes cargas. À medida que o número de encadeamentos em um plano de teste aumenta, a probabilidade de um encadeamento ter que esperar até que o gráfico seja redesenhado antes de iniciar uma nova solicitação aumenta. Aqui está a implementação de drawSample .

private void drawSample(modeloSamplingStatCalculator, Graphics g) {
    largura = getLargura();
    altura dupla = (duplo)getAltura() - 1.0;

    // primeiro vamos desenhar a grade
    for (int y=0; y < 4; y++){
        int q1 = (int)(altura - (altura * 0,25 * y));
        g.setColor(Color.lightGray);
        g.drawLine(xborder,q1,width,q1);
        g.setColor(Cor.preto);
        g.drawString(String.valueOf((25 * y) + "%"),0,q1);
    }
    g.setColor(Cor.preto);
    // desenha o eixo X
    g.drawLine(xborder,(int)height,width,(int)height);
    // desenha o eixo Y
    g.drawLine(xborder,0,xborder,(int)height);
    // o plano de teste deve ter mais de 200 amostras
    // para gerar uma distribuição decente no meio do caminho
    // gráfico. Quanto maior a amostra, melhor
    // resultados.
    if (model != null && model.getCount() > 50) {
        // agora desenha o gráfico de barras
        Número noventa = model.getPercentPoint(0,90);
        Número cinquenta = model.getPercentPoint(0,50);
        total = model.getCount();
        Valores da coleção = model.getDistribution().values();
        Object[] objval = new Object[values.size()];
        objval = valores.paraArray(objval);
        // ordenamos os objetos
        Arrays.sort(objval,new NumberComparator());
        int len ​​= objval.comprimento;
        for (int contagem=0; contagem < len; contagem++) {
            // calcula a altura
            Número[] num = (Número[])objval[contagem];
            double iper = (double)num[1].intValue() / (double)total;
            double iheight = height * iper;
            // se a altura for menor que um, definimos
            // para um pixel
            if (altura < 1) {
                ialtura = 1,0;
            }
            int ix = (contagem * 4) + xborder + 5;
            int dheight = (int)(height - iheight);
            g.setColor(Cor.azul);
            g.drawLine(ix -1,(int)altura,ix -1,altura);
            g.drawLine(ix,(int)height,ix,dheight);
            g.setColor(Cor.preto);
            // desenha uma linha vermelha para 90% do ponto
            if (num[0].longValue() == noventa.longValue()) {
                g.setColor(Color.red);
                g.drawLine(ix,(int)height,ix,55);
                g.drawLine(ix,(int)35,ix,0);
                g.drawString("90%",ix - 30,20);
                g.drawString(
                        String.valueOf(num[0].longValue()),
                        ix + 8, 20);
            }
            // desenha uma linha laranja para 50% do ponto
            if (num[0].longValue() == cinquenta.longValue()) {
                g.setColor(Cor.laranja);
                g.drawLine(ix,(int)height,ix,30);
                g.drawString("50%",ix - 30,50);
                g.drawString(
                        String.valueOf(num[0].longValue()),
                        ix + 8, 50);
            }
        }
    }
}

Em geral, a renderização do gráfico deve ser bastante rápida e não deve ser um gargalo. Como regra geral, é uma boa ideia criar perfis de plugins personalizados. A única maneira de garantir que um visualizador não seja um gargalo é executá-lo com uma ferramenta como o Borland OptimizeIt. Uma boa maneira de testar um plugin é criar um plano de teste simples e executá-lo. O comportamento do heap e da coleta de lixo deve ser regular e previsível.

29.6 Criando um Plugin TestBean para JMeter

Nesta parte, passaremos pelo processo de criação de um componente simples para JMeter que usa o novo framework TestBean .

Este componente será um elemento de leitura de arquivo CSV que permitirá que os usuários variem facilmente seus dados de entrada usando arquivos CSV. Para usar este tutorial com mais eficiência, abra os três arquivos especificados abaixo (encontrados no diretório src/components do JMeter ).

  1. Escolha um pacote e faça três arquivos:
    • [ComponentName].java (org.apache.jmeter.config.CSVDataSet.java)
    • [ComponentName]BeanInfo.java (org.apache.jmeter.config.CSVDataSetBeanInfo.java)
    • [ComponentName]Resources.properties (org.apache.jmeter.config.CSVDataSetResources.properties)
  2. CSVDataSet.java deve implementar a interface TestBean . Além disso, ele estenderá ConfigTestElement e implementará LoopIterationListener .
    • TestBean é uma interface de marcador, portanto, não há métodos para implementar.
    • A extensão de ConfigTestElement tornará nosso componente um elemento Config em um plano de teste. Ao estender diferentes classes abstratas, você pode controlar o tipo de elemento que seu componente será (ou seja , AbstractSampler , AbstractVisualizer , GenericController , etc - embora você também possa criar diferentes tipos de elementos apenas instanciando as interfaces corretas, as classes abstratas podem tornar sua vida mais fácil).
  3. CSVDataSetBeanInfo.java deve estender org.apache.jmeter.testbeans.BeanInfoSupport
    • crie um construtor de parâmetro zero no qual chamamos super(CSVDataSet.class);
    • voltaremos a isso.
  4. CSVDataSetResources.properties - em branco por enquanto
  5. Implemente sua lógica especial para sua classe de plugin.
    1. O CSVDataSet lerá um único arquivo CSV e armazenará os valores encontrados no contexto de execução do JMeter. O usuário irá definir o arquivo, definir os nomes das variáveis ​​para cada " coluna ". O CSVDataSet abrirá o arquivo quando o teste iniciar e o fechará quando o teste terminar (assim implementamos TestListener ). O CSVDataSet atualizará o conteúdo das variáveis ​​para cada thread de teste e para cada iteração por meio de seu controlador pai, lendo novas linhas no arquivo. Quando chegarmos ao final do arquivo, começaremos de novo do início. Ao implementar um TestBean, preste muita atenção às suas propriedades. Essas propriedades se tornarão a base de um formulário GUI pelo qual os usuários configurarão o elemento CSVDataSet .
    2. Seu elemento será clonado pelo JMeter quando o teste for iniciado. Cada thread terá sua própria instância. No entanto, você terá a chance de controlar como a clonagem é feita, se precisar.
    3. Propriedades: filename , variableNames . Com getters e setters públicos.
      • nome do arquivo é autoexplicativo, ele conterá o nome do arquivo CSV que leremos
      • variableNames é uma String que permitirá que um usuário insira os nomes das variáveis ​​às quais atribuiremos valores. Por que uma Corda? Por que não uma coleção? Certamente os usuários precisarão inserir vários (e um número desconhecido de) nomes de variáveis? É verdade, mas se usássemos uma lista ou coleção, teríamos que escrever um componente GUI para lidar com coleções, e eu só quero fazer isso rapidamente. Em vez disso, permitiremos que os usuários insiram uma lista delimitada por vírgulas de nomes de variáveis.
    4. Em seguida, implementei o método IterationStart da interface LoopIterationListener . O ponto deste "evento" é que seu componente é notificado quando o teste entra em seu controlador pai. Para nossos propósitos, toda vez que o controlador pai do CSVDataSet for inserido, leremos uma nova linha do arquivo de dados e definiremos as variáveis. Assim, para um controlador regular, cada loop através do teste resultará em um novo conjunto de valores sendo lidos. Para um controlador de loop, cada iteração fará o mesmo. Cada thread de teste também obterá valores diferentes.
  6. Configurando seus elementos GUI em CSVDataSetBeanInfo :
    • Você pode criar agrupamentos para as propriedades do seu componente. Cada agrupamento que você cria precisa de um rótulo e uma lista de nomes de propriedade a serem incluídos nesse agrupamento. Ou seja:
      createPropertyGroup("csv_data",
              new String[] { "nome do arquivo", "variableNames" });
      
    • Cria um agrupamento chamado csv_data que incluirá elementos de entrada da GUI para as propriedades filename e variableNames de CSVDataSet . Então, precisamos definir que tipo de propriedades queremos que sejam:
      p = propriedade("nome do arquivo");
      p.setValue(NOT_UNDEFINED, Boolean.TRUE);
      p.setValue(DEFAULT, "");
      p.setValue(NOT_EXPRESSION, Boolean.TRUE);
      
      p = propriedade("variableNames");
      p.setValue(NOT_UNDEFINED, Boolean.TRUE);
      p.setValue(DEFAULT, "");
      p.setValue(NOT_EXPRESSION, Boolean.TRUE);
      
      Isso basicamente cria duas propriedades cujo valor não pode ser null e cujos valores padrão são "" . Existem vários desses atributos que podem ser definidos para cada propriedade. Aqui está um resumo:
      NOT_UNDEFINED
      A propriedade não será deixada nula .
      PREDEFINIÇÃO
      Um valor padrão deve ser fornecido se NOT_UNDEFINED for true .
      NOT_EXPRESSION
      O valor não será analisado para funções se isso for verdadeiro .
      NOT_OTHER
      Este não é um campo de entrada de forma livre – uma lista de valores deve ser fornecida.
      TAG
      Com um String[] como o valor, isso configura uma lista predefinida de valores aceitáveis ​​e o JMeter criará uma seleção suspensa.
      Além disso, um editor de propriedade personalizada pode ser especificado para uma propriedade:
      p.setPropertyEditorClass(FileEditor.class);
      
      Isso criará uma entrada de texto e um botão de navegação que abre uma caixa de diálogo para localizar um arquivo. Normalmente, configurações de propriedades complexas não são necessárias, como agora. Para um exemplo mais complexo, veja org.apache.jmeter.protocol.http.sampler.AccessLogSamplerBeanInfo
  7. Definindo suas strings de recursos. Em CSVDataSetResources.properties temos que definir todos os nossos recursos de string. Para fornecer traduções, seria necessário criar arquivos adicionais, como CSVDataSetResources_ja.properties e CSVDataSetResources_de.properties . Para nosso componente, devemos definir os seguintes recursos:
    Nome em Exibição
    Isso fornecerá um nome para o elemento que aparecerá nos menus.
    csv_data.displayName
    criamos um agrupamento de propriedades chamado csv_data , então temos que fornecer um rótulo para o agrupamento
    nomedoarquivo.displayName
    um rótulo para o elemento de entrada do nome do arquivo.
    nome do arquivo.shortDescription
    uma sinopse de texto de ajuda semelhante a uma dica de ferramenta.
    VariableNames.displayName
    um rótulo para o elemento de entrada do nome da variável.
    VariableNames.shortDescription
    dica de ferramenta para o elemento de entrada variableNames .
  8. Depure seu componente.

29.6 Construindo JMeter

JMeter usa Gradle para compilar e construir a distribuição. O JMeter possui várias tarefas definidas, o que facilita para os desenvolvedores a construção do projeto completo. Para aqueles que não estão familiarizados com o Gradle, é uma ferramenta de compilação semelhante à criação no Unix. Uma lista das tarefas Gradle com uma breve descrição é fornecida em gradle.md , que pode ser encontrada no diretório de origem raiz.

Aqui estão alguns comandos de exemplo.

./gradlew runGui
Construir e iniciar a GUI do JMeter
./gradlew createDist
Compile o projeto e copie os arquivos jar relevantes para a pasta ./lib
./gradlew :src:dist:previewSite
Cria visualização de um site para ./build/docs/site
Go to top