1

I have a Class which demonstrate a JMeter test from Java code.

The Object of the test is to set N requests per second.

I want to add a ConstantThroughputTimer to my test in order to set the max RPS(requests per second) JMeter is making.

Created one in the gui and its working well, but i want to run it from a java code.

Right now i have 2 issues :

  1. I don't know how to set the thread group 'loop count' forever. (see screenshot)
  2. I wasn't able to add the ConstantThroughputTimer to my test plan.

I've searched and i couldn't find any documentation about it , nor code example.

Any Help would be very much appreciated.

My Code:

public static void main(String[] args) {
    StandardJMeterEngine jMeterEngine = new StandardJMeterEngine();
    //Setting JMeter Properties
    File properties = JmeterUtils.getPropertiesFile();
    File home = JmeterUtils.getHomePath();
    JMeterUtils.setJMeterHome(home.getPath());
    JMeterUtils.loadJMeterProperties(properties.getPath());
    JMeterUtils.initLocale();

    //Creating HashTreeTestPlan
    HashTree testPlanTree = new HashTree();

    //Creating HttpSampler
    HTTPSamplerProxy sampler = new HTTPSamplerProxy();
    sampler.setMethod("GET");
    sampler.setDomain("example.com");
    sampler.setUseKeepAlive(true);
    sampler.setFollowRedirects(true);
    sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
    sampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
    sampler.setEnabled(true);

    //Creating LoopController
    LoopController loopController = new LoopController();
    loopController.setContinueForever(true);
    loopController.setLoops(10000);
    loopController.setFirst(true);
    loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
    loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName());
    loopController.initialize();
    loopController.setEnabled(true);

    //Creating the number of Threads (clients)
    ThreadGroup threadGroup = new ThreadGroup();
    threadGroup.setName("threadGroup");
    threadGroup.setNumThreads(10);
    threadGroup.setScheduler(true);
    threadGroup.setRampUp(0);
    threadGroup.setDuration(60);
    threadGroup.setSamplerController(loopController);
    threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
    threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());
    threadGroup.setEnabled(true);



    //Adding Constant Throughput Timer - This is what i want to add
    ConstantThroughputTimer timer = new ConstantThroughputTimer();
    timer.setProperty(TestElement.TEST_CLASS, ConstantThroughputTimer.class.getName());
    timer.setName("constantTimer");
    double rpsCalc = 10 * 60;
    timer.setThroughput(rpsCalc);
    timer.setEnabled(true);
    timer.setCalcMode(2);


    //NOT WORKING// 
    //NOT WORKING// 
    threadGroup.addTestElement(timer);



    //Test Plan
    TestPlan testPlan = new TestPlan("Test Plan");
    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);

    jMeterEngine.configure(testPlanTree);

    try {
        jMeterEngine.runTest();
    } catch (JMeterEngineException e) {
        e.printStackTrace();
    }
}
razrog
  • 41
  • 6
  • How exactly is it "//NOT WORKING//"? Did it compile? Does it throw a runtime error? What is happening? – Yuri G Jul 17 '17 at 20:42
  • Sorry . Forgot to mentioned that the test is running but without the timer - meaning requests are made and the rps is much more bigger than what is set on the timer – razrog Jul 17 '17 at 20:44
  • I'm basically not sure you hit your system-under-test at all. I see you added the loop controller to your thread group, but I can't spot the moment where you add your sampler to the loop controller. As well as the moment you add your thread group to the test plan. Is the code you're showing up here different from the one you're trying to run? – Yuri G Jul 17 '17 at 21:00
  • HashTree requestHashTree = new HashTree(); requestHashTree.add(httpSamplerProxy, headerManager); testPlanTree.add(testPlan); HashTree threadGroupHashTree = testPlanTree.add(testPlan, threadGroup); threadGroupHashTree.add(requestHashTree); but still i don't know where to add my timer. – razrog Jul 18 '17 at 05:32

3 Answers3

2

Full working Solution

My Run Method

public void run(String domain, int rps, int durationInSeconds, String host){
    StandardJMeterEngine jMeterEngine = new StandardJMeterEngine();

    //Setting JMeter Properties
    File properties = JmeterUtils.getPropertiesFile();
    File home = JmeterUtils.getHomePath();
    JMeterUtils.setJMeterHome(home.getPath());
    JMeterUtils.loadJMeterProperties(properties.getPath());
    JMeterUtils.initLocale();

    //Creating HashTreeTestPlan
    HashTree testPlanTree = new HashTree();

    //Creating HttpSampler
    HTTPSamplerProxy httpSamplerProxy = JmeterUtils.createHttpSamplerGet(domain);

    //Creating Header Manager
    HeaderManager headerManager = JmeterUtils.createHeaderManager(host);

    //Creating LoopController
    LoopController loopController = JmeterUtils.createLoopController(-1, true);

    //Creating the number of Threads (clients)
    ThreadGroup threadGroup = JmeterUtils.createThreadGroup(domain, rps, durationInSeconds, loopController);

    //Adding Request Manager To requests HashTree
    HashTree requestHashTree = new HashTree();
    requestHashTree.add(httpSamplerProxy, headerManager);

    //Creating Throughput Timer - Controls the RPS
    ConstantThroughputTimer timer = JmeterUtils.createTimer(rps);

    //Creating Test Plan
    TestPlan testPlan = JmeterUtils.createTestPlan(domain);

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

    //Configuring the Engine & Running the Test
    jMeterEngine.configure(testPlanTree);
    jMeterEngine.runTest();

}

My JmeterUtils

public class JmeterUtils {

private static final File PROPERTIES_FILE = new File(System.getProperty("user.dir") + "/testdata/JMeter/bin/jmeter.properties");
private static final File HOME_PATH = new File(System.getProperty("user.dir") + "/testdata/JMeter");

static HeaderManager createHeaderManager(String host){
    HeaderManager headerManager = new HeaderManager();
    if(host != null){
        headerManager.add(new Header("Host",host));
    }
    headerManager.add(new Header("Connection", "Close"));
    headerManager.add(new Header("Cache-Control", "max-age=0"));
    headerManager.add(new Header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.52 Safari/536.5"));
    headerManager.setProperty(TestElement.TEST_CLASS, HeaderManager.class.getName());
    headerManager.setProperty(TestElement.GUI_CLASS, HeaderPanel.class.getName());
    headerManager.setEnabled(true);
    return headerManager;
}

static HTTPSamplerProxy createHttpSamplerGet(String domain){
    HTTPSamplerProxy sampler = new HTTPSamplerProxy();
    sampler.setMethod("GET");
    sampler.setDomain(domain);
    sampler.setUseKeepAlive(true);
    sampler.setFollowRedirects(true);
    sampler.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
    sampler.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
    sampler.setEnabled(true);
    return sampler;
}

static ThreadGroup createThreadGroup(String name, int numOfThreads, int durationInSeconds, LoopController loopController){
    ThreadGroup threadGroup = new ThreadGroup();
    threadGroup.setName(name);
    threadGroup.setNumThreads(numOfThreads);
    threadGroup.setScheduler(true);
    threadGroup.setRampUp(0);
    threadGroup.setDuration(durationInSeconds);
    threadGroup.setSamplerController(loopController);
    threadGroup.setProperty(TestElement.TEST_CLASS, ThreadGroup.class.getName());
    threadGroup.setProperty(TestElement.GUI_CLASS, ThreadGroupGui.class.getName());
    threadGroup.setEnabled(true);

    return threadGroup;
}

static LoopController createLoopController(int numOfLoops,boolean continueForever){
    LoopController loopController = new LoopController();
    if(continueForever){
        loopController.setLoops(-1);
    }
    else{
        loopController.setLoops(numOfLoops);
    }
    loopController.setFirst(true);
    loopController.setProperty(TestElement.TEST_CLASS, LoopController.class.getName());
    loopController.setProperty(TestElement.GUI_CLASS, LoopControlPanel.class.getName());
    loopController.initialize();
    loopController.setEnabled(true);

    return loopController;
}

static ConstantThroughputTimer createTimer(int rps){
    ConstantThroughputTimer timer = new ConstantThroughputTimer();
    long rpsCalc = rps * 60;
    timer.setProperty("throughput", rpsCalc);
    timer.setProperty("calcMode", 2);
    timer.setCalcMode(2);
    timer.setThroughput(rpsCalc);
    timer.setEnabled(true);
    timer.setProperty(TestElement.TEST_CLASS, ConstantThroughputTimer.class.getName());
    timer.setProperty(TestElement.GUI_CLASS, TestBeanGUI.class.getName());
    return timer;
}

static TestPlan createTestPlan(String domain){
    TestPlan testPlan = new TestPlan("Traffic Generator\t[" + domain + "]");
    testPlan.setProperty(TestElement.TEST_CLASS, TestPlan.class.getName());
    testPlan.setProperty(TestElement.GUI_CLASS, TestPlanGui.class.getName());
    testPlan.setUserDefinedVariables((Arguments) new ArgumentsPanel().createTestElement());
    return testPlan;
}


static File getPropertiesFile(){
    return PROPERTIES_FILE;
}
static File getHomePath(){
    return HOME_PATH;
}

}

razrog
  • 41
  • 6
0
  1. To configure Thread Group to run forever:

    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();    
    
  2. To configure Constant Throughput Timer:

    ConstantThroughputTimer ctt = new ConstantThroughputTimer();
    ctt.setName("Constant Throughput Timer");
    ctt.setProperty("throughput", 60 * 10);
    ctt.setProperty("calcMode", 2);
    ctt.setCalcMode(2);
    ctt.setProperty(TestElement.TEST_CLASS, ConstantThroughputTimer.class.getName());
    ctt.setProperty(TestElement.GUI_CLASS, TestBeanGUI.class.getName());
    
  3. For more information see:

Dmitri T
  • 159,985
  • 5
  • 83
  • 133
0

Well, according to documentation:

Timers are only processed in conjunction with a sampler. A timer which is not in the same scope as a sampler will not be processed at all.

Since you only have one sampler, and you actually need this timer to be applied right on it, then

To apply a timer to a single sampler, add the timer as a child element of the sampler. The timer will be applied before the sampler is executed. To apply a timer after a sampler, either add it to the next sampler, or add it as the child of a Test Action Sampler.

Try this, perhaps? I mean, add the timer directly to the sampler.

PS Although it looks already legit to me, at least in usual JMeter GUI perspective. Not sure what the problem is.

PPS I guess, what can be done here, if you really dedicated to nail it - you can save your plan as the .jmx, then do the same in JMeter GUI - and compare.

Yuri G
  • 1,206
  • 1
  • 9
  • 13
  • Thanks Yuri for your response. In the GUI i'm adding the timer either to my ThreadGroup or to the TestPlan itself and it was working fine. But i finally got this done today. Full code is in another answer. – razrog Jul 18 '17 at 18:09