In this article, I will be focusing on configuring JMeter with Maven but lets first understand some basics of JMeter and Maven.
The Apache JMeter™ application is open source software, a 100% pure Java application designed to load test functional behavior and measure performance. These days, performance testing is very very important especially when the applications are targeting large number of users. There are many tools available in market, some are paid, some are free. Apache JMeter is one such free and open source software.
Though JMeter's was initially developed for load testing web applications, it is now far more advanced. The biggest advantage of the JMeter is that it can do many things like performance and functional testing for web services, databases, FTPs or Web Servers, LDAP, JMS, trigger emails/notifications. Most of these features are implemented with plugins.
JMeter is powerful, easy to install and use and FREE! It is a Java desktop application with simple user interface. You can always download stable version of JMeter here. You can download .tgz or .zip files to your desktop and extract it. You need appropriate Java version to run the software.
JMeter comes with a reporting module which shows how effective was the test. It can even generate simple but useful graphs.
Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information. It is a build automation tool used primarily for Java projects. There are three built-in build lifecycles: default, clean and site. The default lifecycle handles your project deployment, the clean lifecycle handles project cleaning, while the site lifecycle handles the creation of your project's site documentation. Each of these build lifecycles is defined by a different list of build phases, wherein a build phase represents a stage in the lifecycle. For example, the default lifecycle comprises of the following phases:
- validate - validate the project is correct and all necessary information is available
- compile - compile the source code of the project
- test - test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
- package - take the compiled code and package it in its distributable format, such as a JAR.
- verify - run any checks on results of integration tests to ensure quality criteria are met
- install - install the package into the local repository, for use as a dependency in other projects locally
- deploy - done in the build environment, copies the final package to the remote repository for sharing with other developers and projects.
Dynamic JMeter properties based on environment
Most of the times, we will see minumum DEV, STAGE and PROD environments. So, if we need to configure different properties for different environments dynamically, then we can create profiles to achive this. Here is the example:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<profiles> | |
<profile> | |
<id>Stage</id> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>com.lazerycode.jmeter</groupId> | |
<artifactId>jmeter-maven-plugin</artifactId> | |
<version>2.0.3</version> | |
<executions> | |
<execution> | |
<id>jmeter-tests</id> | |
<phase>verify</phase> | |
<goals> | |
<goal>jmeter</goal> | |
</goals> | |
</execution> | |
</executions> | |
<configuration> | |
<propertiesUser> | |
<host>stage.sample.com</host> | |
<!-- Use port 443 for https --> | |
<port>80</port> | |
<username>admin</username> | |
<password>password</password> | |
</propertiesUser> | |
<jmeterExtensions> | |
<artifact>kg.apc:jmeter-plugins:pom:1.4.0</artifact> | |
</jmeterExtensions> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
</profile> | |
</profiles> | |
Above example has sample stage profile. Lets say if we need to run JMeter tests against Stage environment, then we can use following command. Likewise, we can create multiple profiles and run JMeter tests against those profiles.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mvn clean -PStage verify | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<plugin> | |
<groupId>org.codehaus.gmaven</groupId> | |
<artifactId>groovy-maven-plugin</artifactId> | |
<executions> | |
<execution> | |
<id>decrypt-passwords</id> | |
<phase>verify</phase> | |
<goals> | |
<goal>execute</goal> | |
</goals> | |
<configuration> | |
<source> | |
import org.jasypt.properties.EncryptableProperties; | |
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; | |
username = "default"; | |
password = "default"; | |
if(properties["JMETER_ENCRYPTION_PASSWORD"] != null) { | |
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); | |
encryptor.setPassword(properties["JMETER_ENCRYPTION_PASSWORD"]); | |
Properties props = new EncryptableProperties((Properties)properties, encryptor); | |
props.propertyNames().each{ | |
if (it == 'encrypted.stage.username') { | |
username = props.getProperty(it); | |
} else if (it == 'encrypted.stage.password') { | |
password = props.getProperty(it); | |
} | |
} | |
} | |
project.properties["stage.username"] = username; | |
project.properties["stage.password"] = password; | |
</source> | |
</configuration> | |
</execution> | |
</executions> | |
<dependencies> | |
<dependency> | |
<groupId>org.jasypt</groupId> | |
<artifactId>jasypt</artifactId> | |
<version>1.9.2</version> | |
</dependency> | |
</dependencies> | |
</plugin> |
Now its time for reporting. Reporting is one of the most important thing after performance test. Apache JMeter has built-in reporting module. You can generate userful reports with some simple configurarations. First, we will modify our sample stage profile as below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<profiles> | |
<profile> | |
<id>Stage</id> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>com.lazerycode.jmeter</groupId> | |
<artifactId>jmeter-maven-plugin</artifactId> | |
<version>2.0.3</version> | |
<executions> | |
<execution> | |
<id>jmeter-tests</id> | |
<phase>verify</phase> | |
<goals> | |
<goal>jmeter</goal> | |
</goals> | |
</execution> | |
</executions> | |
<configuration> | |
<propertiesUser> | |
<host>stage.sample.com</host> | |
<!-- Use port 443 for https --> | |
<port>80</port> | |
<username>${stage.username}</username> | |
<password>${stage.password}</password> | |
<jmeter.save.saveservice.output_format>csv</jmeter.save.saveservice.output_format> | |
<jmeter.save.saveservice.bytes>true</jmeter.save.saveservice.bytes> | |
<jmeter.save.saveservice.print_field_names>true</jmeter.save.saveservice.print_field_names> | |
<jmeter.save.saveservice.label>true</jmeter.save.saveservice.label> | |
<jmeter.save.saveservice.latency>true</jmeter.save.saveservice.latency> | |
<jmeter.save.saveservice.response_code>true</jmeter.save.saveservice.response_code> | |
<jmeter.save.saveservice.response_message>true</jmeter.save.saveservice.response_message> | |
<jmeter.save.saveservice.successful>true</jmeter.save.saveservice.successful> | |
<jmeter.save.saveservice.thread_counts>true</jmeter.save.saveservice.thread_counts> | |
<jmeter.save.saveservice.thread_name>true</jmeter.save.saveservice.thread_name> | |
<jmeter.save.saveservice.time>true</jmeter.save.saveservice.time> | |
</propertiesUser> | |
<jmeterExtensions> | |
<artifact>kg.apc:jmeter-plugins:pom:1.4.0</artifact> | |
</jmeterExtensions> | |
<jmeterExtensions> | |
<artifact>kg.apc:jmeter-plugins-json:jar:2.3</artifact> | |
</jmeterExtensions> | |
<propertiesSystem> | |
<https.socket.protocols>TLSv1.2</https.socket.protocols> | |
</propertiesSystem> | |
<testResultsTimestamp>false</testResultsTimestamp> | |
<appendResultsTimestamp>false</appendResultsTimestamp> | |
</configuration> | |
</plugin> | |
</plugins> | |
</build> | |
</profile> | |
</profiles> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<plugin> | |
<artifactId>maven-antrun-plugin</artifactId> | |
<executions> | |
<execution> | |
<phase>verify</phase> | |
<configuration> | |
<tasks> | |
<mkdir dir="${basedir}/target/jmeter/results/dashboard" /> | |
<copy file="${basedir}/src/test/resources/reportgenerator.properties" | |
tofile="${basedir}/target/jmeter/bin/reportgenerator.properties" /> | |
<copy todir="${basedir}/target/jmeter/bin/report-template"> | |
<fileset dir="${basedir}/src/test/resources/report-template" /> | |
</copy> | |
<java jar="${basedir}/target/jmeter/bin/ApacheJMeter-3.0.jar" | |
fork="true"> | |
<arg value="-g" /> | |
<arg value="${basedir}/target/jmeter/results/<your_jmeter>.jtl" /> | |
<arg value="-o" /> | |
<arg value="${basedir}/target/jmeter/results/dashboard/" /> | |
</java> | |
</tasks> | |
</configuration> | |
<goals> | |
<goal>run</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>com.sample</groupId> | |
<artifactId>sample</artifactId> | |
<version>1.0.0-SNAPSHOT</version> | |
<properties> | |
<encrypted.stage.username>ENC(encrypted_username)</encrypted.stage.username> | |
<encrypted.stage.password>ENC(encrypted_password)</encrypted.stage.password> | |
</properties> | |
<profiles> | |
<profile> | |
<id>Stage</id> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.codehaus.gmaven</groupId> | |
<artifactId>groovy-maven-plugin</artifactId> | |
<executions> | |
<execution> | |
<id>decrypt-passwords</id> | |
<phase>verify</phase> | |
<goals> | |
<goal>execute</goal> | |
</goals> | |
<configuration> | |
<source> | |
import org.jasypt.properties.EncryptableProperties; | |
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; | |
username = "default"; | |
password = "default"; | |
if(properties["JMETER_ENCRYPTION_PASSWORD"] != null) { | |
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); | |
encryptor.setPassword(properties["JMETER_ENCRYPTION_PASSWORD"]); | |
Properties props = new EncryptableProperties((Properties)properties, encryptor); | |
props.propertyNames().each{ | |
if (it == 'encrypted.stage.username') { | |
username = props.getProperty(it); | |
} else if (it == 'encrypted.stage.password') { | |
password = props.getProperty(it); | |
} | |
} | |
} | |
project.properties["stage.username"] = username; | |
project.properties["stage.password"] = password; | |
</source> | |
</configuration> | |
</execution> | |
</executions> | |
<dependencies> | |
<dependency> | |
<groupId>org.jasypt</groupId> | |
<artifactId>jasypt</artifactId> | |
<version>1.9.2</version> | |
</dependency> | |
</dependencies> | |
</plugin> | |
<plugin> | |
<groupId>com.lazerycode.jmeter</groupId> | |
<artifactId>jmeter-maven-plugin</artifactId> | |
<version>2.0.3</version> | |
<executions> | |
<execution> | |
<id>jmeter-tests</id> | |
<phase>verify</phase> | |
<goals> | |
<goal>jmeter</goal> | |
</goals> | |
</execution> | |
</executions> | |
<configuration> | |
<propertiesUser> | |
<host>stage.sample.com</host> | |
<!-- Use port 443 for https --> | |
<port>80</port> | |
<username>${stage.username}</username> | |
<password>${stage.password}</password> | |
<jmeter.save.saveservice.output_format>csv</jmeter.save.saveservice.output_format> | |
<jmeter.save.saveservice.bytes>true</jmeter.save.saveservice.bytes> | |
<jmeter.save.saveservice.print_field_names>true</jmeter.save.saveservice.print_field_names> | |
<jmeter.save.saveservice.label>true</jmeter.save.saveservice.label> | |
<jmeter.save.saveservice.latency>true</jmeter.save.saveservice.latency> | |
<jmeter.save.saveservice.response_code>true</jmeter.save.saveservice.response_code> | |
<jmeter.save.saveservice.response_message>true</jmeter.save.saveservice.response_message> | |
<jmeter.save.saveservice.successful>true</jmeter.save.saveservice.successful> | |
<jmeter.save.saveservice.thread_counts>true</jmeter.save.saveservice.thread_counts> | |
<jmeter.save.saveservice.thread_name>true</jmeter.save.saveservice.thread_name> | |
<jmeter.save.saveservice.time>true</jmeter.save.saveservice.time> | |
</propertiesUser> | |
<jmeterExtensions> | |
<artifact>kg.apc:jmeter-plugins:pom:1.4.0</artifact> | |
</jmeterExtensions> | |
<jmeterExtensions> | |
<artifact>kg.apc:jmeter-plugins-json:jar:2.3</artifact> | |
</jmeterExtensions> | |
<propertiesSystem> | |
<https.socket.protocols>TLSv1.2</https.socket.protocols> | |
</propertiesSystem> | |
<testResultsTimestamp>false</testResultsTimestamp> | |
<appendResultsTimestamp>false</appendResultsTimestamp> | |
</configuration> | |
</plugin> | |
<plugin> | |
<artifactId>maven-antrun-plugin</artifactId> | |
<executions> | |
<execution> | |
<phase>verify</phase> | |
<configuration> | |
<tasks> | |
<mkdir dir="${basedir}/target/jmeter/results/dashboard" /> | |
<copy file="${basedir}/src/test/resources/reportgenerator.properties" | |
tofile="${basedir}/target/jmeter/bin/reportgenerator.properties" /> | |
<copy todir="${basedir}/target/jmeter/bin/report-template"> | |
<fileset dir="${basedir}/src/test/resources/report-template" /> | |
</copy> | |
<java jar="${basedir}/target/jmeter/bin/ApacheJMeter-3.0.jar" | |
fork="true"> | |
<arg value="-g" /> | |
<arg value="${basedir}/target/jmeter/results/<your_jmeter>.jtl" /> | |
<arg value="-o" /> | |
<arg value="${basedir}/target/jmeter/results/dashboard/" /> | |
</java> | |
</tasks> | |
</configuration> | |
<goals> | |
<goal>run</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
</plugins> | |
</build> | |
</profile> | |
</profiles> | |
</project> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mvn clean -PStage verify -DJMETER_ENCRYPTION_PASSWORD=password | |
P.S. Click here to access my other posts.
Comments
Post a Comment