5 Things that Are Easier in k6 Than in JMeter
Check out the load testing tasks that are easier in the open-source performance testing tool k6.
Join the DZone community and get the full member experience.
Join For Free
k6 is an open-source load testing tool available on GitHub. It is written in Go and runs test scripts that are written in JavaScript. It’s seen strong interest from developers, testers and DevOps teams and has more than 4400 GitHub stars. k6 is command line driven, with test results output to stdout or result analysis tools such as Load Impact Insights.
JMeter is also an open source load testing tool and has been around for many years. It’s very popular and has thousands of users. It’s a Java application and the JMeter GUI is used for creating test scripts. In addition, a few scripting languages can be used to write JMeter functions including Java, Groovy and JavaScript. Groovy has become the recommended default option. But, load test runs can only be executed from the command line.
In a ‘David versus Goliath’ sort of way, let’s take a look at a few examples of things that are easier to do in k6 than in JMeter.
1. Save an HTTP Response in a Variable
In JMeter:
- Add a Beanshell Postprocessor as a child of the request which returns the response you’re looking for.
- Put the code
vars.put(“response”, new String(data));
into the PostProcessor’s “Script” area. - Refer to the extracted value as
${response}
where required.
In k6, use the following test script code:
let response = http.get(“http://test.loadimpact.com/”);
In both cases, the data ends up in the response variable. The main difference is that you have to add a Beanshell PostProcessor to the request in JMeter before you can add the code snippet.
2. Test for an Expected 404 Response
In JMeter:
Create a new Response Assertion under the test. In the "Response Field to Test" section of the assertion, make sure to check the box for "Ignore Status".
You can then add other assertions such as setting the radio in "Response Field to Test" to "Response Code" and setting the "Patterns to Test" to 404.
Figure 1: JMeter GUI Showing How to Set Up the Response Assertion.
In k6, use the following test script code:
let response = http.get(“http://some.url/”);
check(res, {
"Status is 404": (r) => r.status === 404
});
The main difference here is the fact that doing this in JMeter requires you to click through a GUI and fill in values in entry fields, while with k6 you write a couple of lines of code instead. Your k6 JavaScript load test code can easily be tracked and managed in your version control system (VCS), just like your application code.
3. Reuse Custom Test Code in Different Tests
For example, say you want to call a logTransaction()
function defined in one file, from 150 different test configurations.
In JMeter:
- Add the line
beanshell.sampler.init=BeanShellSampler.bshrc
to the user.properties file (located in the "bin" folder of your JMeter installation). - Put your logTransaction function in the BeanShellSampler.bshrc file (same location, JMeter's "bin" folder).
- Next time you start JMeter, you will be able to call the function from any Beanshell Sampler in any script.
In k6:
- Put your logTransaction() function in a JavaScript file, e.g. “logTransaction.js"
- Use the following statement to import the function in any script: import { logTransaction } from "/path/to/logTransaction.js";
In k6, any Javascript file can be used directly as an importable module, which allows you to organize files any way you want. You can also import modules directly over the network:
import { logTransaction } from "s3.amazonaws.com/path/to/logTransaction.js";
Besides the standard ES6 JavaScript APIs, k6 comes bundled with APIs to handle Cookies, Crypto, Encodings, Environment variables, HTML forms, HTML parsing, Multipart requests, TLS client certificates, TLS ciphers and versions, and more.
4. Implement a Nested Loop
For example, you may want to test a servlet with two parameters: X and Y, where X and Y are random numbers from 0 to 100. You want a nested loop which is something like:
for (int x = 0; x <= 100; x++)
for (int y = 0; y <= 100; y++)
servlet?param1=x¶m2=y
In JMeter:
Your schema may be like the following:
Thread Group
User Defined Variables
maxX = 100
maxY = 100
Loop Controller X
Loop Count: ${__BeanShell(Integer.parseInt(vars.get("maxX"))+1)}
Counter X
Start: 0
Increment: 1
Maximum: ${maxX}
Reference Name: loopX
Loop Controller Y
Loop Count: ${__BeanShell(Integer.parseInt(vars.get("maxY"))+1)}
Counter Y
Start: 0
Increment: 1
Maximum: ${maxY}
Reference Name: loopY
YOUR HTTP Request
servlet?param1=${loopX}¶m2=${loopY}
. . .
Figure 2: JMeter GUI Showing Nested Loop.
In k6:
Use the following script code:
for (var x = 0; x <= 100; x++)
for (var y = 0; y <= 100; y++)
http.get(“http://some.domain/servlet?param1=” + x + “¶m2=” + y);
Doing more complex logical branching is, of course, where a GUI-based approach often becomes quite unwieldy compared to writing the logic directly in code. The k6 solution is very similar to the pseudo-code used to describe the problem.
5. Make Parallel Requests
We typically want to issue more than one request in parallel, like browsers do when fetching web pages. This puts a lot more stress on the server than having each virtual user just issue one request at a time.
In JMeter:
JMeter provides the Synchronizing Timer which allows grouping requests so they can be executed at exactly in the same moment. Just add a Synchronizing Timer to your test plan and make sure that:
- It is at the same level in both requests
- The number of virtual users in the Thread Group is >= what is set in the Synchronizing Timer
Figure 3: JMeter Synchronizing Timer.
In k6:
Use the http.batch()
function to issue multiple requests in parallel. For example:
http.batch([
"http://test.loadimpact.com",
"http://test.loadimpact.com/style.css",
"http://test.loadimpact.com/images/logo.png"
]);
The above "solutions" are not 100% comparable. In the JMeter case, we will still only have each Virtual User (VU) issuing a single request at a time. This means that JMeter VUs are not entirely accurate models of “real users.” A single human user will issue multiple requests concurrently, using their web browser, while a JMeter VU only issues one request at a time.
What JMeter does instead is synchronize the VUs so they issue requests at exactly the same time. (Which to me seems less useful-- the total throughput will probably go down, given that some VUs have to wait for other VUs to complete requests).
k6, on the other hand, will, in the example shown, let each VU open three concurrent TCP connections, and so be able to fetch the three items in parallel, just like a web browser does. This means that in the k6 case, 100 VUs may fetch 300 items in parallel. In the Jmeter case 100 VU will fetch 100 items in parallel. (Note: there is also JMeter extension called the Parallel Controller that can be used to create parallel requests).
So, there are a handful of examples of different load testing functions that are somewhat, or in some cases, very much easier to do in k6 than in JMeter. Are you a convert yet?
Opinions expressed by DZone contributors are their own.
Comments