Moving from JMeter: importing .jmx test plans into Spitfire
You do not need to rewrite your JMeter test plans. Spitfire reads a .jmx file, turns it into a Spitfire test and opens it in the editor: Thread Groups become scenarios, HTTP requests steps, assertions checks. Every element without an equivalent is listed in a report with its line. This page covers what is converted and how, what is not, and the steps.
Steps
- On the Tests page, press Open file and pick the
.jmxfile (up to 4 MB). The file is only read, never run. - The report above the editor says what was converted and how: not converted (missing from the test), check (converted approximately), note (how it was converted). Every line comes with its place in the source file; nothing is dropped silently.
- Review the steps, thresholds and variables; Try sends one iteration of the selected scenario and shows every request and response. Then save.
What is converted, and how
| JMeter | Spitfire |
|---|---|
Thread Group | Scenario: constant or ramping (ramp-up) VUs with a duration, iterations per VU with a loop count |
HTTP Request | HTTP step: method, URL, parameters, body |
HTTP Request Defaults · Header Manager | Base address and headers on every request below |
Response · Duration · JSON Assertion | Checks |
JSON Extractor · Regular Expression Extractor | Extraction from the response |
Constant · Uniform Random Timer | Think time |
User Defined Variables · ${__P(x,default)} | Variables with their defaults |
${__Random} · ${__UUID} · ${__time} · ${__threadNum} | Spitfire template functions |
Transaction · Simple Controller | Flattened; its name prefixes the steps |
Disabled elements are left out. A Thread Group with both a duration and a loop count is converted by duration; one that loops forever with no duration is set to 10 minutes; the report says both. A timer applies to every request in its scope and is set as think time on the requests before it.
A JMeter plan has no thresholds; if you want the test to pass or fail, add them in the editor's Thresholds tab (for example p(95)<500, rate<0.01). The report reminds you of this too.
Example: before and after
A small plan that starts 50 users over 60 seconds and runs for 6 minutes, with one GET request, a response code assertion and a 1-second constant timer:
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0">
<hashTree>
<TestPlan testname="Checkout" enabled="true"/>
<hashTree>
<ThreadGroup testname="Shoppers" enabled="true">
<stringProp name="ThreadGroup.num_threads">50</stringProp>
<stringProp name="ThreadGroup.ramp_time">60</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">360</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController">
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy testname="List items" enabled="true">
<stringProp name="HTTPSampler.domain">shop.example.com</stringProp>
<stringProp name="HTTPSampler.protocol">https</stringProp>
<stringProp name="HTTPSampler.path">/api/items</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
</HTTPSamplerProxy>
<hashTree>
<ResponseAssertion testname="200" enabled="true">
<collectionProp name="Asserion.test_strings"><stringProp name="49586">200</stringProp></collectionProp>
<stringProp name="Assertion.test_field">Assertion.response_code</stringProp>
<intProp name="Assertion.test_type">8</intProp>
</ResponseAssertion>
<hashTree/>
</hashTree>
<ConstantTimer testname="Think" enabled="true">
<stringProp name="ConstantTimer.delay">1000</stringProp>
</ConstantTimer>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>The test the converter wrote (the general options block left out). The 60 s ramp-up and the 360 s duration became a 1-minute climb and a 5-minute hold:
{
"name": "Checkout",
"scenarios": [
{
"name": "shoppers",
"executor": {
"type": "ramping-vus",
"stages": [{"duration": "1m0s", "target": 50}, {"duration": "5m0s", "target": 50}]
},
"steps": [
{
"id": "list_items",
"name": "List items",
"protocol": "http",
"request": {
"method": "GET",
"url": "https://shop.example.com/api/items",
"body": {"type": "none"}
},
"checks": [{"name": "200", "type": "status", "op": "eq", "value": 200}],
"thinkTime": {"min": "1s"}
}
]
}
]
}What is not converted
These are listed in the report with their line; you set up the Spitfire equivalent by hand before saving:
- If, Loop and While Controllers: Spitfire runs the steps in order; every iteration is the whole flow.
- CSV Data Set Config: upload the CSV under Data files and bind it to the test; columns become variables such as
{{users.email}}(in order, random or unique across runners). - Non-HTTP samplers (JDBC, JMS…): Spitfire supports SQL, Kafka, MQTT, AMQP, Redis, MongoDB, gRPC and WebSocket built in; add the step in the editor.
- JSR223 and BeanShell scripts: free-form code has no equivalent; extraction, checks and template functions cover most cases.
- Plugins and listeners that write results to files: results are on the run page; reports download as PDF, HTML or CSV.
A whole folder
Select several files in Open file and the bulk import page converts, validates and lists each with its report; you save the ones you pick with one button. On the command line one command converts a folder; one test file is written per script and every report line goes to the CSV (file, test, line, level, message):
spitfire convert ./tests -o spitfire-tests/ -r report.csvSpitfire installs on Docker or Kubernetes with one command; every testing feature and protocol is open in the free edition.