【问题标题】:How to create and run Apache JMeter Test Scripts from a Java program?如何从 Java 程序创建和运行 Apache JMeter 测试脚本?
【发布时间】:2013-10-09 10:41:46
【问题描述】:

我想使用 Apache JMeter 提供的 API 从 Java 程序创建和运行测试脚本。我已经了解了 ThreadGroup 和 Samplers 的基础知识。我可以使用 JMeter API 在我的 Java 类中创建它们。

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);

但是,我不知道如何创建一个结合线程组和采样器的测试脚本,然后从同一个程序中执行它。有任何想法吗?

【问题讨论】:

    标签: java api automated-tests jmeter


    【解决方案1】:

    如果我理解正确,您希望在 Java 程序中以编程方式运行整个测试计划。就个人而言,我发现创建一个测试计划 .JMX 文件并在 JMeter 非 GUI 模式下运行它更容易:)

    这是一个基于原始问题中使用的控制器和采样器的简单 Java 示例。

    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();
        }
    }
    

    依赖关系

    这些是基于 JMeter 2.9 和使用的 HTTPSampler 所需的最小 JAR。 其他采样器很可能具有不同的库 JAR 依赖项。

    • 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

    注意

    • 在首先从 JMeter 安装 /bin 目录复制它之后,我还在 Windows 上的 c:\tmp 中硬连线了 jmeter.properties 的路径。
    • 我不确定如何为 HTTPSampler 设置转发代理。

    【讨论】:

    • 感谢您的回答。这正是我一直在寻找的。还有一件事。我认为将 LoopController 添加到 ThreadGroup 就足够了。不需要单独添加到 HashTree 中。
    • 关于添加到 HashTree 的要点。不久前我在玩 JMeter API,但我对传递给 JMeter Engine 配置方法的数据结构的细节有点生疏:)
    • 嗨。我收到以下错误。 2014-02-16 18:22:20.957 [jorphan.] (): strPathsOrJars[0]: null/lib/ext 调试 2014-02-16 18:22:20.957 [jorphan.] (): 没有找到:C :/Users/mvandrangi/workspace/mani/bin DEBUG 2014-02-16 18:22:20.957 [jorphan.] (): 没有找到:C:/Users/mvandrangi/Downloads/apache-jmeter-2.11/bin/ ApacheJMeter.jar DEBUG 2014-02-16 18:22:20.957 [jorphan.] (): 未找到:C:/Users/mvandrangi/Downloads/apache-jmeter-2.11/bin/ApacheJMeter_core.jar
    • @VishalPuliani 我不确定使用独立 Java 程序进行分布式测试是否可行或实用。
    • 我将此示例复制粘贴到我的 maven 项目中,其中我有 ApacheJMeter_core 和 ApacheJMeter_http 的依赖项。发生在我身上的是采样器永远不会被调用。我调查了为什么,似乎克隆到 JMeterThread 的哈希树在没有 LoopController 的情况下被克隆。所以在这部分:Sampler e = this.threadGroupLoopController.next(); while(true) { while(this.running && e != null) { 它不执行循环并且不调用采样器。什么给了?
    【解决方案2】:
    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);
    
    
            }
        }
    

    【讨论】:

    • 嗨,当我想将其作为分布式测试运行时,我需要做哪些更改?
    • 有没有人设法使用 java api 从 csv 或 jtl 文件生成 html 结果?
    【解决方案3】:

    截至 2020 年 8 月,您可以尝试使用此库:

    使用 Maven,添加到 pom.xml:

    <dependency>
       <groupId>us.abstracta.jmeter</groupId>
       <projectId>jmeter-java-dsl</projectId>
       <version>0.1</version>
     </dependency>
    

    示例代码:

     import static org.assertj.core.api.Assertions.assertThat;
     import static us.abstracta.jmeter.javadsl.JmeterDsl.*;
    
     import java.time.Duration;
     import org.eclipse.jetty.http.MimeTypes.Type;
     import org.junit.jupiter.api.Test;
     import us.abstracta.jmeter.javadsl.TestPlanStats;
    
     public class PerformanceTest {
    
       @Test
       public void testPerformance() throws IOException {
         TestPlanStats stats = testPlan(
            threadGroup(2, 10,
            httpSampler("http://my.service")
               .post("{\"name\": \"test\"}", Type.APPLICATION_JSON)
         ),
          //this is just to log details of each request stats
         jtlWriter("test.jtl")
         ).run();
                  assertThat(stats.overall().elapsedTimePercentile99()).isLessThan(Duration.ofSeconds(5));
      }
    
     }
    

    【讨论】:

      【解决方案4】:

      我使用 JMeter Java Api 创建了一个简单的概念验证项目 具有 Maven 依赖项: https://github.com/piotrbo/jmeterpoc

      您可以生成 JMeter 项目 jmx 文件并从命令行执行它 或者直接从java代码执行。

      这有点棘手,因为 jmx 文件需要存在 'guiclass' 属性 对于每个 TestElement。 要执行 jmx,添加 guiclass 就足够了(即使值不正确)。 要在 JMeter GUI 中打开,需要为每个 guiclass 输入正确的值。

      更烦人的问题是基于条件的流控制器。 JMeter API 并没有为您提供比 GUI 更多的功能。你还需要通过 condition 例如在IfController 中作为常规String。字符串应包含 javascript。所以你有基于 Java 的项目和 javascript,例如语法错误,在执行性能测试之前您不会知道:-(

      可能更好的选择是保留代码和支持 IDE 而不是 JMeter GUI 学习 Scala 并使用 http://gatling.io/

      【讨论】:

      • 无法使用 JMeter GUI 打开 simpleProject_generated.jmx 文件!?它面临错误。
      【解决方案5】:

      在非 GUI 模式下运行要快得多。做了一个项目,在后端模式下使用 Jmeter,然后解析 XML 文件以显示测试结果。看看这个 repo-https://github.com/rohitjaryal/RESTApiAutomation.git

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-05
        • 2015-12-24
        • 1970-01-01
        • 2014-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多