web-dev-qa-db-fra.com

Comment créer et exécuter des scripts de test Apache JMeter à partir d'un programme Java?

Je souhaite utiliser l'API fournie par Apache JMeter pour créer et exécuter des scripts de test à partir d'un programme Java. J'ai compris les bases de ThreadGroup et Samplers. Je peux les créer dans mon Java en utilisant l'API JMeter.

ThreadGroup threadGroup = new ThreadGroup();
    LoopController lc = new LoopController();
    lc.setLoops(5);
    lc.setContinueForever(true);
    threadGroup.setSamplerController(lc);
    threadGroup.setNumThreads(5);
    threadGroup.setRampUp(1);

HTTPSampler sampler = new HTTPSampler();
    sampler.setDomain("localhost");
    sampler.setPort(8080);
    sampler.setPath("/jpetstore/shop/viewCategory.shtml");
    sampler.setMethod("GET");

    Arguments arg = new Arguments();
    arg.addArgument("categoryId", "FISH");

    sampler.setArguments(arg);

Cependant, je ne sais pas comment créer un script de test combinant le groupe de threads et l'échantillonneur, puis l'exécuter à partir du même programme. Des idées?

30
Alim Ul Gias

Si je comprends bien, vous souhaitez exécuter un plan de test complet par programme à partir d'un programme Java. Personnellement, je trouve plus facile de créer un fichier .JMX de plan de test et de l'exécuter dans JMeter non Mode GUI :)

Voici un exemple simple Java basé sur le contrôleur et l'échantillonneur utilisé dans la question d'origine.

import org.Apache.jmeter.control.LoopController;
import org.Apache.jmeter.engine.StandardJMeterEngine;
import org.Apache.jmeter.protocol.http.sampler.HTTPSampler;
import org.Apache.jmeter.testelement.TestElement;
import org.Apache.jmeter.testelement.TestPlan;
import org.Apache.jmeter.threads.SetupThreadGroup;
import org.Apache.jmeter.util.JMeterUtils;
import org.Apache.jorphan.collections.HashTree;

public class JMeterTestFromCode {

    public static void main(String[] args){
        // Engine
        StandardJMeterEngine jm = new StandardJMeterEngine();
        // jmeter.properties
        JMeterUtils.loadJMeterProperties("c:/tmp/jmeter.properties");

        HashTree hashTree = new HashTree();     

        // HTTP Sampler
        HTTPSampler httpSampler = new HTTPSampler();
        httpSampler.setDomain("www.google.com");
        httpSampler.setPort(80);
        httpSampler.setPath("/");
        httpSampler.setMethod("GET");

        // Loop Controller
        TestElement loopCtrl = new LoopController();
        ((LoopController)loopCtrl).setLoops(1);
        ((LoopController)loopCtrl).addTestElement(httpSampler);
        ((LoopController)loopCtrl).setFirst(true);

        // Thread Group
        SetupThreadGroup threadGroup = new SetupThreadGroup();
        threadGroup.setNumThreads(1);
        threadGroup.setRampUp(1);
        threadGroup.setSamplerController((LoopController)loopCtrl);

        // Test plan
        TestPlan testPlan = new TestPlan("MY TEST PLAN");

        hashTree.add("testPlan", testPlan);
        hashTree.add("loopCtrl", loopCtrl);
        hashTree.add("threadGroup", threadGroup);
        hashTree.add("httpSampler", httpSampler);       

        jm.configure(hashTree);

        jm.run();
    }
}

Dépendances

Ce sont les JAR mininum nus requis basés sur JMeter 2.9 et le HTTPSampler utilisé. D'autres échantillonneurs auront très probablement des dépendances JAR de bibliothèque différentes.

  • ApacheJMeter_core.jar
  • jorphan.jar
  • avalon-framework-4.1.4.jar
  • ApacheJMeter_http.jar
  • commons-logging-1.1.1.jar
  • logkit-2.0.jar
  • oro-2.0.8.jar
  • commons-io-2.2.jar
  • commons-lang3-3.1.jar

Remarque

  • J'ai également câblé le chemin vers jmeter.properties dans c:\tmp sous Windows après l'avoir copié pour la première fois depuis le répertoire d'installation/bin de JMeter.
  • Je ne savais pas comment définir un proxy direct pour le HTTPSampler.
53
T.P.
package jMeter;

import Java.io.File;
import Java.io.FileOutputStream;

import org.Apache.jmeter.config.Arguments;
import org.Apache.jmeter.config.gui.ArgumentsPanel;
import org.Apache.jmeter.control.LoopController;
import org.Apache.jmeter.control.gui.LoopControlPanel;
import org.Apache.jmeter.control.gui.TestPlanGui;
import org.Apache.jmeter.engine.StandardJMeterEngine;
import org.Apache.jmeter.protocol.http.control.gui.HttpTestSampleGui;
import org.Apache.jmeter.protocol.http.sampler.HTTPSamplerProxy;
import org.Apache.jmeter.reporters.ResultCollector;
import org.Apache.jmeter.reporters.Summariser;
import org.Apache.jmeter.save.SaveService;
import org.Apache.jmeter.testelement.TestElement;
import org.Apache.jmeter.testelement.TestPlan;
import org.Apache.jmeter.threads.ThreadGroup;
import org.Apache.jmeter.threads.gui.ThreadGroupGui;
import org.Apache.jmeter.util.JMeterUtils;
import org.Apache.jorphan.collections.HashTree;

public class JMeterFromScratch {

        public static void main(String[] argv) throws Exception {

            String jmeterHome1 = "/home/ksahu/Apache-jmeter-2.13";
            File jmeterHome=new File(jmeterHome1);
//          JMeterUtils.setJMeterHome(jmeterHome);
            String slash = System.getProperty("file.separator");

            if (jmeterHome.exists()) {
                File jmeterProperties = new File(jmeterHome.getPath() + slash + "bin" + slash + "jmeter.properties");
                if (jmeterProperties.exists()) {
                    //JMeter Engine
                    StandardJMeterEngine jmeter = new StandardJMeterEngine();

                    //JMeter initialization (properties, log levels, locale, etc)
                    JMeterUtils.setJMeterHome(jmeterHome.getPath());
                    JMeterUtils.loadJMeterProperties(jmeterProperties.getPath());
                    JMeterUtils.initLogging();// you can comment this line out to see extra log messages of i.e. DEBUG level
                    JMeterUtils.initLocale();

                    // JMeter Test Plan, basically JOrphan HashTree
                    HashTree testPlanTree = new HashTree();

                    // First HTTP Sampler - open example.com
                    HTTPSamplerProxy examplecomSampler = new HTTPSamplerProxy();
                    examplecomSampler.setDomain("www.google.com");
                    examplecomSampler.setPort(80);
                    examplecomSampler.setPath("/");
                    examplecomSampler.setMethod("GET");
                    examplecomSampler.setName("Open example.com");
                    examplecomSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
                    examplecomSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());


                    // Second HTTP Sampler - open blazemeter.com
                    HTTPSamplerProxy blazemetercomSampler = new HTTPSamplerProxy();
                    blazemetercomSampler.setDomain("www.tripodtech.net");
                    blazemetercomSampler.setPort(80);
                    blazemetercomSampler.setPath("/");
                    blazemetercomSampler.setMethod("GET");
                    blazemetercomSampler.setName("Open blazemeter.com");
                    blazemetercomSampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
                    blazemetercomSampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());


                    // Loop Controller
                    LoopController loopController = new LoopController();
                    loopController.setLoops(1);
                    loopController.setFirst(true);
                    loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
                    loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName());
                    loopController.initialize();

                    // Thread Group
                    ThreadGroup threadGroup = new ThreadGroup();
                    threadGroup.setName("Example Thread Group");
                    threadGroup.setNumThreads(1);
                    threadGroup.setRampUp(1);
                    threadGroup.setSamplerController(loopController);
                    threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
                    threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());

                    // Test Plan
                    TestPlan testPlan = new TestPlan("Create JMeter Script From Java Code");
                    testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
                    testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
                    testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());

                    // Construct Test Plan from previously initialized elements
                    testPlanTree.add(testPlan);
                    HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup);
                    threadGroupHashTree.add(blazemetercomSampler);
                    threadGroupHashTree.add(examplecomSampler);

                    // save generated test plan to JMeter's .jmx file format
                    SaveService.saveTree(testPlanTree, new FileOutputStream(jmeterHome + slash + "example.jmx"));

                    //add Summarizer output to get test progress in stdout like:
                    // summary =      2 in   1.3s =    1.5/s Avg:   631 Min:   290 Max:   973 Err:     0 (0.00%)
                    Summariser summer = null;
                    String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
                    if (summariserName.length() > 0) {
                        summer = new Summariser(summariserName);
                    }


                    // Store execution results into a .jtl file
                    String logFile = jmeterHome + slash + "example.jtl";
                    ResultCollector logger = new ResultCollector(summer);
                    logger.setFilename(logFile);
                    testPlanTree.add(testPlanTree.getArray()[0], logger);

                    // Run Test Plan
                    jmeter.configure(testPlanTree);
                    jmeter.run();

                    System.out.println("Test completed. See " + jmeterHome + slash + "example.jtl file for results");
                    System.out.println("JMeter .jmx script is available at " + jmeterHome + slash + "example.jmx");
                    System.exit(0);

                }
            }

            System.err.println("jmeter.home property is not set or pointing to incorrect location");
            System.exit(1);


        }
    }
10

J'ai créé un projet de démonstration de principe simple en utilisant JMeter Java Api avec les dépendances Maven: https://github.com/piotrbo/jmeterpoc

Vous pouvez soit générer le fichier jmx du projet JMeter et l'exécuter à partir de la ligne de commande, soit l'exécuter directement à partir de Java.

C'était un peu délicat car le fichier jmx nécessite l'existence de l'attribut 'guiclass' pour chaque TestElement. Pour exécuter jmx, il suffit d'ajouter guiclass (même avec une valeur incorrecte). Pour ouvrir dans l'interface graphique JMeter, il faut mettre la valeur correcte pour chaque guiclass.

Les contrôleurs de flux basés sur des conditions sont un problème beaucoup plus ennuyeux. L'API JMeter ne vous offre pas beaucoup plus que l'interface graphique. Vous devez toujours passer un condition par exemple dans IfController comme normal String. Une chaîne doit contenir du javascript. Vous avez donc Java avec javascript avec par exemple une erreur de syntaxe et vous ne le saurez pas jusqu'à ce que vous exécutiez votre test de performance :

Probablement une meilleure alternative pour rester avec le code et le support de IDE au lieu de l'interface graphique JMeter est d'apprendre un peu Scala un peu et d'utiliser --- (http: // gatling .io /

5
Piotr Boho

L'exécution en mode non GUI est beaucoup plus rapide. Avoir fait un projet qui utilise Jmeter en mode backend puis analyse le fichier XML pour afficher les résultats des tests. Jetez un oeil à ce repo- https://github.com/rohitjaryal/RESTApiAutomation.git

0
rohit.jaryal