Apache JMeter Testing

From Training Material
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Nobleprog.svg


Apache JMeter Testing


What is JMeter

Apache JMeter

  • Open source project
  • Started in the late 1990s
  • Part of the Apache Foundation
  • Complete portability and 100% Java purity

JMeter is a testing tool

  • Full multithreading framework allows concurrent sampling by many threads
  • Simultaneous sampling of different functions by separate thread groups.
  • Test Plan building and debugging.
  • Caching and offline analysis/replaying of test results.
  • Apache JMeter features include:
    • Ability to load and performance test many different server/protocol types:
      • Web - HTTP, HTTPS
      • SOAP
      • FTP
      • Database via JDBC
      • LDAP
      • Message-oriented middleware (MOM) via JMS
      • Mail - SMTP(S), POP3(S) and IMAP(S)
      • MongoDB (NoSQL)
      • Native commands or shell scripts
      • TCP
    • Highly Extensible core:
      • Pluggable Samplers allow unlimited testing capabilities.
      • Several load statistics may be choosen with pluggable timers .
      • Data analysis and visualization plugins allow great extensibility as well as personalization.
      • Functions can be used to provide dynamic input to a test or provide data manipulation.
      • Scriptable Samplers (BeanShell, BSF-compatible languages and JSR223-compatible languages)
References:
Apache JMeter website
Apache JMeter Online Manual
Tutorialspoint JMeter Tutorial
Another JMeter Tutorial

JMeter requires Java to run

  • It is written in Java
  • To run it needs a Java Virtual Machine (JVM)

JVM, JRE, JDK - what are these?

JVM - Java Virtual Machine

  • Runs Bytecode produced by the Java Compiler
  • Allows Java to run on multiple types of hardware (write once, run anywhere)
  • Interprets Bytecode into the instruction set of the hardware
  • Can use JIT (just in time) compilation
References:
Wikipedia Article on JVM
NobleProg Page on JVM
Wikipedia Article on JIT Compilation

JRE - Java Runtime Environment

  • Contains the Java Virtual Machine, code Libraries, and other components
  • Allows applications and applets written in Java to run
  • Can be either Standard or Enterprise
References:
Java Standard Libraries
Java Enterprise Libraries

JDK - Java Development Kit

  • An implementation of one of the Java SE, Java EE, or Java ME platforms
  • For a particular Hardware and Operating System such as Windows, Linux, Solaris, or Mac OS
  • Contains JRE (with JVM), and Tools to develop applications
  • Important tools it has include, compiler, debugger, JavaDoc generator, JAR archiver
  • Most development uses an IDE such as Eclipse or NetBeans that may access the tools in the JDK
References:
Wikipedia Article on the JDK
Diagram of JDK vs JRE etc.

Java SE versus EE

  • Java EE is built on top of SE components
  • The more important components in EE are designed to help build
  • Web Applications (Servlets, JSP, JSF, etc.)
  • Enterprise Applications (EJB, Database connectivity, Message Services)
  • There are numerous packages in EE

Install the Java SE JDK

Hands on Exercise - Install the Java JDK:
Using the following document install the Java JDK that corresponds to the type of Operating system that exists on your computer (Windows, Mac OS, Linux x64, etc.). The installation steps will be approximately the same for each operating system.
Installing the JDK


Understanding the development process

Set up a development web server

  • The web server builds and serves web pages to browsers
    • Browsers - Firefox, Chrome, Internet Explorer, Safari, etc.
  • A Development web server generally is on a developer's computer
    • The code base is put onto the server such that the developer can step through web pages that are built by the server.
    • These days this is usually done in an Integrated Development Environment (IDE)
      • Eclipse
      • Netbeans
      • Visual Studio
      • Intellij


Install Eclipse IDE

Hands on Exercise - Install an Integrated Development Environment (IDE):
Using the following instructions install Eclipse on your computer. Eclipse is an Integrated Development Environment commonly used by developers. Installation steps will be approximately the same for all operating systems. There is only one installation zip file for all operating systems.
Installing Eclipse

Install Apache Tomcat

Hands on Exercise - Install a Web Server
Install Tomcat on Windows

Apache httpd

  • The original Apache project
  • Handles static HTML pages
  • Can sit in front of Tomcat
  • Can use a connector to send JSP's to Tomcat
  • Apache httpd handles static pages
  • Tomcat handles JSP's and Servlets
  • Tomcat can handle static HTML pages on its own


Create a small web application for use in testing

HTML Static Pages

Servlets

  • Tomcat has a Servlet Container. The Servlet Container:
    • Gets HTTP requests from clicks on web pages (usually)
    • Keeps state for the user through cookie JSESSIONID, web pages are stateless
    • Delegates the request to a servlet.
    • Returns a response to the requester.
  • A servlet:
    • Is a component of a Java Web Application (usually)
    • Is a Java class that extends HttpServlet (usually)
    • Is configured to handle requests for a specific web page
    • Gets requests from the Servlet Container
    • Give responses back to the Servlet Container
Hands on Exercise
Step 1 - Click and save the Web Project WAR file that is zipped below
Step 2 - Extract the WAR file from the zip
Step 3 - Start Eclipse if it is not already running
Step 4 - Import the WAR file below into Eclipse
Step 5 - Go over the examples of JSPs and Servlets with the instructor
Note that "Create a Servlet and WAR file in Eclipse" and "Create an Eclipse Web Project" are discussions on how to create web projects and Servlets. The WAR file to be imported was created by making a web project and then creating servlets and JSPs within that project. Those files were then export as the WAR.
Web Project WAR file that is zipped
Create a Servlet and WAR file in Eclipse
Create an Eclipse Web Project
References
Servlets Tutorial
Tomcat Servlet Examples Explained
HTTP Methods Get vs Post
Using WebServlet Annotation in Tomcat

JSPs

JavaServer Pages (JSPs) are another component of a Web Application.

JavaServer Pages:

    • Mix HTML with Java Code by using scriplets <% some code %>
    • Allow dynamic content such as database content
    • Are translated in Java code
      • Static code is translated as prints to the output
      • Dynamic code is translated as Java code
    • The code is compiled into Servlets
    • When a reference is made to a JSP the servlet is run

An example of a JavaServer Page is given below.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Insert title here</title>
</head>
<body>
  This is the testing page.
  <% int a, b;
     a = 5;
     b = a + 6;
  %>
  <br/>
  The integer was <%=b%>
</body>
</html>

JNDI and DataSources

The Java Naming and Directory Interface (JNDI)

  • Is an API that provides naming and directory services to Java programs
  • Tomcat provides JNDI services for use by the developer
  • Context.xml and web.xml are used to configure JNDI resources for use in Tomcat
Hands on Exercise
Install MySQL
Create a Tomcat JNDI DataSource for MySQL
Create a Tomcat Servlet that uses the JNDI DataSource


References
CodeJava Example of JNDI Datasource in Tomcat
JournalDev Example of Tomcat Datasource JNDI
Tomcat JNDI Resource How-To
Tomcat JNDI Datasource How-To
Oracle JNDI Trail

Understanding the Testing Environment

Types of Testing

  • Performance Testing
    • Identify performance bottlenecks
    • Determine throughput
    • Determine performance for various system and server configurations
  • System Testing
    • Does system meet original requirement specifications
    • Testing is only as good as the test plan
      • If requirements are not complete then tests may fail to catch all bugs
      • Set up tests to test JIRA reported bugs
  • Regression Testing
    • rerun sets of standard testing scripts
    • determine if system still functions to meet requirements when new versions are to be released
  • White Box and Black Box testing
    • White Box - find out about the internal structures of the software
      • For Example database connections, queries, and inserts should be tested.
      • Connections to other systems should be tested.
      • Complex algorithms should be tested
    • Black box - ignore the internals and just act like a user
      • What do users do with the system?
      • What types of errors can they make as the use the system?
      • Any Ecommerce that can go wrong, multiple clicks on the buy button?
  • Testers built test plans and scripts
    • Close cooperation with developers is needed
    • Testers must ask questions
      • Are there hidden requirements?
      • Show us what is supposed to be happening with the system?
      • What happens if bad input is put into the system?
      • Can we break the system?
References:
Wikipedia on Test Plans
Wikipedia on Software Testing
Software Testing Fundamentals

Install JMeter

Hands on Exercise
Installing JMeter with a Short Discussion of JMeter

Tools for Viewing Web Application Performance

  • JConsole
  • Google Tools
  • VisualVM
  • PSI Probe

Build a Test using JMeter

To understand the elements of JMeter test plans it is easiest to build a test plan.

A test plan will consist of

  • Thread Groups
  • Samplers
  • Logic Controllers
  • Listeners
  • Assertions
  • Configuration elements (when needed).
Hands on Exercise - Step 1:
Build a test plan using the elements in the JMeter Elements sections below.
First create a new test plan so that elements can be added

JMeter Elements

Reference:
Elements of a Test Plan, JMeter Manual
In General test plans consist of
  • Thread Groups
  • Logical Controllers - control the flow of the test
  • Samplers - send requests and receive responses
  • Other elements like Assertions, Timers, Pre Processors, etc.

Test Plan

The elements of the test plan will be added under this item in the left portion of the window
Test Plan Elements
  • Threads - each thread simulates a single user hitting the web server.
  • Note that the actual plan is built under a Thread Group
  • Thread Groups are under the Threads menu item
  • Test Fragment - A special type of controller.
  • You can build a test fragment from other elements under this element
  • It can be included in the test plan in multiple places
  • An Include Controller is used to include it
  • Config Element - Various configuration elements are here
  • For example the HTTP Request Default element which defines the default host and port etc.
  • when placed at the same level as the Thread Group they become global configurations
  • Timer - various types of timers that can be used to time the test plan
  • Generally JMeter send requests with no pauses between requests
  • This does not correspond to the way systems are used by users
  • Pre Processors - Executes an action prior to a request (Samplers are discussed below)
    • For example setting parameters for a request
    • There are scoping rules that apply to Pre Processors
  • Post-Processors - Executes an action after a request
  • usually it processes the response data
  • There are scoping rules that apply to Post-Processors
  • Assertions - Used to test the responses
  • Was the response correct
  • If not fail the response
  • Generally added as the child of a Sampler (Discussed below)
  • Listeners - provide access to the information JMeter gathers during the test


Hands on Exercise - Step 2:
Add a Thread Group to your Test Plan

Thread Group

Thread Group Elements
  • Logic Controller - these control the flow of the test plan
  • Config Element - the came configuration elements as above
  • apply these to Thread Group Elements by placing them as sub-elements in the test plan
  • Note that both order of the test plan and where sub-elements are placed are important
  • Timer - Same timers as above but these are timers used within the flow of the plan
  • Pre Processors - usually attached as children of Samplers
  • processed before their parent elements
  • Samplers - make requests and get responses from the system
  • For example the HTTP Request sampler requests a web page
  • the same thing as clicking on a link in a web page
  • Post Processors
  • Usually attached as children of Samplers
  • process the response to a request by the sampler
  • Assertions - Used to test the responses
  • Was the response correct
  • If not fail the response
  • Generally added as the child of a Sampler
  • Listeners - provide access to the information JMeter gathers during the test
Hands on Exercise - Step 3:
Add a View Results Tree Listener to the Thread Group
This will allow the viewing of the results of the test plan once we add other elements



Samplers

Sampler Elements
  • FTP Request - send request to retrieve a file or upload a file to an FTP server
References from search engine - JMeter FTP request tutorial
Tutorialspoint JMeter FTP Test Plan
Apache JMeter Manual FTP Test Plan
  • HTTP Request - send an HTTP/HTTPS request to a web server
  • This is commonly used to test web server pages
References from search engine - JMeter HTTP Request Tutorial
Apache JMeter Manual Web Test Plan
Tutorialspoint JMeter Web Test Plan
YouTube video on HTTP Request and FTP Request
Hands on Exercise - Step 4:
Add a HTTP Request Sampler to your Thread Group.
Use a URL that hits the Tomcat test server that has been set up in prior steps
  • JDBC Request - send a JDBC request to a database
  • This sampler would directly exercise a database using JDBC
  • Another way to do this is by sampling an HTML page that is built from a database
  • Debug Sampler - The Debug Sampler generates a sample containing the values of all JMeter variables and/or properties.
  • Can be used to send all of the variables and their values to a View Results Tree
  • Beanshell Sampler - very powerful script driven sampler
  • Can be programmed to do tasks
  • Programming is done in the Bean Shell script
References
Beanshell Website
Beanshell Manual
  • JSR223 Sampler - very powerful script driven sampler (fast)
  • JMeterVariables (vars) and JMeterProperties (props) see the JavaDocs
References from search engine - JSR223 vs Beanshell
Variables Available in Scripts
JMeter JavaDocs
Beanshell vs JSR223 Sampler with Groovy
Groovy Beginners Tutorial


  • Java Request - exercise a Java class
  • the class would have to implement the correct interface
  • Samplers that are not used as often
  • SOAP/XML-RPC Request - sample a SOAP service
  • LDAP Request - sample an LDAP service
  • SMTP Request - send an email through an SMTP server
  • Mail Reader Sampler - read an email from a POP or IMAP server
  • JMS Publisher, Subscriber, Point to Point
  • Most of the other samplers i.e. BSF, TCP, JUnit, OS Process, etc.
Reference - JMeter Samplers
Apache JMeter Manual - Samplers

Logical Controllers

  • Control the flow of the test
  • Similar to logic within a programming language
  • The order of the test plan determines how elements are executed
  • Top element is first then on down through the test plan
  • Controllers can cause loops and conditional execution of elements
  • For example if, foreach, loop, random, etc.
Logical Controllers
  • ForEach Controller - loops over a set of values in a variable
  • For Example a Regular Expression Extractor can be used in an HTTP Request to get the values from a page into a variable
  • While Controller - allows the setting of a condition that will stop the loop
Hands on Exercise - Step 6:
Create a while controller that will stop when an index gets to 20
Use a Counter to index the loop
  • If Controller - conditionally execute steps
  • Usually uses a JMeter function or variable in the condition
  • JMeter has a set of standard functions (JMeter User Manual)
  • variables can be set using
  • Regular Expression Extractor as a child of a prior Sampler
  • CSS/JQuery Extractor as a child of a prior Sampler
Hands on Exercise - Step 7:
Create a If Controller that
Is a child of the While Controller
Calls one URL if a counter is below 10
Calls another URL is counter is over 10
  • Include Controller - include another test plan from a file into this test plan
  • Usually the other test plan would not have its own thread group.
  • Interleave Controller - The thread group does the looping if any is done
  • Child elements are interleaved with each loop by the thread group
  • Loop Controller - loop a specific number of times over the children of the controller
  • Module Controller - includes a Test Fragment into the test plan
  • The Test Fragment is defined within the Test Plan
  • It is defined outside the Thread Group
  • Once only Controller - executes its children once only during a test.
  • If placed under another looping controller it executed only once per test
  • Random Controller - similar to interleaving but does it randomly
  • Random Order Controller - randomizes the execution of its children
  • Recording Controller - Used to record a series of actions taken in a browser (see section Build a Test Using a Recorder)
  • Runtime Controller - controls how long the children are allowed to run (i.e. 1 second)
  • Simple Controller - used to group children that belong together
  • Provides no functionality other than a place holder for grouping
  • Switch Controller - acts like a switch statement
  • Throughput Controller - controls the number or percentages of times its children are executed.
  • Transaction Controller - generates an additional sample telling how long it takes to execute its child elements



Assertions

  • Used to perform checks on Samplers
  • Test can be failed when assertion fails
Assertions
References from search engine - JMeter Assertions
BlazeMeter on Assertions
Apache JMeter Manual on Assertions
  • Bean Shell Assertion - use the Beanshell to create the assertion code
  • BSF Assertion - kind of outdated by Beanshell and JSR223 assertions
  • Compare Assertion - do two samplers give the same response or response time, for example from two servers
  • Duration Assertion - How long did the request and response take
  • HTML Assertion - is the response well formed HTML
  • JSR223 Assertion - Used when the assertion requires programming
  • For example extraction of data from the response
  • MD5Hex Assertion - does the response match a MD5 hex hash
  • Response Assertion - match patterns in the response
Hands on Exercise - Step 8:
Add a Response Assertion to the test and test for specific phrases that are expected in the response from the sampler
  • Size Assertion - what is the size of the response
  • SMIME Assertion - deals with email responses
  • XML Assertion - is the response well formed xml
  • XML Schema Assertion - does the response match a specific schema
  • XPath Assertion
References:
BlazeMeter on Assertions

Timers

  • Timers apply to all Samplers in their scope
  • Timers at a level apply to all Samplers (and their Sampler children) at that level
  • If a timer is to apply to a specific Sampler it must be a child of that Sampler
Timer Elements
BeanShell Timer - use Beanshell scripting to code a timer
BSF Timer - use BSF scripting to code a timer
Constant Throughput Timer - random timing, throughput for all samplers in total kept at a specified value
Constant Timer - pause for the same amount of time between requests (Samplers)
Hands on Exercise - Step 9:
Add one or more Constant timers to the test
Determine how the placement of the timer effects the test, in other words determine how scope matters.
Gaussian Timer - the variation around constant offset has a Gaussian curve distribution
JSR223 Timer - use a JSR223 scripting language to code a timer
Poisson Random Timer - pause each thread request for a random amount of time, with most of the time intervals occurring near a particular value
Synchronizing Timer - bottleneck several threads then release them all at once
Uniform Random Timer - pauses for a random amount of time
The maximum time is specified
An offset is specified
To get 20 to 100 milliseconds have max of 80, offset of 20
Values are then generated randomly from 20 to 80



Listeners

  • Most of the listeners perform several roles in addition to "listening" to the test results.
  • They also provide means to view, save, and read saved test results.
  • Note that Listeners are processed at the end of the scope in which they are found.
  • It is easiest to understand the various Listeners by trying them
Listener Elements
  • Aggregate Graph - Graph showing various time and throughput data
  • Aggregate Report - table row for each request giving various time and throughput data
  • Assertion Results - shows labels of all assertions executed and results of any failures
  • Beanshell Listener - use Beanshell scripting to create a listener
  • BSF Listener - use BSF scripting to create a listener
  • Comparison Assertion Visualizer - shows results of Compare Assertions
  • Distribution Graph - shows graph of response times
  • Generate Summary Results - shows results as the test is running to the log and standard output (console)
  • Graph Results - graph of sample times
  • JSR223 Listener - use JSR223 scripting to create a listener
  • Mailer Visualizer - sends email with success and failure data
  • Monitor Results - can monitor servers
  • Response Time Graph - Graph of response times
  • Save Responses to a File - saves responses for samplers in its scope to a file
  • Simple Data Writer - records data to a file, faster than the GUI Listeners
  • Spline Visualizer - graph of sample times using splines
  • Summary Report - similar to an Aggregate Report
  • View Results in Table - shows various data in table format such as sample name, size, start time, etc.
  • View Results Tree - shows tree (parent child) of results
Hands on Exercise - Step 9:
A View Results Tree was added in a prior step. Try some of the other Listeners to see how they work.

User Defined Variables

  • Defined in the User Defined Variable configuration element
  • Values are static during test execution (cannot be changed)

Blazemeter on User Defined Variables

Variables and Functions

  • JMeter has built in functions that can be used in scripts (for example in JSR223 Samplers)
  • JMeter has the ability to save and use variables and properties
  • JMeter variables have thread scope
  • JMeter properties are shared between all thread
  • Functions available in scripts
  • Variables available in scripts, for example in the JSR223 Sampler
  • Variables passed to scripts by JMeter automatically
vars - see class JMeterVariables
ctx - see class JMeterContext
props - see class JMeterProperty
SampleResult - see class SampleResult
sampler - for a pre-processor or post-processor gives access to the sampler that is its parent.
log - the Logger
Label - the sampler label
filename - the file name if any
Parameters - text from the Parameters field
args[] - the parameters split into a String array
OUT - System.out i.e. System.out.println
  • Variables that can be built on the fly by the elements (i.e. JSR223 Samplers)
vars.put("somename", "someString"), vars.get("somename")
vars.putObject("somename", someObject), (cast to correct type)vars.getObject("somename")
  • Properties (class java.util.Properties)
  • properties that can be built on the fly by the elements(i.e. JSR223 Samplers)
  • props.setProperty("somename", "someString")
  • __setProperty("name", "value")
  • String value = props.getProperty("somename")
  • String value = __property("somename")
References
Apache user manual on Functions and Variables
JMeter JavaDocs see JMeterVariables and JMeterProperty (vars)
JMeter Complete Element Reference

Configuration Element

  • HTTP Defaults
  • HTTP Cookie Manager
  • JDBC Connection Configuration

Workbench

  • The workbench is a place where elements of the test plan can be temporarily stored while not in use
  • certain test elements are only available on it
  • HTTP(S) Test Script Recorder
  • HTTP Mirror Server
  • Property Display



Build a Test using a Recorder

  • JMeter Test Script Recorder
    • Creates a Proxy in JMeter
      • Proxy lets JMeter listen for incoming requests from a Browser
    • Browser must be set up to use a proxy localhost:7000 for example
    • Once JMeter and Browser are set up correctly
      • Actions taken in the browser are recorded by JMeter
    • Allows a simple test plan to be recorded
      • This can then be made more complex


Hands on Exercise - Use a Recorder to Build a Test Plan
Using the following document set up the recorder in JMeter and install a Foxyproxy add-on in Chrome, Firefox, or IE to allow proxy definition. After setting up JMeter and the Browser explore the various options in the Test Script Recorder to see the recording variations. Take the recorded requests and build them into a test plan that uses View Results Tree and Graph results listeners.
Note: It is important to make sure that your web browser has not cached the pages you are going to visit. If they are cached then the cache copy will be used and there will not be a request going through the JMeter proxy. This will cause the page request to not be recorded by JMeter (the cached copy will be used instead). Go into your browser's options or settings and clear the cache.

Using a Proxy with a Proxy If you already have a company proxy and need to use JMeter as the proxy for recording see this article

Proxy with a Proxy 1
Proxy with a Proxy 2

Recording How To

JMeter Recorder Example
References:
Foxyproxy add-on for Firefox, Chrome, IE
Google Chrome Blazemeter
Regular Expression Quick Reference
Reqular Expression Tutorial

Load Test Mobile Apps

  • The basic steps are:
Record a Mobile Device using JMeter as the proxy as per the discussion in the previous section
Note that the mobile device and computer running JMeter have to be on the same subnet
The mobile device should not be on Cellular Data it should be on Wireless so it is on the network
Change the recording into a test plan
Set the bandwidth for the test using the article in the references
Run the test plan, most likely in a master slave distributed environment
Note the device designation in the Header Managers
References
Blazemeter on Mobile Testing
Simulate Bandwidth on JMeter

Build a Test for a Form

  • HTML Form parameters can be simulated by JMeter
    • Using a HTTP Request Sampler
      • Host and port are given by the server location, i.e. localhost and 8080
      • Path reference is the HTML Form action parameter
  • The results can be checked using an Assertion
    • Most likely a Response Assertion
    • A JSR223 Assertion could also be used
      • JSR223 requires programming of the assertion code
      • Assertion failure use AssertionResult.setFailure(true);
      • Assertion success use AssertionResult.setFailure(false);

Login in a Test

  • To test a login the following must be known
  • Is the site using cookies to determine the user and whether they have logged in
  • Is it a special cookie or one such as JSESSIONID that is keeping track of the session
  • What is Session on a web server?
References
Blazemeter on Login Techniques
Apache JMeter Manual on Web Test Plan
  • What is the URL of the page that will receive the login request
  • The HTML form's action URL
  • Not the URL of the page that has the input form (that shows the username and password textboxes)
  • What are the names of the input textboxes for username and password
  • These will go into the parameters of the HTTP Request along with their values


Hands on Exercise - Test a Login Page:

Part 1
  • Find the names of the input textboxes and the form action for a login page on the web
Use a page that you are aware of such as Amazon.com or a page used by your company or organization
Part 2
  • Look over the Java Server Pages userForm.jsp, actionPage.jsp, and anotherPage.jsp in Eclipse
They are under WebContent in the web project
  • Determine how the login will work.
  • Build a test plan that uses the Cookie Manager, and HTTP Request Defaults configurations along with a Thread Group, HTTP Requests, Assertions, and Listeners to test the login
  • Export a WAR file to your Tomcat webapps folder
  • Start Tomcat using startup.bat
  • Test the login page with JMeter and see if you go correctly to the "anotherPage.jsp
  • Look at the cookies in the Cookie Manager to see how the login works with Cookies.

Build a ForEach Loop

  • This uses a ForEach Controller
References
Hands on Exercise:
  • Using the first 7 lessons in the Regular Expression Interactive Tutorial (above) determine what strings match expression
<a href="([^"]+)"
Hands on Exercise
Add a ForEach Controller to your test plan using a Module Controller and a Test Fragment.
Use the example at link ForEachTestPlan
Right click on the link and save it into an examples folder
Start a second JMeter and use it to open and copy the elements needed
Create a Test Fragment and paste the copied elements into it
Create an Module Controller under the Thread Group

Using JSR223 and Java

  • JSR223 defines an interface between Java and Scripting Languages
  • It is a part of the Java Language
  • It allows JMeter which is written in Java to work with Scripting Languages
  • JSR223 can be used with Samplers, Pre-Processors, and Post-Processors
  • It also allows these to work with Java code
Hands On Exercise
  • Retrieve the zip file at the end of this document and save it
  • Extract the contents into the JMeter folder (from the installation of JMeter)
  • Open JMeter
  • From JMeter open the test plan "Everything and More.jmx"
  • Look over and experiment with the JSR223 samplers present in that example
References
JavaWorld Article on Scripting
JMeter Manual on JSR223 Samplers

JSR223 Get Sampler Response

  • JSR223 Can provide a more complex anaylsis of responses
    • To check certain elements such as links
    • To check for attributes or tokens on URLs
    • To parse for various embedded resources
    • To save all or part of the response to a file
  • How to get the response using scripting components such as Beanshell or JSR223
    • Which ones have this access to the sampler's response (SampleResult)?
      • They would need to be children of the sampler
      • Look at Post-Processors, Pre-Processors or Assertions
      • Assertions have access to SampleResult
      • Pre-Processors do not have access they occur before the response happens
      • Post-Processors do not have access to SampleResult
  • Get the SampleResult using a JSR223 assertion
    • The assertion is a child of the sampler
    • SampleResult is available as an implicit variable
      • It is available to the assertion code that the user writes

An Example where the SampleResult is printed to the console

//print out the Sampler's Response and set the Assertion Result failure to false
String response = SampleResult.getResponseDataAsString();
System.out.println("**********************************************The response data was");
System.out.println(response);
System.out.println("**********************************************The response data end");
AssertionResult.setFailure(false);
Hands on Exercise
  • Start a new test plan
  • Put in a Thread Group
  • Put in an HTTP Request Sampler
  • Put a JSR223 Assertion as the sampler child
  • Set it to language Java
  • Use import statements to import a FileWriter
  • Get the SampleResult
  • Print it to a file

Set up Eclipse for JSR223 Scripts

  • Writing a script within JMeter is hard
    • In a JSR223 Assertion using the text editor
    • There are no context drop downs or error checking
    • It would be better to write them in Eclipse and copy to JMeter

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx continue this and show how to set up in Eclipse with the JARS etc.

Identify Individual JMeter Threads

  • Threadgroup number of threads
  • Allows multiple JVM threads to be started
  • How to identify each individual thread
  • For example so that individual files can be written for each thread
  • Perhaps using a JSR223 sampler
  • Since the threads are running in the JVM the java Thread class can be used
    • For example code in a JSR223 Sampler or Post-Processor might be:
Thread thread = Thread.currentThread();
//Debug using out.println
System.out.println("Runnable Job is being run by " + thread.getName() + " (" + thread.getId() + ")");
Long threadNum = thread.getId();
vars.putObject("threadNum", threadNum);
  • Threads are scheduled
  • placed on the running queue in the scheduler
  • JMeter timers cause interrupts to threads
  • placed on the waiting queue
  • This can be seen with a test plan that incorporates a Uniform Random Timer
  • with an HTTP Request with a JSR223 Post-Processor
  • the Post-Processor has the code given above
  • The results printed in the console will interleave printlns from the various threads

Build a While Loop

  • This uses a While Controller
  • While Controller stops on condition being the String "false"
  • Something has to set a Variable (one way to control the looping) to the String "false"
  • For example JSR223 Samplers could be used
  • The code using Strings would be similar to
Note the System.out.println statements that can be used for debugging
   String theIndex = vars.get("index"); //gets value from JMeterVariables see Javadocs
   int newCount = Integer.parseInt(theIndex) + 1;
   System.out.println("************** newCount is " + newCount); //writes to the console
   String count = "" + newCount;
   vars.put("index", count); //puts value into JMeterVariables see Javadocs
   if (newCount > 3) {
      vars.put("continue", "false"); // stops the while loop
   }
  • The code using Strings and Integers would be similar to
   Integer theCounter = (Integer)vars.getObject("counter");
   System.out.println("\n****************** theCounter is " + theCounter);
   theCounter = theCounter + 1;
   System.out.println("****************** new theCounter is " + theCounter + "\n");
   vars.putObject("counter", theCounter);
   if (theCounter > 3) {
      vars.put("continue", "false");
   }

Build Test Fragments

  • Using the Module Controller
  • Test fragments can be put into a Test Plan outside the Thread Group
  • placed at locations in the test plan using the module controller
  • Using the include controller
  • Build a test fragment in a test plan
  • Save the test plan
  • Include the fragment in another test plan using the include controller

Debugging Test Plans

  • Debug Sampler - in user manual under miscellaneous components
  • System.out.println to console from JSR223 (Sampler, Pre-Processor, or Post-Processor)
  • Assertion Results - Listener
Will show errors in the Assertions
  • Error Messages in View Results Tree
The element name in the left column turns red when there is an error
  • Stacktraces in Console
  • Stacktraces in log
Errors can cause stacktraces which show up in the console

Connecting to a Database

  • Testing a Database using JDBC
  • Using SQL statements
  • Elements needed are
  • Thread Group
  • JDBC Connection Configuration
  • JDBC Request Sampler
  • Other elements as needed, i.e. Listeners, assertions
  • Questions to ask
  • Is it more relevant to test the web pages that are populated by the database than the database itself?
  • Is the database behind a firewall that will prevent connection?
Hands on Exercise
  • Create a JDBC test plan
  • user the following elements (at a minimum)
Thread Group
JDBC request
Summary Results
View Results Tree
  • Use the MySQL database that has been installed as the database to hit
Use the usersdb database and test the users table
Use a select statement - select * from users

The Build Database Test Plan section of the JMeter User's Manual give very good directions. It is listed below in the references

References
JMeter Manual - Build Database Test Plan

HTTP Cookie Manager

  • A configuration element
  • Stores any cookies sent by the website
  • Sends them back in any request made to the website
  • Cookies being managed can be seen in the View Results Tree listener
References:
[http://blazemeter.com/blog/using-http-cookie-manager-jmeter-not-cookie-jar Blazemeter on Cookie Manager

Access Log Sampler with Writing of a jmx File (A Hard Example to Work on Together)

  • The Access Log Sampler will read a tomcat access log and request all of the URLs in the log
  • Gives a more realistic test plan that follows what users do with the website.
  • However it cannot write the HTTP Request Samplers that could be included in a test plan
Hands on Exercise
Using an Access Log Sampler with a JSR223 Post Processor write a test plan that will read the access log and create a snippet of xml that can be included in another test plan using an Include Controller.
Step 1 get a test plan running that uses a Access Log Sampler with a View Results tree and a child Simple Data Writer Listener
Step 2 Determine the format of a jmx file for an HTTP Request so that we can write one of these
Step 3 Create a JSR223 child of the Access Log Sampler
Step 4 Figure out the java code that will get the path from the sampler variable, open a file, and write xml similar to the jmx sample for an HTTP Request sampler.
Note that most groups doing this exercise counted the number of lines in the access log
Then got to a while loop controlled by the number of lines in the file
where the Access Log Sampler did its work

Distributed Test using Multiple Clients to hit Server

  • JMeter can have a Master the controls multiple slaves
  • Useful in stress testing so that the local network or laptop is not overloaded
  • A laptop can simulate about 300 to 600 users before becoming overloaded
  • better to use the laptop to control multiple other machines
  • A stress test may want to simulate 1000s of users hitting the web server at the same time
  • There must be a way of determining the server performance during the test
  • For example JConsole or VisualVM (jvisualvm.exe on Windows)
  • Is there a firewall?
  • Both tools create Random RMI ports and therefore have a hard time with internal firewalls
References
JMeter Distributed Step by Step

JMeter Plugins

  • There are sets of plugins for JMeter.
  • give new elements of the various types such as Assertions and Listeners
  • Can integrate JMeter with tools such as Selenium/WebDriver
  • Those from JMeter-plugins.org are
References
JMeter Plugins from JMeter-plugins.org

Functional Testing

  • Testing that the systems meets the requirements
  • Does the system behave as it should
  • Act like a user even making errors
  • Black box and white box
  • Black box - act as thought system internals are unknown, i.e. HTML Request where response is built from database
  • White box - system internals are known, i.e. test a complex algorithm
References
Functional Testing with JMeter
Functional Testing with JMeter
Automated Functional Testing with Jmeter
TutorialsPoint on Functional Testing

Regression Testing

  • Determine whether the system still meets requirements after changes or bug fixes
  • Rerun tests that deal with parts of the system not included in the changes
References

Wikipedia on Regression Testing Whatis on Regression Testing

Stress Testing

  • Putting a server or the software under stress to see whether it behaves with a large number of users
  • Does the server get overloaded and response time suffers?
  • Does a database get overloaded and fail or response time suffers?
  • Does the software fail due to the load?
  • Does the web server fail due to the load?
  • Tools must be available to gauge the performance of the hardware and software


References
Wikipedia on Stress Testing Software
Wikipedia on Stress Testing

References

JMeter Example Files

The test plans below contain various types of debugging techniques, test plan elements, looping constructs, regular expressions, and other code that is somewhat hard to figure out when using JMeter test plans. They are examples to be discussed.

JMeter Test Plans

Sample code

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.8" jmeter="2.13 r1665067">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">1</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">1</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <longProp name="ThreadGroup.start_time">1447770674000</longProp>
        <longProp name="ThreadGroup.end_time">1447770674000</longProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </ThreadGroup>
      <hashTree>
        <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">localhost</stringProp>
          <stringProp name="HTTPSampler.port">8080</stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path"></stringProp>
          <stringProp name="HTTPSampler.concurrentPool">4</stringProp>
        </ConfigTestElement>
        <hashTree/>
        <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
          <collectionProp name="CookieManager.cookies"/>
          <boolProp name="CookieManager.clearEachIteration">false</boolProp>
        </CookieManager>
        <hashTree/>
        <UniformRandomTimer guiclass="UniformRandomTimerGui" testclass="UniformRandomTimer" testname="Uniform Random Timer" enabled="true">
          <stringProp name="ConstantTimer.delay">1000</stringProp>
          <stringProp name="RandomTimer.range">4000.0</stringProp>
        </UniformRandomTimer>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request Login" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain"></stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">Web_Project_1/userForm.jsp</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request action page" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments">
              <elementProp name="name" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">${name}</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">name</stringProp>
              </elementProp>
              <elementProp name="password" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">mypassword</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">password</stringProp>
              </elementProp>
            </collectionProp>
          </elementProp>
          <stringProp name="HTTPSampler.domain"></stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">Web_Project_1/actionPage.jsp</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request another page" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain"></stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">Web_Project_1/anotherPage.jsp</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>false</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <threadCounts>true</threadCounts>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="2.7" jmeter="2.12 r1636949">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">1</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">1</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <longProp name="ThreadGroup.start_time">1437060734000</longProp>
        <longProp name="ThreadGroup.end_time">1437060734000</longProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </ThreadGroup>
      <hashTree>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">localhost</stringProp>
          <stringProp name="HTTPSampler.port">8080</stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/Web_Project_1/userForm.jsp</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments">
              <elementProp name="name" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">Donald</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">name</stringProp>
              </elementProp>
              <elementProp name="password" elementType="HTTPArgument">
                <boolProp name="HTTPArgument.always_encode">false</boolProp>
                <stringProp name="Argument.value">mypassword</stringProp>
                <stringProp name="Argument.metadata">=</stringProp>
                <boolProp name="HTTPArgument.use_equals">true</boolProp>
                <stringProp name="Argument.name">password</stringProp>
              </elementProp>
            </collectionProp>
          </elementProp>
          <stringProp name="HTTPSampler.domain"></stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/Web_Project_1/actionPage.jsp</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain"></stringProp>
          <stringProp name="HTTPSampler.port"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/Web_Project_1/anotherPage.jsp</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <boolProp name="HTTPSampler.monitor">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
        </HTTPSamplerProxy>
        <hashTree/>
        <UniformRandomTimer guiclass="UniformRandomTimerGui" testclass="UniformRandomTimer" testname="Uniform Random Timer" enabled="true">
          <stringProp name="ConstantTimer.delay">2000</stringProp>
          <stringProp name="RandomTimer.range">3000</stringProp>
        </UniformRandomTimer>
        <hashTree/>
        <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>false</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <threadCounts>true</threadCounts>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
        <hashTree/>
        <ConfigTestElement guiclass="HttpDefaultsGui" testclass="ConfigTestElement" testname="HTTP Request Defaults" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">localhost</stringProp>
          <stringProp name="HTTPSampler.port">8080</stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path"></stringProp>
          <stringProp name="HTTPSampler.concurrentPool">4</stringProp>
        </ConfigTestElement>
        <hashTree/>
        <CookieManager guiclass="CookiePanel" testclass="CookieManager" testname="HTTP Cookie Manager" enabled="true">
          <collectionProp name="CookieManager.cookies"/>
          <boolProp name="CookieManager.clearEachIteration">false</boolProp>
        </CookieManager>
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>