GUI & Test Plan Workflow

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

Baseline date: 2026-10-14. This page was written against Apache JMeter 5.6.3, the latest release on that date (Java 8 or later, Java 17 or later recommended; Java 21 is used in the examples). JMeter 6.0 is not released. The master branch declares 6.0.0 and requires Java 17 or later, and this page names the planned 6.0 changes that touch the GUI workflow as planned, not as released behaviour. The Plugins Manager (2.0), the jmeter-maven-plugin (3.8.x) and the gRPC Request plugin (2.0.x) are not needed on this page. The books used for the methodology (JMeter Cookbook, Performance Testing with JMeter and Pro Apache JMeter) target JMeter 2.11, 2.12 and 3.0, so every menu path below is taken from the current official documentation and jmeter.properties of 5.6.3.

The JMeter GUI is a Swing application. It has one job: to build a test plan (a .jmx file) and to prove that the plan works against a single user. It is not a load generator. This page covers the test tree and how to edit it, saving and backups, templates, Test Fragments for re-use, searching, the Validate, Start and Start no pauses commands, stopping a run with Stop or Shutdown, the GUI settings, and the reasons for leaving the GUI before generating load. The elements themselves are described in Test Plan Elements, Execution Order & Scoping, the first launch in Installation & Configuration and the architecture behind it in Introduction & Architecture.

The window and the test tree

JMeter starts its GUI when bin/jmeter (Unix) or bin\jmeter.bat (Windows) is run without -n. The window has a menu bar, a toolbar, the test tree on the left and the configuration pane of the selected element on the right. A counter at the top right shows the number of error and fatal messages written to jmeter.log; clicking the warning icon opens the log viewer (see The log viewer).

The tree contains a Test Plan as its root. Every element in the tree is one of the types described in the elements page: Thread Groups, Samplers, Logic Controllers, Config Elements, Timers, Pre- and Post-Processors, Assertions, Listeners and Test Fragments. Where an element sits in the tree decides which samplers it applies to, and the order of siblings decides the order of execution for samplers and controllers. The GUI therefore shows the plan exactly as the engine will interpret it, which is why working in the tree is the safest way to author a plan.

Editing the tree

Operation How Notes

Add an element

Right-click a node, then Add, then pick the element type (for example Add → Threads (Users) → Thread Group, Add → Sampler → HTTP Request)

The menu offers the element types that make sense for the selected node.

Remove an element

Select it, right-click, Remove

Removes the element and all of its children.

Move an element

Drag and drop within the tree

Moving changes scope and order. A Config Element dropped into a different Thread Group no longer applies to the old one.

Cut, copy, paste

The toolbar buttons

Paste adds a copy of the copied branch under the selected node.

Enable or disable

The toggle button on the toolbar

A disabled element is greyed out, is saved with enabled="false" and is ignored when the plan runs.

Expand and collapse

Toolbar buttons

Useful for big plans.

Merge saved elements

Right-click the target node, Merge

Merges the elements of another .jmx file below the selected node.

Save part of a plan

Right-click an element, Save Selection As … (also in the Edit menu)

Saves the element and its children as a separate .jmx, handy for sharing a Thread Group or a fragment.

The default toolbar is defined by the property jmeter.toolbar in jmeter.properties (new, open, close, save, save as test plan, cut, copy, paste, expand, collapse, toggle, start, stop, shutdown, remote start/stop/shutdown, clear, clear all, search, reset search, function helper, help). It can be overridden in user.properties.

Enable and disable as a debugging tool

Toggling is the cheapest way to isolate a failing element: disable a Timer to speed up a trial run, disable a Listener that writes large result files, or disable a branch of a Transaction Controller to see whether the problem is in it. A disabled element is not executed, but it stays in the file, so a plan can carry optional pieces (for example a Backend Listener that is only enabled for runs against a monitoring stack). One consequence matters for Test Fragments: a Test Fragment is disabled by default since 2.13, otherwise its content would run twice.

Keyboard shortcuts documented by the project

The official documentation lists the following shortcuts. Shortcuts for other menu entries are shown next to the entry in the menu itself and depend on the platform, so use the menu as the reference.

Shortcut Action

Control + R

Run, Start

Control + .

Run, Stop

Control + ,

Run, Shutdown

Control + 0 to Control + 9

Quick-add elements, see Hotkeys to add elements

Saving, backups and the .jmx file

A test plan is saved as XML in a .jmx file with File → Save or File → Save Test Plan As …. The file is meant to be kept in version control and to be run from the command line, so some habits help: use relative paths for CSV files and proto files, keep credentials out of the plan (use -J properties or CSV files with placeholders), and keep result files out of the repository. The .jmx format is verbose but diff-friendly when the plan is not re-ordered needlessly.

JMeter keeps backups of the plan whenever it is saved from the GUI (since 3.0). They are configured in user.properties:

Property Default Meaning

jmeter.gui.action.save.backup_on_save

true

Before the .jmx is overwritten, a copy is written to the backup directory.

jmeter.gui.action.save.backup_directory

empty, which means ${JMETER_HOME}/backups

Directory for the backups. Created when missing.

jmeter.gui.action.save.keep_backup_max_hours

0

Maximum age of backups in hours. 0 keeps them for ever. Age expiry is applied before the count limit.

jmeter.gui.action.save.keep_backup_max_count

10

Maximum number of backups kept. 0 means backups are not deleted by count unless the hours property is set.

save_automatically_before_run

true

The plan is saved, and backed up, before a run starts from the GUI.

Backup names follow the plan name with an incrementing number, for example bookshelf-load-000012.jmx when the last backup was bookshelf-load-000011.jmx.

# user.properties: keep 50 backups outside the installation directory
jmeter.gui.action.save.backup_on_save=true
jmeter.gui.action.save.backup_directory=/var/backups/jmeter
jmeter.gui.action.save.keep_backup_max_count=50

The cost of auto-save is small, but the backup directory grows with every save of a large plan, and save_automatically_before_run=true means that pressing Start also saves unfinished edits. If a plan must not be touched until it is deliberately saved, set that property to false.

Templates

File → Templates … (or the Templates toolbar icon) opens a list of ready-made plans. Choosing one creates a new plan; a template that has parameters (for example the recording template) opens a second window where the values are entered and then confirmed with the Validate button. The templates shipped in the 5.6.3 bin/templates/templates.xml are:

Template Use

Recording, Recording with Think Time

A plan with an HTTP(S) Test Script Recorder configured and a Thread Group to receive the recorded samples, with parameters such as the host and scheme to record. Recording itself is covered in a later page.

Simple HTTP request

A minimal Thread Group with one HTTP request and listeners.

Building a Web Test Plan, Building an Advanced Web Test Plan

The plans of the user manual tutorials.

Functional Testing Test Plan [01]

The functional testing tutorial plan.

Building a SOAP WebService, FTP, LDAP and Extended LDAP Test Plan

Tutorial plans for those protocols.

JDBC Load Test

A JDBC connection configuration and request.

MongoDB Load Test

A plan for the MongoDB elements, which the planned 6.0 release removes.

JSR223 Sampler using Groovy, BeanShell Sampler

Fragments (not complete plans) to add scripting; prefer JSR223 with Groovy.

Think Time at a point

A fragment that adds a think time.

The list can be extended: the property template.files in jmeter.properties names the XML file that describes the templates, and a template is an entry with a name, a .jmx file name, a description and optional parameters. Because the shipped list changes between releases (the SOAP and MongoDB entries are examples of features that are old or being removed), a template is a starting point to read, not a pattern to copy blindly.

Test Fragments: re-use inside a plan

A Test Fragment (Add → Test Fragment → Test Fragment) sits on the tree at the same level as a Thread Group but is never run by itself. It holds a branch of controllers and samplers that other places include by reference, so that one login sequence or one checkout journey is written once.

  • An Include Controller loads the branch of another .jmx file (the file name is a field of the controller).

  • A Module Controller runs a Test Fragment, or any other controller, of the same plan, chosen from the tree.

  • The Test Fragment has only a name. It is disabled by default, which the component reference describes as the correct state when used with a Module Controller, so that the fragment is not executed on its own.

For the Bookshelf scenario the login steps are kept in a fragment so that both the journey plan and a smaller smoke plan reuse them:

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.6.3">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Bookshelf fragments"/>
    <hashTree>
      <TestFragmentController guiclass="TestFragmentControllerGui"
                              testclass="TestFragmentController" testname="Login" enabled="true"/>
      <hashTree>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="POST /api/auth/login">
          <stringProp name="HTTPSampler.domain">localhost</stringProp>
          <stringProp name="HTTPSampler.port">8080</stringProp>
          <stringProp name="HTTPSampler.path">/api/auth/login</stringProp>
          <stringProp name="HTTPSampler.method">POST</stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

The fragment can be saved on its own with Save Selection As … and pulled into other plans with an Include Controller. The XML above shows the structure the GUI writes, with the fragment enabled as in a file meant for an Include Controller; a Test Fragment created in the GUI starts disabled, which is the state to keep when a Module Controller in the same plan references it. Building the fragment through the menu and saving it is the recommended way to produce a valid file.

Pitfalls: a relative path in an Include Controller or a CSV Data Set Config depends on the directory JMeter is started from, so check that a plan which works from the GUI also works when started from a CI job; variables used inside a fragment must exist where it is included; and in distributed testing the included file must exist on every node, as CSV files must.

Searching the tree

Large plans need search. JMeter has a menu search (since 2.6) with two options: Case sensitive and Regular exp., which treats the text as a regular expression over the component tree. The toolbar has matching search and reset search buttons. Matching nodes are highlighted, and resetting clears the highlight. Use it to find every element that mentions a host name or a variable before renaming it.

Checking and running from the GUI

Command Behaviour

Run → Start

Runs the whole plan with its timers and the configured number of threads.

Run → Start no pauses

Runs the plan but without running the timers, so think time is skipped. It is a quick way to check the sampler logic. It is not a load test: with no pauses, the threads fire as fast as the server answers.

Validate (right-click a Thread Group)

Runs only that Thread Group in validation mode.

Right-click a selection of Thread Groups, Start

Starts only the selected Thread Groups (since 3.0).

Right-click a selection, Start no pauses

Starts only the selected groups without timers.

Run → Stop

Stops threads as soon as possible.

Run → Shutdown

Lets running samples finish and stops threads afterwards.

Run → Clear and Clear All

Remove the results from the selected listener, or from all listeners. Clear before every run, or old results mix with new ones.

Validate

Validation mode runs a Thread Group with one thread, one iteration, no timers and a startup delay of zero, so a new or changed Thread Group can be proved in seconds without editing its load settings. The behaviour is controlled by properties in user.properties:

Property Default Meaning

testplan_validation.nb_threads_per_thread_group

1

Threads used to validate a Thread Group.

testplan_validation.number_iterations

1

Iterations used.

testplan_validation.ignore_timers

true

Timers are ignored.

testplan_validation.ignore_backends

true

Backend Listeners are ignored, so a validation does not write to InfluxDB or Graphite.

testplan_validation.tpc_force_100_pct

false

When true, a Throughput Controller in percentage mode runs as if it were 100 %.

testplan_validation.tree_cloner_class

org.apache.jmeter.validation.ComponentTreeClonerForValidation

The class that builds the validation tree. A custom policy must extend org.apache.jmeter.engine.TreeCloner.

Worked example. The Bookshelf Thread Group has 50 threads, a 60 s ramp-up (about 0.83 threads started per second), a Constant Timer of 1000 ms after every request and 5 requests per iteration. A full iteration takes at least 5 s of think time plus the response times. Validate starts one thread, runs it once and skips the timers, so a run that would take minutes finishes in the time of 5 responses, for instance 1 s in total if each answers in 200 ms, and the View Results Tree shows every request and response for that single user.

A debugging loop that works

  1. Add a View Results Tree and, if needed, a Debug Sampler to the plan (see the Listeners page for their cost).

  2. Select the Thread Group and choose Validate.

  3. Read the request, the response data and the assertion results in the View Results Tree. The tree also offers renderers and testers for regular expressions, XPath, JSON and CSS selectors, so extractors can be tried against a real response.

  4. Fix the extractor, assertion or parameter, and repeat.

  5. When the single user works, disable or remove the View Results Tree and the Debug Sampler before any load run.

The View Results Tree keeps every response in memory in the JVM of the GUI, which is the main way a GUI run exhausts the heap. The limits view.results.tree.max_results (default 500 in jmeter.properties) and view.results.tree.max_size (default 10485760 bytes) limit what it shows, and a disabled listener costs nothing.

Source: Getting Started

Stop versus Shutdown

Stop Shutdown

Shortcut

Control + .

Control + ,

Effect

Threads are stopped as soon as possible and active samples may be interrupted

Threads finish the current sample and stop, no new iterations begin

Wait

Waits for threads to stop, 5000 ms by default (jmeterengine.threadstop.wait)

If it takes too long, close the dialog and use Stop

tearDown Thread Groups

Never run

Run only when Run tearDown Thread Groups after shutdown of main threads is checked on the Test Plan

Use when

A sampler hangs or the plan is wrong

A clean end of a long run is needed so the last samples are recorded

In CLI mode the same two operations are sent to the running instance by the scripts shutdown.sh / shutdown.cmd (graceful) and stoptest.sh / stoptest.cmd (abrupt) on port 4445, set by jmeterengine.nongui.port; if the first port is busy JMeter tries up to jmeterengine.nongui.maxport (4455), and a port of 1000 or less disables the listener. The Thread Group’s own Action to be taken after a Sampler error has the options Continue, Start Next Thread Loop, Stop Thread, Stop Test (end after current samples) and Stop Test Now (interrupt samplers), which follow the same graceful versus abrupt split.

GUI settings

All settings below are properties; the file jmeter.properties must not be edited, since an upgrade replaces it. Put overrides in bin/user.properties.

Look and feel, and the toolbar

The look and feel can be chosen from Options → Look and Feel, where a tooltip lists the class names available. To set it permanently, use jmeter.laf in user.properties with either a full class name or one of the strings System or CrossPlatform. It can be refined per operating system: jmeter.laf.windows, jmeter.laf.mac and a name derived from os.name such as jmeter.laf.windows_xp. If none is defined, JMeter uses the CrossPlatform look and feel. The Darklaf look and feels also accept darklaf.decorations (default false) and darklaf.unifiedMenuBar (default true).

# user.properties
jmeter.laf=System
# Which toolbar buttons are shown
jmeter.toolbar=new,open,save,|,toggle,|,test_start,test_stop,test_shutdown,|,test_clear,test_clear_all,|,search,search_reset,|,function_helper,help

HiDPI

On Java 9 and later, scale the whole UI with the Java property sun.java2d.uiScale, for example export JVM_ARGS="-Dsun.java2d.uiScale=200%" before starting ./bin/jmeter. Java 8 has no Swing HiDPI support; for it JMeter offers a partial mode that affects tree nodes, toolbar icons, tables and text-area fonts only:

Property Value Effect

jmeter.hidpi.mode

true

Enables the pseudo-HiDPI mode (default false).

jmeter.hidpi.scale.factor

2.0

Scales some UI elements (default 1.0).

jmeter.toolbar.icons.size

22x22, 32x32 or 48x48

Toolbar icons, 48x48 suggested for HiDPI.

jmeter.tree.icons.size

19x19, 24x24, 32x32, 48x48

Tree icons, 32x32 suggested for HiDPI.

jsyntaxtextarea.font.family and jsyntaxtextarea.font.size

for example Hack and 28

Font of script editors.

Hotkeys to add elements

The properties gui.quick_0 to gui.quick_9 bind Control + 0 to Control + 9 to element classes. The defaults are for a Windows QWERTY keyboard and need adapting on other platforms.

Key Default element

Ctrl+0

Thread Group (ThreadGroupGui)

Ctrl+1

HTTP Request

Ctrl+2

Regular Expression Extractor

Ctrl+3

Response Assertion

Ctrl+4

Constant Timer

Ctrl+5

Test Action

Ctrl+6

JSR223 PostProcessor

Ctrl+7

JSR223 PreProcessor

Ctrl+8

Debug Sampler

Ctrl+9

View Results Tree

# user.properties: Ctrl+4 adds a Uniform Random Timer instead of a Constant Timer
gui.quick_4=UniformRandomTimerGui

The log viewer

Options → Log Viewer shows jmeter.log in a pane under the tree. jmeter.loggerpanel.display=true shows it at start-up. jmeter.loggerpanel.enable_when_closed (default true) lets it collect events while closed, at a small cost in performance that the properties file accepts because the GUI is not used for load. jmeter.loggerpanel.maxlength limits what the panel keeps (1000 in jmeter.properties, 0 means unlimited). Logging itself is configured in log4j2.xml since 3.2, and -L overrides a level on the command line. Another property, jmeter.gui.refresh_period (default 500 ms), sets how often the GUI processes listener events.

View Results Tree and the browser renderer

On a JDK newer than 8 the HTML browser renderer of the View Results Tree needs JavaFX installed separately: set PATH_TO_FX to its lib directory and add --module-path $PATH_TO_FX --add-modules javafx.web,javafx.swing to JAVA9_OPTS in bin/jmeter. JMeter is not a browser, and these renderers are for reading responses, not for executing them.

Why the GUI is for building and debugging only

The official manual states it directly: do not run a load test in GUI mode; use the GUI to create and debug the plan and run the test in CLI mode. The reasons are mechanical.

  • Listener cost. GUI listeners such as the View Results Tree, Table and graphs keep samples in memory and redraw on a timer. The View Results Tree stores every response it displays, so memory use grows with response sizes and request counts.

  • Shared CPU. The GUI, the engine and the sample collectors compete for CPU on the machine that generates the load, which can inflate measured response times so that they reflect the injector, not the server.

  • Heap. The default heap is set by HEAP (-Xms1g -Xmx1g and a metaspace limit) and is shared between the GUI and the load threads.

  • Repeatability. A .jmx with -J properties and a results file gives the same run on a laptop, a CI agent and a load-generation node. A hand-driven GUI session does not.

A workable split is: build and debug in the GUI with Validate, one thread and a View Results Tree; save; then run jmeter -n -t bookshelf-load.jmx -l results.jtl from a terminal, as described in the CLI mode page, and read the results afterwards in the dashboard or in a listener opened on the .jtl file.

jmeter -n -t bookshelf-load.jmx -l results.jtl -e -o report

Changes across versions

Version Relevant change

2.x books

Plans were built around a WorkBench, and non-GUI mode was the name for what is now CLI mode.

3.0

Selected Thread Groups can be started alone, and backups are made on save.

3.2

Logging moved to log4j2.xml; the Monitor Results listener was removed.

4.0

The WorkBench was removed; templates and the recording template replace it.

5.1

The documentation calls non-GUI mode CLI mode.

5.6.3

Current release: the behaviour on this page.

6.0 (planned)

Per changes.xml on master: Java 17 or later is required, and MongoDB elements are removed, which also affects the MongoDB template. The master branch is unreleased and may change.

Source: Changes History and Changes

References