If you’ve been in the load testing game for awhile or ever looked around for open source load testing tools, which you no doubt had at some point if you’re reading this, you’d likely have run into JMeter. It’s a well-known, featureful load testing tool but with quite a few years on its back, first seeing the light of day in 1998.
Before jumping into the details of what the converter can do and how it works, credit needs to be given where credit is due; major thanks to @bookmoons for doing an amazing job implementing this tool 👏🙌
Let’s waste no more time, this is how you get the converter installed: npm install -g jmeter-to-k6
This will install the converter globally on your system so it can be run from anywhere (we recommend to use nvm to avoid permission issues with trying to use sudo on Unix/Linux systems). If you prefer to install it on a per-project basis, as a dependency, you can of course do that as well (run something like npm install --save-dev jmeter-to-k6 instead).
To convert a JMeter .jmx file you run a command like this: jmeter-to-k6 -o /conversion/output/directory MyTest.jmx
When you run this two things happen:
- The converter will parse the JMeter XML and output the equivalent k6 JS test script to a file at /conversion/output/directory/test.js.
As some JMeter features don’t exist in k6 yet, we need to bridge that feature gap by importing third-party Node.js libraries. A /conversion/output/directory/libs directory will be created including the necessary Node.js libraries. The JS libs in this directory will be imported by the main test.js file as needed.
Will it work on all JMeter files?
The short answer is no. The longer answer requires us to start digging into the feature set of the tool by looking at the supported JMeter features in this initial release.
Supported JMeter features/elements
- Stepping Thread Group: converts into the equivalent k6 options.stages settings.
- Thread Group: converts into the equivalent k6 options.stages settings.
- setUp Thread Group: converts to an export function setup() in k6 including all the child logic of this element converted into the body of the this function.
- tearDown Thread Group: converts to an export function teardown() in k6 including all the child logic of this element converted into the body of this function.
DNS Cache Manager: converts to the equivalent k6 options.hosts settings.
HTTP Auth Manager: converts to the appropriate URL userinfo or Authorization header.
HTTP Cookie Manager: converts to the a global (per-VU) cookiejar merged with per-request cookies. Example:
HTTP Header Manager: converts to per-request headers. Example:
XPath Assertion: converts to a comment recommending a pure JS library be used (see section below on future improvements).
ForEach Controller: converts to a JS for-loop in k6. Example:
If Controller: converts to a JS if statement in k6. Example:
Interleave Controller: converts to a JS switch statement in k6 that alternates between all child elements for each VU iteration. Example (with 2 child elements of the Interleave Controller):
Loop Controller: converts to either a JS while(true)-loop, if "Forever” has been checked, or a JS for-loop otherwise. Example (with a loop count of 5):
Once Only Controller: converts to an if statement whose body is only run if the VU is in the first iteration. Example:
Random Controller: converts to a JS switch statement selecting a case at random. Example (with 2 child elements):
Runtime Controller: converts to JS block that keeps track of a deadline time in the future that it checks at the end of each iteration of child element execution. Example (with a Loop Controller, looping forever, as a child element):
Simple Controller: converts to a group() in k6, with the controller name as the group name. Example:
Transaction Controller: like the Simple Controller above, the Transaction Controller converts to a group() in k6, with the controller name as the group name. As k6 measures group duration the equivalent metric data will be available as for a Transaction Controller. Example:
While Controller: converts to a JS while-loop in k6. Example:
- Constant Timer: converts into a sleep(timeInSecs) statement in k6.
- BeanShell PreProcessor: converts to a comment with the code in k6.
- JSR223 PreProcessor: converts to a comment with the code in k6.
BeanShell PostProcessor: converts to a comment with the code in k6.
Boundary Extractor: converts to JS code using a regex to extract the needed data in k6. Example (extracting the slideshow.author field from the JSON returned by https://httpbin.test.loadimpact.com/json):
JSR223 PostProcessor: onverts to a comment with the code in k6.
Regex Extractor: converts to code using the standard JS RegExp API to extract the specified data. Example:
Result Status Action Handler: converts to a JS if-statement checking the response status code and taking appropriate action. Example:
XPath Extractor: converts to a comment recommending a pure JS library be used (see section below on future improvements).
A word about the future
We’re very excited about getting this initial release into the hands of our customers, users and the greater community. We’d love to hear what you think of the tool, especially what you think we should improve. Add a comment to this post, open an issue on Github or reach out through any of the other channels (k6 community forum, k6 Slack or Email). I’ll close off by sharing the next steps we’d like to take with the converter:
Multi-scenario support: In JMeter you can have several different thread groups with independent ramping configurations. This is something we’re working on adding in k6 as well. Once it’s implemented in k6 we’ll expand the converter to support this in a cleaner 1-to-1 way than what is currently implemented.
More logic controllers: There are some logic controllers that we left out of this initial release that we plan to add in a future release. They include:
XPath assertions and extraction: As k6 currently doesn’t support XML parsing nor XPath querying this can’t be implemented without using a third-party JS library. We thus opted to drop it from the initial release, but something we want to add.
Reduce dependencies: The current converter has a dependency on a number of third-party Node.js libraries to bridge the current feature gap between JMeter and k6. As k6 gains these features natiely, we’ll move off of the dependencies.