---
title: 'JMeter Properties: Configurable Test Plans'
url: https://blog.octoperf.com/jmeter-properties-configurable-test-plans/
date: '2019-01-14'
authors:
- sjenkins
categories:
- JMeter
tags:
- JMeter
- Design
- Runtime
- Groovy
- Scalability
description: An in-depth look at the benefits of using JMeter properties to create configurable test plans.
---

# JMeter Properties: Configurable Test Plans

Your company probably runs [**JMeter**](https://jmeter.apache.org/ "JMeter") test plans on a regular basis. Tests constantly need to be adjusted to **change settings** like concurrent users or test duration. **Editing the JMX is time consuming and error prone**.

It's painful, especially if you run test using [Continuous Integration](https://en.wikipedia.org/wiki/Continuous_integration) as part of a [Shift-Left](https://en.wikipedia.org/wiki/Shift_left_testing) strategy. Thankfully, there is a way!

Let me guide you through all the options to **design flexible JMeter test plans** using *configurable properties*. 

## Why Configurable Tests

[**JMeter**](https://jmeter.apache.org/ "JMeter") performance test plans are now commonly being executed throughout the development lifecycle as part of:

- pipelines to focus on a particular service or user journey,
- Isolated [component testing](https://tryqa.com/what-is-component-testing/) as part of development activities,
- And agile [Shift-Left](https://en.wikipedia.org/wiki/Shift_left_testing) performance testing: testing earlier during the development cycle.


But, there is added value in designing configurable tests even with traditional performance testing (like [Soak Testing](https://en.wikipedia.org/wiki/Soak_testing), Scalability Testing, Resilience Testing etc.). The key settings you usually would like to configure are:

- **Threads**: number of concurrent users swarming your servers,
- **Ramp Up**: duration between test start and peak load,
- **Loop Count**: number of user iterations to run,
- **Duration**: test duration in hours, minutes or seconds,
- **Throughput**: requests per second sent to the web application under test.

Being able to configure them **without editing the JMX** (independently from your [**JMeter**](https://jmeter.apache.org/ "JMeter") script) will **increase the flexibility** of your Test Assets. One of the most powerful ways to do this is to abstract these values from your [Test Plans](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans"). But, How?

> *Abstracting*: the act of taking away or separating; withdrawal.

There are several ways to do so:

- **reference variables** on the **command line** explicitely,
- or usng **properties files** during [**JMeter**](https://jmeter.apache.org/ "JMeter") test execution.

This is by no means an exhaustive list of what can be accomplished with properties but does demonstrate that their use **improves the flexibility of [JMeter](https://jmeter.apache.org/ "JMeter") scripts significantly**.

This guide shows you how **properties can do more than just control threads and duration**. They can be used to control most aspects of your tests. Properties are an **extremely powerful addition** to your [performance testing](https://en.wikipedia.org/wiki/Software_performance_testing) skills.

For instance, you can keep the **[**Test Plans**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans") (Asset)** separate from the **Throughput (Load Profile)**. That means: all we need to do to manage multiple test profiles is have multiple properties files.

Let get started!

## Basic Test Plan

Let's create a simple script called [OctoPerf.jmx](https://blog.octoperf.com/img/blog/configurable-test-plans/octoperf.jmx) that browses the [OctoPerf](https://octoperf.com "OctoPerf") website:

1. First, goes to the *Home Page*,
2. then browses the *Blog*,
3. after a while, switches to the *Design* page,
4. and finally, hits the *Pricing* Page.

![Simple Scenario](https://blog.octoperf.com/img/blog/configurable-test-plans/1-simple-scenario.png)

Let's add a [**BeanShell Post Processor**](https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_PostProcessor "BeanShell Post Processor") to output the execution flow in the **jmeter.log** to help demonstrate how the script execution can be affected through the use of the examples in this guide.

![BeanShell Post Processor](https://blog.octoperf.com/img/blog/configurable-test-plans/2-beanshell.png)

The BeanShell will write various information like the **Sampler Name**, **Thread Number**, **Start Time**, **Status Code**, **Total Threads** and **Iteration Number**.

Let's run the test from the command line:

    jmeter -n -t OctoPerf.jmx

Our output in **jmeter.log** shows a single user will perform 1 iteration of the test.

![Log File](https://blog.octoperf.com/img/blog/configurable-test-plans/3-log-file.png)

### Command Line Properties

If we replace our basic Thread Properties values with a [**Simplified Property Function**](https://jmeter.apache.org/usermanual/functions.html#__P "simplified property function") we now have the **flexibility to change the load profile from outside of the script**, our properties are:

- **noThreads**: number of concurrent users to execute,
- **rampUp**: duration (in `seconds`) between test start and peak load,
- **lCount**: total iterations count to run during the test.

![Simple Scenario With Properties](https://blog.octoperf.com/img/blog/configurable-test-plans/4-simple-scenario-with-properties.png)

Now, We can adjust the test profile from outside the [**Test Plan**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans")! Let's now run our test this time with these values passed from the command line by prefixing the property names with -J switch as per the [**JMeter User Manual**](https://jmeter.apache.org/usermanual/functions.html#__P "JMeter User Manual").

```
jmeter -JnoThreads=2 -JrampUp=1 -JlCount=2 -n -t OctoPerf.jmx
```

Now, let's check the **jmeter.log** output: it shows 2 users will perform 2 iterations each, and both will start within 1 second of each other.

![Log File](https://blog.octoperf.com/img/blog/configurable-test-plans/6-log-file.png)

Great! But, can't we do better? Of course, by using a configuration file.

### Simple External Properties File

Properties can also be included in a **flat file** which provides a **further degree of flexibility**, you could simply include the values in the [**user.properties**](https://jmeter.apache.org/usermanual/get-started.html#configuring_jmeter "user.properties") file which is loaded when [**JMeter**](https://jmeter.apache.org/ "JMeter") starts, here’s how:

![User Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/8-user-properties-file.png)

Let's now run our test this time with these values passed into the test from the [**user.properties**](https://jmeter.apache.org/usermanual/get-started.html#configuring_jmeter "user.properties") file.

```
jmeter -n -t OctoPerf.jmx
```

Our output in **jmeter.log** shows 3 users will perform 3 iterations each, and both will start within 2 second of each other.

![User Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/9-user-properties-file.png)

The **most effective and versatile** way to include properties is to create your custom properties file and reference it on the **command line**, let's create a properties file called **octoPerf.properties**.

![Custom Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/9-custom-properties-file.png)

Let's run our same test with this custom properties file passed into the test from the command line using either the -p or -q command line switches, **the difference being** that you use -p for the first properties file and -q for any subsequent ones as stated in the [**JMeter User Manual**](https://jmeter.apache.org/usermanual/get-started.html#options "JMeter User Manual"), as we only have a single properties file we will use the -p switch.

    jmeter -p octoPerf.properties -n -t OctoPerf.jmx

Our output in **jmeter.log** shows 1 user will perform 4 iterations.

![Log File](https://blog.octoperf.com/img/blog/configurable-test-plans/11-log-file.png)

Imagine, you can now have:

- a single *JMX Test Plan*: important settings are imported using the `${__P(propName, defaultValue)}` function,
- **multiple properties files**: depending on the type of test to run, you provide a different configuration file.

For example, you can have a single git repository containing your JMX and the configuration files. Depending on the [Jenkins](https://jenkins.io) job running the test (with *Continuous Integration*), it picks a different properties file.

### Additional Properties

Let us look at other ways we can benefit from abstracting data from the [**Test Plans**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans") to an external properties file. We are now going to use a [**HTTP Request Defaults**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request_Defaults "HTTP Request Defaults") Config Element to *manage the URL for the site or server* we are testing.


![HTTP Header](https://blog.octoperf.com/img/blog/configurable-test-plans/12-http-header.png)

We are going to using the `${__P(propName, defaultValue)}` syntax ([Simplified Property Function](https://jmeter.apache.org/usermanual/functions.html#__P "simplified property function")) in the following settings:

- **Protocol [http]**: can be either `http` or `https`,
- **Server Name or IP**: target server to load test,
- **Port Number**: target server port.

Now, we can adjust the server being tested from outside the JMX.

![HTTP Header With Variables](https://blog.octoperf.com/img/blog/configurable-test-plans/13-http-header-replace.png "Test plan using variables in protocol, hostname and port.")

Then, we move those settings to our custom properties file.

![Custom Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/14-custom-properties-file.png "Introducing `pCol`, `serverName` and `pNo` variables in our previous configuration file.")

We now have the ability to:

- **change the load profile** from our properties file,
- **AND** change the environment against which we test.

Most big companies usually have web applications deployed in multiple environments like *development*, *pre-production*, *qa*. By externalizing the tested server, a **single JMX can be used to test multiple environments**. That's a great way to save time!

## Advanced Test Plan

Let’s try to take this further and use our custom properties file to manage the execution flow of the [**Test Plan**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans").

First, let's add an [**If Controller**](https://jmeter.apache.org/usermanual/component_reference.html#If_Controller "If Controller") to the Design Page [**HTTP Request Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler").

![If Controller](https://blog.octoperf.com/img/blog/configurable-test-plans/15-if-controller.png)

Then, we're going to use *Groovy* to interpret the expression:

```
${__groovy("${__P(executeDesignPage)}" == "true")}
```

And include the property `executeDesignPage=false` in our custom properties file.

![Custom Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/16-custom-properties-file.png)

Let's now run our test and as we have set `executeDesignPage=false` we see that the Design Page [**HTTP Request Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler") has been ignored and only the **Home**, **Blog** and **Pricing** [**HTTP Request Samplerss**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler") have been included.

    jmeter -p octoPerf.properties -n -t OctoPerf.jmx

![Log File](https://blog.octoperf.com/img/blog/configurable-test-plans/16-log-file.png)

By moving these values to an external properties file we can **easily control many aspects of our [**Test Plans**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans")** without adjusting the **.jmx** file.

To complete this section, we are going to change the **Loop Count** to Forever and add a [**Simplified Property Function**](https://jmeter.apache.org/usermanual/functions.html#__P "simplified property function") to the **Duration** field.

![Duration Values](https://blog.octoperf.com/img/blog/configurable-test-plans/17-duration-vals.png)

Let's also add a [**Constant Throughput Timer**](https://jmeter.apache.org/usermanual/component_reference.html#Constant_Throughput_Timer "Constant Throughput Timer") which again uses a [**Simplified Property Function**](https://jmeter.apache.org/usermanual/functions.html#__P "simplified property function") to manage the throughput.

![Transactions Per Minute](https://blog.octoperf.com/img/blog/configurable-test-plans/18-trans-per-min.png)

Let’s add these properties to our custom file

![Custom Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/19-custom-properties-file.png)

Let's now run our test

    jmeter -p octoPerf.properties -n -t OctoPerf.jmx

The `lCount` **property will be ignored** and the test will run for 60 seconds and perform 8 transactions balanced across this time period.

Now we have set `executeDesignPage=true` we will see a single user run each of the 4 [**HTTP Request Samplers**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler") twice.

![Log File](https://blog.octoperf.com/img/blog/configurable-test-plans/20-log-file.png)

Now we can **demonstrate that we can control duration and load** in addition to our other properties.

### Run Time Property Changes

Let’s consider a scalability test where we want to **systematically increase load over a period of time** to see how our application reacts; we can easily manage these load profiles from our external properties file which allows us to change our testing load profile during run time.

We need a [**BeanShell Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_Sampler "BeanShell Sampler") that needs to exist in its own [**Thread Group**](https://jmeter.apache.org/usermanual/component_reference.html#Thread_Group "Thread Group") so it is executed independently to the [**Thread Group**](https://jmeter.apache.org/usermanual/component_reference.html#Thread_Group "Thread Group") that controls the server requests.

![Beanshell Sampler](https://blog.octoperf.com/img/blog/configurable-test-plans/21-beanshell-scalability.png)

Let’s break this sampler down: we are performing a loop that is managed by a property `${__P(noIncrements,1)}`, this is effectively the number of increments we wish to simulate during the test.

A switch statement is used to set the value of our `transPerMin` property in the [**Constant Throughput Timer**](https://jmeter.apache.org/usermanual/component_reference.html#Constant_Throughput_Timer "Constant Throughput Timer") where `increment_1`, `increment_2`, `increment_3` and `increment_4` overwrite the `transPerMin` value in the properties file.

You will need an **increment_** property for each iteration so if your `${__P(noIncrements,1)}` property is set to 10 you will need  to include `increment_1`**......**`increment_10` in your properties file. 

Finally we set a time between increments `Thread.sleep(${__P(incrementDuration,600)});`

Let’s set these values in our properties file:

![Customer Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/22-custom-properties-file.png)

We have 4 increments, `increment_1` will perform 60 requests a minute, `increment_2` will perform 120 requests a minute with the third and fourth increment running at 180 and 240 requests per minute respectively.

The duration between increments will be 2 minutes which needs to be defined as milliseconds and the test duration `durationSec` needs to last for the full duration of the test which is **4 x 2 minutes = 480 seconds**.

The [**Thread Group**](https://jmeter.apache.org/usermanual/component_reference.html#Thread_Group "Thread Group") that the [**BeanShell Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_Sampler "BeanShell Sampler") is contained in uses the same parameter for **Duration** as the [**Thread Group**](https://jmeter.apache.org/usermanual/component_reference.html#Thread_Group "Thread Group") that contains the server requests to ensure they finish at the same time.

![BeanShell Thread Group](https://blog.octoperf.com/img/blog/configurable-test-plans/23-beanshell-threadgroup.png)

Let's run our test; **we will output the results to a flat file** so we can graph the output which will make it easier to display:


    jmeter -p octoPerf.properties -n -t OctoPerf.jmx -l OctoPerf.jtl

Our output shown in the **Hits Per Second Graph** shows us a clear increase of transaction rates every 2 minutes.

![Trans Over Min Graph](https://blog.octoperf.com/img/blog/configurable-test-plans/23-trans-per-min-graph.png)

Let’s wrap the [**BeanShell Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#BeanShell_Sampler "BeanShell Sampler") in an [**If Controller**](https://jmeter.apache.org/usermanual/component_reference.html#If_Controller "If Controller") as we did to the Design Page [**HTTP Request Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler")

![If Controller](https://blog.octoperf.com/img/blog/configurable-test-plans/24-if-controller.png)

Use Groovy to interpret the expression:

    ${__groovy("${__P(executeScalabilityTest)}" == "true")}

Include this property in our properties file.

![Custom Properties File](https://blog.octoperf.com/img/blog/configurable-test-plans/25-custom-properties-file.png)

We now have the ability to control many aspects of our [**Test Plan**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans").

## Real World Benefits

Whilst **data abstraction** is a powerful way to ensure that your [**Test Plan**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans") can support multiple load profiles, against multiple environments and support multiple use journeys for any given duration it is important to define how this can be of benefit in real world examples.

Let’s take 2 custom properties files, we’ll call them:

- `PeakHourLoad.properties`,
- and `SoakTest.properties`.

The **PeakHourLoad.properties** file:

- Runs for 3600 seconds,
- Ramps up to 100 users over 60 seconds,
- Tests the OctoPerf web site,
- Includes the Design Page [HTTP Request Sampler](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler"),
- and Runs at 100 transactions per minute.

![Peak Hour Load File](https://blog.octoperf.com/img/blog/configurable-test-plans/27-peak-hour-load-file.png)

The **SoakTest.properties** file:

- Runs for 24 Hours,
- Ramps up to 100 users over 60 seconds,
- Tests the OctoPerf web site,
- Does not include the Design Page [**HTTP Request Sampler**](https://jmeter.apache.org/usermanual/component_reference.html#HTTP_Request "HTTP Request Sampler"),
- Runs at 100 transactions per minute for 12 hours and then scales up to 200 transactions per minute for 12 hours.

![Soak Test File](https://blog.octoperf.com/img/blog/configurable-test-plans/28-soak-test-file.png)

This gives us a profile for 2 alternative tests so in order to run a **Peak Hour Load Test** followed by a **24 Hour Soak Test** all we need to do is run our OctoPerf.jmx test with each of these properties file.

We could do this as part of a **Jenkins Pipeline**:

![Jenkins Pipeline](https://blog.octoperf.com/img/blog/configurable-test-plans/29-jenkins-pipeline.png)

We could do this on the **command line**:

![Windows Command Line](https://blog.octoperf.com/img/blog/configurable-test-plans/30-command-line.png)

![Linux Command Line](https://blog.octoperf.com/img/blog/configurable-test-plans/31-linux-cl.png)

Whatever your approach you can see how **easy it is to run multiple tests** in succession using the same script asset but using alternative property data values.

Hopefully, this post has given you the keys to make your [**JMeter Test Plans**](https://jmeter.apache.org/usermanual/build-test-plan.html "Test Plans") much more flexible. These tips improve the productivity on JMeter and allow for a greater reuse of existing scripts.
