April 26, 2022

JMeter DSL: Bringing Performance Testing Closer to Developers

Open Source Automation

JMeter is a very popular tool among non-developers testers. This is mainly because no programming knowledge is needed and it supports a large number of protocols and plugins, which increases its versatility. However, JMeter also has its limitations, and not being CI/CD friendly is one of them. As seen here, running JMeter programmatically might be too verbose and hard to review as it's not friendly with any VCS format. In addition, creating test plans in JMeter GUI can be too slow for continuous development teams. This is where JMeter DSL, or "jmeter-java-dsl" comes in.

 

Table of Contents:

 

What is JMeter DSL?

JMeter DSL is an open-source developer-friendly tool for running performance tests as code, both locally and at scale. JMeter DSL is a Java API that takes advantage of not only JMeter using it as an engine but also coding benefits as well.

This means it provides all the JMeter potential and its protocols support, as well as all the benefits from coding in an IDE, like inline documentation and autocompletion. In addition, it has built-in features that ease CI/CD pipelines integration. Finally, its simple design allows programmers and testers to create much shorter tests and scripts that are easy to read and maintain.

Follow the documentation here to learn how to use the DSL and also to acquire knowledge of good performance testing practices.

 

What is DSL?

Unlike other languages that are designed for general purposes, DSL or Domain Specific Language are expressive, human-readable programming languages that are customized for specific tasks like generating artifacts, configuring projects, and more. In our case, we used a DSL to configure our pom.xml file. JMeter DSL is Java-based and its purpose is to code performance tests.

 

In this post, we share the creation of a simple test with JMeter DSL. We will show the main functions, such as adding headers and assertions. We will also show how to run the test locally and in BlazeMeter, and see how to view the test results.

 

How to Use JMeter DSL

Locally Running jmeter-java-dsl

 

We will create a test for the BlazeDemo site that will simulate access to the home page and verify the response’s information.

Setup:

 

In this example, we use the Apache Maven software. For other tools, check the user’s guide.

 

1. To use the JMeter DSL there's no need to install anything. Just include the following dependency on your pom.xml file, which is the file that contains your project’s configurations:

 

 

<dependency><groupId>us.abstracta.jmetergroupId><artifactId>jmeter-java-dslartifactId><version>0.49.1version><scope>testscope>dependency>

 

 

2. We will use AssertJ and JUnit5 test libraries. So now, add the corresponding dependencies to the pom.xml file. These frameworks are needed in order to support the code written later:

 

 

<dependency><groupId>org.junit.jupitergroupId><artifactId>junit-jupiterartifactId><version>5.8.2version><scope>testscope>dependency><dependency><groupId>org.assertjgroupId><artifactId>assertj-coreartifactId><version>3.21.0version><scope>testscope>dependency>

 

Simple HTTP test plan 

After the setup, let’s create our first test.

 

3. Add a test plan that will pass a thread group as a parameter. You can define the number of threads (concurrent virtual users), iterations, and samplers to be executed. This example uses 1 thread that will send 1 HTTP GET request to the BlazeDemo homepage. 

 

 

importstatic us.abstracta.jmeter.javadsl.JmeterDsl.*;importorg.junit.Test;publicclassSimpleScriptTest{@TestpublicvoidtestDSL()throws Exception {
   testPlan(
       threadGroup(1,1,
           httpSampler("http://blazedemo.com"))).run();}}

 

4. Add a response assertion to the test to verify that the site is displaying the text “Welcome to the Simple Travel Agency!” as it should. Add the following to the httpSampler.

 

.children(responseAssertion().containsSubstrings("Welcome to the Simple Travel Agency!"))

 

5. Send the headers of the request using the method .header(), which in this case are:

@TestpublicvoidtestDSL()throws Exception {
 TestPlanStats stats = testPlan(
     threadGroup(1,1,
         httpSampler("http://blazedemo.com").children(responseAssertion().containsSubstrings("Welcome to the Simple Travel Agency!")).header("accept","text/html,application/xhtml+xml,application"+"/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application"+"/signed-exchange;v=b3;q=0.9").header("accept-encoding","gzip, deflate, br").header("accept-language","es-ES,es;q=0.9").header("cache-control","max-age=0").header("sec-ch-ua","\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"98\", \"Google "+"Chrome\";v=\"98\"").header("sec-ch-ua-platform","Windows").header("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) "+"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"))).run();}

 

 

HTTP Headers are sent to check that the right information is being received. They contain a lot of additional information about HTTP connection types, proxies, etc

 

6. Add acceptance criteria to your test results, like checking that the response time of the 99 percentile of the requests is less than 5 seconds.

 

This is the final script:

 

importjava.time.Duration;importorg.junit.Test;importus.abstracta.jmeter.javadsl.blazemeter.BlazeMeterEngine;importus.abstracta.jmeter.javadsl.core.TestPlanStats;importstatic org.assertj.core.api.Assertions.assertThat;importstatic us.abstracta.jmeter.javadsl.JmeterDsl.*;publicclassSimpleScriptTest{@TestpublicvoidtestDSL()throws Exception {
   TestPlanStats stats = testPlan(
       threadGroup(1,1,
           httpSampler("http://blazedemo.com").children(responseAssertion().containsSubstrings("Welcome to the Simple Travel Agency!")).header("accept","text/html,application/xhtml+xml,application"+"/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application"+"/signed-exchange;v=b3;q=0.9").header("accept-encoding","gzip, deflate, br").header("accept-language","es-ES,es;q=0.9").header("cache-control","max-age=0").header("sec-ch-ua","\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"98\", \"Google "+"Chrome\";v=\"98\"").header("sec-ch-ua-platform","Windows").header("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) "+"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"))).run();
 
   assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5));}

 

This means that this test will fail if it doesn't get the information that was specified or if the 99th percentile of the requests’ response time is less than 5 seconds.

 

7. Running the test is as easy as running any other Junit test, as it can be done in Maven or your preferred IDE. In IntelliJ just click the green play symbol next to the test:

Test run in IntelliJ

 

These are the results in the console:

 

Test results in IntelliJ

As we can see, we get the error range and time statistics (average, minimum and maximum time to perform the simulation).

 

How to Run JMeter DSL Tests at Scale in BlazeMeter

You can easily run a JMeter DSL test at scale in BlazeMeter and obtain an extended report. This will enable you to use the additional features provided (historic data tracking, real-time reporting, etc.).

8. To do so, include the following module as a dependency on the pom.xml file.

 

<dependency><groupId>us.abstracta.jmetergroupId><artifactId>jmeter-java-dsl-blazemeterartifactId><version>0.49.1version><scope>testscope>dependency>

 

9. To access your BlazeMeter account, you will need an authentication token. So the next step will be generating it, as shown here. As long as it doesn't expire, you only need to create it once.

 

10. Once you already have your token, replace each .run()linewith .runIn(new BlazeMeterEngine(...)) in any existing jmeter-java-dsl test. See the following example:

importjava.time.Duration;importorg.junit.Test;importus.abstracta.jmeter.javadsl.blazemeter.BlazeMeterEngine;importus.abstracta.jmeter.javadsl.core.TestPlanStats;importstatic org.assertj.core.api.Assertions.assertThat;importstatic us.abstracta.jmeter.javadsl.JmeterDsl.*;publicclassSimpleScriptTest{@TestpublicvoidtestDSL()throws Exception {
   TestPlanStats stats = testPlan(
       threadGroup(1,1,
           httpSampler("http://blazedemo.com").children(responseAssertion().containsSubstrings("Welcome to the Simple Travel Agency!")).header("accept","text/html,application/xhtml+xml,application"+"/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application"+"/signed-exchange;v=b3;q=0.9").header("accept-encoding","gzip, deflate, br").header("accept-language","es-ES,es;q=0.9").header("cache-control","max-age=0").header("sec-ch-ua","\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"98\", \"Google "+"Chrome\";v=\"98\"").header("sec-ch-ua-platform","Windows").header("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) "+"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"))).runIn(new BlazeMeterEngine(System.getenv("BZ_TOKEN")).testName("Simple DSL test").totalUsers(10).holdFor(Duration.ofSeconds(120)).threadsPerEngine(25).testTimeout(Duration.ofSeconds(240)));
 
   assertThat(stats.overall().sampleTimePercentile99()).isLessThan(Duration.ofSeconds(5));}}

 

A detail to keep in mind is to set the auth token, which has a <KEY_ID:KEY_SECRET> format, as a custom environment variable “BZ_TOKEN”. You can get it with Sysem.getEnv(“BZ_TOKEN”) to make it cleaner. Even though inserting new BlazeMeterEngine(“KEY_ID:KEY_SECRET”) is valid as well, inserting sensitive data directly into a test is not a recommended security best practice. Using the token as a custom environment variable is safer than using it directly in a test.

 

11. Note that if you want to run your test in BlazeMeter, you must set a name for the test, the total number of users, the duration, etc. This test uses 10 concurrent users. Check BlazeMeterEngine for details on usage and other configuration options.

 

Once you run your test, it will automatically load the complete report on BlazeMeter. These are the results:

 

Besides scaling your tests, BlazeMeter gives really useful features like real-time reporting and historic data tracking. You can observe key statistics of the tests compared with the baseline on the Summary Panel, a test overview, and trends of your KPIs.

BlazeMeter real-time reporting and historic data tracking

 

How Can JMeter DSL Help Me?

 

JMeter DSL is a great option for integrating load tests to agile teams as it considerably eases the scripting and maintenance of performance tests in the repositories usually used in this kind of project. Also, it's a great choice for users who have more of a developer profile and are not used to JMeter’s UI. We know how irritating can be constantly switching from an IDE to a UI-oriented tool. That’s not all, you can also take advantage of the entire BlazeMeter platform, scale your tests and obtain detailed reports.

The best of this tool is that anyone can use it, having or not JMeter experience. The example provided is a good place to start and will guide you in your first steps. We consider this tool will be a major contribution to the software community so we encourage you to try this well-documented tool and start bringing performance testing closer to development.

START TESTING NOW