When running JMeter script from Java functions and

2019-08-03 03:19发布

问题:

I am trying to execute JMeter script from Java code using

String jmeterHome = "D:/tmp/apache-jmeter-3.3";
StandardJMeterEngine jmeter = new StandardJMeterEngine();
JMeterUtils.loadJMeterProperties(jmeterHome + "/jmeter.properties");
JMeterUtils.setJMeterHome(jmeterHome);
JMeterUtils.initLocale();

SaveService.loadProperties();

File script = new File(jmeterHome + "/http_localhost.jmx");
HashTree testPlanTree = SaveService.loadTree(script);

Summariser summer = null;
String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
if (summariserName.length() > 0) {
    summer = new Summariser(summariserName);
}       

String logFile = jmeterHome + "/file.jtl";
ResultCollector logger = new ResultCollector(summer);
logger.setFilename(logFile);
testPlanTree.add(testPlanTree.getArray()[0], logger);

jmeter.configure(testPlanTree);
jmeter.run();

In JMeter GUI in "Thread Group" configuration I am setting "Number Of Threads" to be "${__P(xxx,20)}". It works fine from the GUI - I can execute script with default value of "20". But the code above does not start any threads. Java code prints that it is trying to start zero threads.

I have seen Jmeter functions don't executing when calling from java code and I do have following dependencies in my project

        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>3.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_http</artifactId>
            <version>3.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_functions</artifactId>
            <version>3.3</version>
        </dependency>

回答1:

Your code is wrong, you are not referencing the correct jmeter.properties path.

Working example:

    String jmeterHome = "/data/jmeter/jmeters/apache-jmeter-3.3/";
    StandardJMeterEngine jmeter = new StandardJMeterEngine();
    JMeterUtils.setJMeterHome(jmeterHome);
    JMeterUtils.loadJMeterProperties(jmeterHome + "bin/jmeter.properties");
    JMeterUtils.initLocale();

    SaveService.loadProperties();

    File script = new File("/data/jmeter/workspace/JMeterFromJava/scenario/localhost.jmx");
    HashTree testPlanTree = SaveService.loadTree(script);

    Summariser summer = null;
    String summariserName = JMeterUtils.getPropDefault("summariser.name", "summary");
    if (summariserName.length() > 0) {
        summer = new Summariser(summariserName);
    }       

    String logFile = "/data/jmeter/workspace/JMeterFromJava/results/file.jtl";
    ResultCollector logger = new ResultCollector(summer);
    logger.setFilename(logFile);
    testPlanTree.add(testPlanTree.getArray()[0], logger);

    jmeter.configure(testPlanTree);
    jmeter.run();

EDIT 29 september 2017:

You submitted to bugzilla a demo project showing the problem. It helped understand your problem.

Status: - Code works if App is ran as a Main application - Code works if AppTest is ran from Eclipse - But code fails when ran through mvn clean install

The failure is due to this code:

  • https://github.com/apache/jmeter/blob/trunk/src/jorphan/org/apache/jorphan/reflect/ClassFinder.java#L335


回答2:

Small workaround:

final List<String> classPathUrls = new ArrayList<>();
for (final URL url : URLClassLoader.class.cast(this.getClass().getClassLoader()).getURLs()) {
   classPathUrls.add(url.getPath());
}
final String classPath = StringUtils.join(classPathUrls, ";");
JMeterUtils.setProperty("search_paths", classPath);


回答3:

When Jmeter functions are used in the Java code, Jmeter tries to compare the function related classes from java class path with classes from the 'search_path' (Reads classes from the jars). So Jmeter function works only if required function class is present in both the path (Jmeter has seperate class for each function).

This is why we need to make sure the 'ApacheJMeter_functions' jar added in the pom (which will be added in class path ) and the path to jmeter functions jar is set to 'search_path'.Both should have same version.

You can refer this link for more details



回答4:

The problem with JMeter is that it wants to have a library in classpath with exact name of "ApacheJMeter_functions.jar" it can't be "ApacheJMeter_functions-3.3.jar" even if the files are binary equal