JMeter JKnowledge: Properties and Variables

JMeter JKnowledge is a chance to take a moment away from the tutorials and learn a little bit more about some of the concepts we have been or will be using.

It’s very important as your tests become more complicated, and we move ever closer to taking our functional testing work and utilizing it to perform load and performance testing, that we have a good understanding of what Properties and Variables are in JMeter, as well as their benefits and limitations.

In all likelihood every test plan you create will rely on both JMeter Properties and Variables. Understanding how both work is crucial to being able to accomplish your automation goals.

We will discuss three types of Properties and Variables, and ways to set and manipulate them. Perhaps counter-intuitively, we will start from the bottom and work our way up.

Contents

  1. Thread Level Variables
  2. User Defined Variables
  3. JMeter Properties
  4. Referencing and Setting Property and Variable Values

Thread Level Variables

Thread level variables are variables whose values are unique to the thread using them. For instance if you have a ThreadGroup called LogIn and you have that ThreadGroup simultaneously running three threads (simulating three users logging in at the same time) then each thread (or user) would have their own thread level variables for username and password. That way each thread is logging in as a different user.

This is incredibly useful when running many threads of the same workflow, but wish for each thread to vary from others running the same workflow.

It might be easiest to think of ThreadGroups as a Workflow Definition, and Threads running off the ThreadGroup as individual Users executing that workflow.

Since thread level variables are specific to the thread which is using them, no other thread can access them.

Creating Thread Level Variables

Thread level variables can be created a number of ways, and if you have been following the tutorials you have already seen a couple ways of creating them and setting their values.

Parameterized Controllers are one easy and convenient way of creating a thread level variable and setting its value when you need it. In the tutorials we have used Parameterized Controller to create and set variables which we then use when calling a Sampler. For instance when we call our SignIn Sampler Library module we first use a Parameterized Controller to set the username and password to use for signin.

Thread level variables can also be created by using a Post Processor Extractor. Our SignIn Library module extracts the server supplied token into a “token” variable and populates its value.

You can also create thread level variables in Beanshell scripts by using the “vars” variable. In the Life in a Beanshell tutorial we used a Beanshell script to save a folder id into a variable with the following line of Java code.

vars.put(“getFolderId”, folderid.toString());

These are just some of the ways to create thread level variables, but the three most common I find myself using.


User Defined Variables

User Defined Variable documentation on apache.org.

It’s easy to think User Defined Variables are something more than they really are. The simplest, and perhaps most accurate, way to think of User Defined Variables are as a starting set of variables and values for your entire test plan.

We use User Defined Variables in the tutorials to specify our API resources or urls for all of our API calls to use, across all ThreadGroups and threads. We also position it in our test plan at the very top to signify that the variables defined there will affect the entire test plan.

We also use the User Defined Variables directly on the test plan itself to define and set variables needed by our API Resources.

It is important to know that all User Defined Variables are processed at the start of the test run. This means that if you have more than one User Defined Variables object, they will both be processed at the start of the test, and then the variables will copied to every thread when it begins to run. Each ThreadGroup does not have a unique set of User Defined Variables. At the time the thread starts, it begins with the same User Defined Variables and values as all other threads.

Additionally, since all User Defined Variables are processed in order at the beginning of a test, if two User Defined Variables contain variables with the same name, only one variable will be created and that variable will have the value from the last User Defined Variable object processed.

Consider the following scenario with three User Defined Variables, one at the Test Plan level:

one under Thread Group 1

and one under ThreadGroup2

Running this test plan would result in both ThreadGroup1 and ThreadGroup2 getting the following variables and values when the test starts:

var1 = ThreadGroup2 Value
var2 = ThreadGroup2 Value
var3 = ThreadGroup2 Value
var4 = ThreadGroup1 Value
var5 = Test Plan Value

It’s this behavior that can make User Defined Variables tough to use and manage, since every variable you create you need to make sure is uniquely named. Additionally, since all threads get the same copy of the User Defined Variables each thread may get way more variables than it needs.

It is valuable to note, however, that once the thread receives it’s copy of the User Defined Variables, those variable become thread level variables. This means that while the thread will begin with the default variables and values, they can be modified by the thread itself afterward, and those changes are specific to that thread.


JMeter Properties

JMeter Properties are variables which live above all ThreadGroups and are available to all threads. Therefore JMeter Properties can be used to share data across threads and even across ThreadGroups.

If thread1 creates and sets a Property, then thread2 (even if it’s part of another ThreadGroup) can access the Property and its value (and even change the Property’s value).

So far, in the tutorials, we haven’t had much use for Properties. In functional testing its generally a best practice to keep tests as atomic as possible and to not have one test rely on the output of another.

Properties become far more useful when using JMeter for load and performance testing. However, even then, you’ll want to make your choice of using a Property carefully as you’ll not have good control over the timing of threads running in parallel, and the thread which expects the Property value to be populated might be running faster than the thread populating the value.

I have found JMeter Properties to be most useful when my load tests require the creation of a number of accounts and users, which the tests will need to use. In that case, I create a setUp Thread, which runs before all other test threads, and creates accounts and users in the system under test, then populates the user and account info into a Property. When each of the test threads runs, the first thing it does is get the account and user Property and check out a user to use in the test. When the test is done, the thread gets the account and user Property again and checks the user back in for other threads to use.

Creating JMeter Properties

JMeter Properties can be created by creating your own user.properties file and modifying your jmeter.properties file to also load your user.properties.

However, I have always created Properties via BeanShell. Properties can be created the same way as variables in BeanShell, but by using the “props” variable. The following line will create a Property called “MyFirstProp”:

props.put(“MyFirstProp”, “This is my first JMeter Property”);


Referencing and Setting Property and Variable Values

Properties, User Defined Variables, and thread level variables can all be accessed with ${} notation in most JMeter objects.

For example you could use a user_password variable in the body fo a HTTP Request Sampler like so:

{
“password”: “${user_password}”
}

Or in an If Controller (and many other JMeter objects) like so:

“${outcome}” == “Success”

User Defined Variables and thread level variables, aside from being created by other JMeter objects like Post Processor Extractors, can also be created and set in BeanShell by using either:

vars.put()
vars.putObject()

vars.put takes two parameters; a variable name and a String value. You can provide an existing variable name to replace an existing variable value.

vars.put(“AStringVariable”, MyIntegerValue.toString());

vars.putObject also takes two parameters; a variable name and any object as a value (does not have to be a String).

vars.putObject(“UserInfo”, new HashMap());

Conversely variables can be retrieved by:

vars.get(“AStringVariable”);
vars.getObject(“UserInfo”);

Properties can be accessed in much the same way, however props.put() does not need to be a String.

props.put(“StringInteger”, MyIntegerValue.toString());
props.put(“Integer”, MyIntegerValue);
props.put(“UserInfo”, new HashMap());
props.get(“UserInfo”);


Summary

So there you have it! Those are three of the most common types of variables in JMeter, and how to use them. Now you are ready to write well organized tests leveraging the right type of variable in every situation. No doubt you will find a use for each type in every test plan.

Happy testing!

Leave a Reply

Your email address will not be published. Required fields are marked *