For Part 1 of this series, please click here.
Test Plan Elements
Up until now we haven't said anything about how to actually do something useful with JMeter, but it's only because we need to cover some boring details of how to configure it before actually running some performance testing.
The picture below introduces the elements we can use in JMeter performance testing program:
We can see that there are the following elements that we can use:
- Thread Groups
- Controllers (Samplers, Logic Controllers)
- Post Processors
- Pre Processors
Let's describe the elements a little bit further.
Thread group element states the beginning of each test plan and is a mandatory element. The next picture shows the configuration settings of a thread group element.
The first option allows us to name the thread group. It's named as "Thread Group" by default. The next option is what should happen when the Sampler fails. Samplers provide JMeter with functionality like sending requests to a server and waiting for a response. Thus we can choose from the following actions if sending a request or receiving a response fails: Continue, Start Next Thread Loop, Stop Thread, Stop Test, Stop Test Now. I guess the actions are self-explanatory, which is why we won't describe them further.
After that comes a very important section, which we must understand correctly.
- Number of Threads (N): Sets the number of threads the JMeter will use to execute our test plan. We must know that each thread will execute the whole test plan, which effectively utilizes the number of users that could use the tested service at any given time simultaneously.
- Ramp-Up Period R: Specifies how much time (in seconds) it will take for JMeter to start all the threads (simultaneous user connections). If the number of users is 5 and the ramp-up time is 10 seconds, then each thread will be started in a 2 second delayed interval. We need to be careful when setting this value, because if the value is too high the first thread will already finish processing the whole test plan before the second thread will even begin. This is important because that would effectively reduce the number of concurrent users using the testing server application at any given time. But the ramp-up period also needs to be high enough to avoid starting all of the thread at a single time, which could overload the target application.
- Loop Count (L): How many times each thread group will loop through all configured elements belonging to that thread group.
At the bottom of the thread group is also a "Scheduler", which can be used to set the duration, starting and ending point of a test scan. This can be seen in the picture below:
There are two types of controllers: samplers and logical controllers.
Samplers are used to send requests and wait for response. The requests can be pretty much any type, from an HTTP request to a LDAP request. If we take a look at the HTTP request sampler, we can see that there are quite a few options that we can set; we can see that in the picture below:
Some of the more important options we can set in the HTTP sampler are the following:
- Server Name or IP: this must be set so that JMeter knows where to send requests (which target application is being tested).
- Port number: the port number is 80 by default, but we can set it to any value if our HTTP server is running on a different port.
- Path: here we can specify the resource path we would like to access, like /index.html or something like that. We can also add various GET/POST parameters with each request or use a Proxy server to send requests through it.
Logic controllers are used to specify when to send the requests, change the requests, change the order of sending the requests, etc. Basically they control how samplers are processed and executed.
Listeners save the responses on issue requests for later analysis. There are numerous listeners that can analyze the results and present them on the graph or something. So far, we already talked about listeners having an option for saving the responses in a csv/xml file, but here we'll take a look at listeners in detail.
To view the results of any kind of sampler we need to add one of the following two listeners:
- View Results in Table
We can see that listener in the picture below:
Basically we don't need to configure the "View Results in Table" element, but we can set a couple of options like the name and description of the element and the filename where to save the responses. Below that is where the graph will be drawn.
- View Results Tree
We can see that listener in the picture below:
Again, there is really nothing complicated about that; we can leave the listener as it is and it will work just fine, no configuration is necessary.
By default JMeter sends requests without waiting between each request. It's advisable that we add a delay element to a Thread Group, which will delay the sending of each request. We can do that by introducing a new Timer element, which will ensure that requests will be sent in a timely fashion, so that not too many requests are sent at a time, which can overload the server application. If there are multiple timers in the scope, the addition of all of them is being used.
We can add a custom timer as shown in the picture below, which delays each thread by 300 miliseconds.
With assertions we can check whether a response contains an exact string we're looking for. We can see the results of an assertion if we add an Assertion Listener to a Thread Group. We can see an Assertion Listener in the picture below:
The configuration elements are being used to additionally change the behavior of Sampler elements. The configuration elements can't make new requests, but can change the requests already being produced by a Sampler.
Preprocessor elements can execute some action before a Sampler sends a request to the target application, which is why we must add these elements to the Sampler elements.
Postprocessor elements are executed after the requests have been sent and a response received. We can use post-processor elements to extract some data from the response.
Scope and Execution Order
We didn't yet talk about the execution order and the scope of the JMeter elements. The execution order and the scope are important features to understand when adding new elements to the test plan.
First we must talk about the scope of the elements. We've seen that we can add arbitrary elements to each other element, so understanding the scope is really important. First we must know that it's the Logical Controllers and Samplers that are the primary elements being used. All the other elements are applied to the Logical Controllers and Samplers.
The Sampler elements are executed the way they appear in a tree regardless of the hierarchy of them. Some of the Logical Controllers can change the execution order of their child Sampler elements, but that is more an exception than a rule. This is why when determining which requests the test plan will execute, we must first look at subsequent Sampler elements. Then we must apply other hierarchical elements to it, namely: Listeners, Config Elements, Pre-processor Elements, Post-processor Elements, Assertions, and Timers.
We know that all these elements are being applied to Logical Controller or Sampler elements, which is why we must determine what elements belong to which. Additionally, Samplers can be added to Logical Controllers and all the elements of a Logical Controller are then applied to its Samplers.
Thus if we have the example presented in the picture below:
We can see that we defined a Test Plan with a Thread Group, which must be defined in every test plan. Then there are two Sampler elements, two Timer elements and one Controller element. We've said that we must apply all elements to the Sampler and Controller elements, which is why we can present the problem differently like this:
- Sampler 1: None
- Sampler 2: None
- Controller 1: None
Now we can assign the two Timer elements to the appropriate Controller and Sampler elements. From the picture above, we can see that Timer 1 belongs to all elements, since it's a direct child of the Thread Group. The Timer 2 element is a direct child of Controller 1, where it belongs. But we also said that all Controller elements are automatically added to its Sampler elements too, which is why the Time 2 element also belongs to the Sampler 2 element. The Timer elements are then added to the Controller and Sampler elements like this:
- Sampler 1: Timer 1
- Sampler 2: Timer 1, Timer 2
- Controller 1: Timer 1, Timer 2
Besides the scope, we must also talk about the execution order, which is the following:
- Configuration elements
Now we have a basic idea of how the elements are applied to the Sampler elements, which actually send the requests to the target application.
Now it is the time to look at some action and actually run performance testing on the most widely used target applications. When doing a penetration test, we often need performance testing of certain web pages (HTTP or HTTPS), but performance testing of a MySQL database and POP3 mail server are equally important.