qualersoft / jmeter-gradle-plugin

Gradle plugin for using JMeter
Apache License 2.0
12 stars 2 forks source link
gradle-plugin jmeter

= jmeter-gradle-plugin ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: :important-caption: :heavy_exclamation_mark: :caution-caption: :fire: :warning-caption: :warning: endif::[] ifndef::env-github[] :icons: font endif::[] :jm_base: https://jmeter.apache.org :jm_tm: {jm_base}/[JMeter(TM),window=_blank] :jm_doc_base: {jm_base}/usermanual :jm_remoteing: {jm_doc_base}/remote-test.html :jm_cli: {jm_doc_base}/get-started.html#override :gh_rp: https://github.com/qualersoft/jmeter-gradle-plugin :toc: preamble

[cols="1,~", frame=none, grid=none] |=== |General |image:https://img.shields.io/github/license/qualersoft/jmeter-gradle-plugin[link={gh_rp}/blob/main/LICENSE] image:https://app.fossa.com/api/projects/custom%2B17788%2Fgithub.com%2Fqualersoft%2Fjmeter-gradle-plugin.svg?type=shield[link=https://app.fossa.com/projects/custom%2B17788%2Fjmeter-gradle-plugin/refs/branch/main/]

|Main |image:{gh_rp}/actions/workflows/build.yml/badge.svg?branch=main[title="Build status", link={gh_rp}/blob/main/.github/workflows/build.yml] image:https://www.codefactor.io/repository/github/qualersoft/jmeter-gradle-plugin/badge/main[title="Code quality", link=https://www.codefactor.io/repository/github/qualersoft/jmeter-gradle-plugin/overview/main] image:https://codecov.io/gh/qualersoft/jmeter-gradle-plugin/branch/main/graph/badge.svg?token=Z5CT2C7LN1[title="Coverage", link=https://app.codecov.io/gh/qualersoft/jmeter-gradle-plugin/branch/main]

|Develop |image:{gh_rp}/actions/workflows/build.yml/badge.svg?branch=develop[title="Build status", link={gh_rp}/blob/develop/.github/workflows/build.yml] image:https://www.codefactor.io/repository/github/qualersoft/jmeter-gradle-plugin/badge/develop[title="Code quality", link=https://www.codefactor.io/repository/github/qualersoft/jmeter-gradle-plugin/overview/develop] image:https://codecov.io/gh/qualersoft/jmeter-gradle-plugin/branch/develop/graph/badge.svg?token=XT7QzRFkaj[title="Coverage", link=https://app.codecov.io/gh/qualersoft/jmeter-gradle-plugin/branch/develop] |===

Gradle plugin to integrate {jm_tm} tests into the gradle ecosystem. + This plugin arose from the need of a simple to start, but easy to customize plugin. The current available plugins are either hardwired to older {jm_tm} version or configuration is not so well documented.

== Usage === Applying the plugin .Kotlin DSL [%collapsible%open]

[source,kotlin]

plugins { id("de.qualersoft.jmeter") version "" }

====

.Groovy DSL [%collapsible]

[source,groovy]

plugins { id 'de.qualersoft.jmeter' version '' }

====

=== Customization The easiest way to customize the plugin is via its jmeter extension. + The extension offers the following properties [source,kotlin]

jmeter { systemPropertyFiles // <.> systemProperties // <.> mainPropertyFile // <.> additionalPropertyFiles // <.> jmeterProperties // <.> customReportTemplate // <.> globalPropertiesFile // <.> globalProperties // <.>

proxxScheme // <.> proxyHost // <.> proxyPort // <.> nonProxyHosts // <.>

logConfig // <.> logOutputFile // <.>

jmxRootDir // <.> resultDir // <.> reportDir // <.> maxHeap // <.> jvmArgs //<.>

enableRemoteExecution // <.> exitRemoteServers // <.> }

[%collapsible]

<.> Additional system property file(s). <.> Define additional system properties. <.> The jmeter property file to use. <.> Additional JMeter property file(s). <.> Define additional JMeter properties. <.> Path to a custom report-template folder used by report generator. <.> Path to a JMeter property file which will be sent to all servers. <.> Properties which will be sent to remote servers. <.> Scheme of the proxy (e.g. for non-http). <.> Proxy server hostname or ip address. <.> Proxy server port. <.> Non-proxy hosts (e.g *.apache.org). <.> Custom log configuration file (currently log4j2) + Defaults to bundled configuration. <.> File where jmeter log will be written to. + Defaults to /logs/jmeter.log <.> Used to search for jmx files. + Defaults to src/test/jmeter <.> Directory to which the jtl-files will be written. + Defaults to /test-results/jmeter <.> Root directory where to put the reports + Defaults to /reports/jmeter <.> [Optional] Specifies the maximum heap size the JVM process will start with. <.> [Optional] additional JVM arguments that will be passed to the jvm directly. <.> [Optional] tells {jm_tm} to run the tests on the configured remote-servers (see {jm_remoteing}[remoting]) + Defaults to false. <.> [Optional] Flag to exit remote servers at the end of the test. Only effective iff enableRemoteExecution is true. + Defaults to false.

These configurations will be applied to all tasks (where appropriate) and can be overridden or extended on a per task base.

== Quickstarter [IMPORTANT,title=Important] To use the quickstarter you must have gradle installed and available on your path

=== Running a jmeter-test

  1. In a folder of your choice (referred to as root), execute: + [source,shell script]

    root> gradle init --dsl kotlin --type basic

    This brings up the setup. We are going to create a basic project and using Kotlin as build script DSL.

  2. Create the following folder structure (gradle stuff from 1. left out) + [source]

    root ├── src │ └── test │ └── jmeter │ └── Test.jmx <.> └── build.gradle.kts <.>

    <1> default folder for jmx-files is `src/test/jmeter` + You can copy the `Test.jmx` from link:./src/functionalTest/resources[functional test resources] <2> build.gradle.kts is generated by gradle; we need it in next step.
  3. Put the following into build.gradle.kts + [source,kotlin]

    import de.qualersoft.jmeter.gradleplugin.task.* // <.>

plugins { id("de.qualersoft.jmeter") version "" // <.> }

repositories { mavenCentral() // <.> }

tasks { register("runJMeter") { // <.> jmxFile.set("Test.jmx") // <.> } }

<1> Import `task` package. (to save some typing later on 😋) <2> Apply the plugin. (Don't forget to correct the version 😉) <3> We need a repository to retrieve jmeter-library. `mavenCentral` should work in almost any case. <4> Register a run-task and give it a name (if we wouldn't had imported the `task` package in (1), we would have to use the full qualified path) <5> Configure the task to use our test.jmx file under `src/test/jmeter` 4. Run it by opening a cli of your choice in `root` + [source, shell script] ---- root> ./gradlew runJMeter ---- + [source, shell script,title=Output] ---- ... Starting standalone test @ Sat Sep 04 18:53:51 CEST 2021 (1630774431340) Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445 Warning: Nashorn engine is planned to be removed from a future JDK release summary = 30 in 00:00:03 = 10,0/s Avg: 206 Min: 108 Max: 345 Err: 2 (6,67%) Tidying up ... @ Sat Sep 04 18:53:55 CEST 2021 (1630774435185) ... end of run BUILD SUCCESSFUL in 15s 1 actionable task: 1 executed ---- 👏 Congratulations, you've run your first jmeter script with this plugin. + 🎉 4 steps, that's it. Simple, wasn't it? === Generating a report After you've run your first jmeter script successfully, you might want to have a report showing some nice charts and stats. No problem, just: 1. add the following to your `build.gradel.kts` s `task` section + [source,kotlin] ---- tasks { register("runJMeter") { jmxFile.set("Test.jmx") } register("jmeterReport") { // <.> jmxFile.set("Test.jmx") // <.> } } ---- <1> registering a `JMeterReportTask` task (remember the include? Now it pays off 😊) <2> by pointing it to our `jmx` file the plugin knows where to find everything 2. back in CLI run + [source, shell script] ---- root> ./gradlew jmeterReport ---- This generates the report under `build/reports/jmeter/Test` [NOTE,title=Note] The directory 'Test' is retrieved from the jmx-file's name. 🎉 Voila, just 2 steps to get a report. Remark that to generate a report, you have to execute the `runJMeter` task before. There are two ways you can get it in one rush. 1. Declare a `dependsOn` in report task + [source,kotlin] ---- register("jmeterReport") { jmxFile.set("Test.jmx") dependsOn("runJMeter") } ---- if you now execute `jmeterReport`, `runJMeter` get executed first if required 2. Or let the 'run' task always generate a report with `generateReport` flag + [source,kotlin] ---- register("runTest") { jmxFile.set("Test.jmx") generateReport = true } ---- [TIP,title=Tip] If you are going to rerun the task without cleaning outputs you will get an error because the report already exists. In such cases just enable the `deleteResults` property === Want to modify the jmx-Script with jmeter UI? No problem, just add the following task to your build-script [source,kotlin] ---- tasks { register("edit") { jmxFile.set("Test.jmx") } } ---- And back to CLI [source,shell script] ---- root> ./gradlew edit ---- As an alternative, if you don't want to clutter your tasks-section, you can use the `jmeter`-extension [source,kotlin] ---- jmeter { withGuiTask("edit") { jmxFile.set("Test.jmx") } } ---- == Cli arguments All tasks also provide some of their properties through cli-arguments. + To see what arguments are supported by a task simply run [source,shell script] ---- root> ./gradlew help --task <.> ---- <1> with being a JMeter*Task defined in your build script. E.g. our 'runTest' task from above. == Configure jmeter As mentioned in the preamble, this plugin is designed to be as flexible as possible. + By that, the used jmeter runner artifact as well as plugins or libraries aren't hardwired but can be configured. === Configure the runner You can easily configure not only the version but also its coordinates. All this can be done through the `jmeter.tool` property. [source,kotlin] ---- jmeter { tool { group // <.> name // <.> version // <.> mainConfigureClosure // <.> mainClass // <.> } } ---- [%collapsible] ==== <1> The group-id of the jmeter-runner. + Defaults to 'org.apache.jmeter'. <2> The name (artifact-id) of the jmeter-runner. + Defaults to 'ApacheJMeter'. <3> the version of the jmeter-runner. + Defaults to '5.5'. <4> A closure/lambda to configure the dependency any further. + Will only applied if not `null` (which is the default). <5> The main class used to execute the jmeter runner. + Defaults to 'org.apache.jmeter.NewDriver'. ==== === Adding plugins Because the runner itself is quite useless without any plugins you can add them with the `jmeterPlugin` dependency handler [source,kotlin] ---- dependencies { jmeterPlugin("org.jmeter:a-plugin:1.2.3") // <.> } ---- <1> Resolves the 'a-plugin' and puts its artifact into `/lib/ext`, transitive dependencies will be put to `lib` directory. [NOTE] ==== Please note the <> section. ==== By default, this plugin includes the following plugins (as they are also default plugins in a normal JMeter installation): ==== "bolt", "components", "core", "ftp", "functions", "http", "java", "jdbc", "jms", "junit", "ldap", "mail", "mongodb", "native", "tcp" ==== [%collapsible, title=Info] ==== At the current time, these plugins are hardwired and cannot be modified. + (Yeah, I know, so much about flexibility... Mea culpa! 😉) ==== === Adding support libraries Sometimes you have quite special and reusable code that you wouldn't maintain within JMeter. Or you just want to use an existing libraries functions within JMeter. + To make them available to JMeter you can use the `jmeterLibrary` dependency handler [source,kotlin] ---- dependencies { jmeterLibrary("org.apache.commons:commons-csv:1.9.0") // <.> } ---- <1> Resolves the 'commons-csv' artifact and puts its artifact, and all its transitive dependencies, under `/lib` directory. [NOTE] ==== Please note the <> section. ==== [CAUTION,title=Internal only] ==== Within an IDE with autocomplete, you may also notice the `jmeterRunner` dependency handler. This is for internal use only! Please use the respective `jmeter.tool` properties to configure the runner. ==== === Pitfalls when using jmeter-dependencies/-plugins Some of the jmeter dependencies or plugins, which you want to apply through `jmeterLibrary` or `jmeterPlugin` might depend on 'org.apache.jmeter:bom'. This dependency seems not available on any maven-repository (for further information refer to https://bz.apache.org/bugzilla/show_bug.cgi?id=64465[Issue 64465]). If you are affected by this issue, you will see an error message similar to ---- ... > Could not resolve all dependencies for configuration ':jmeterPlugin'. > Could not find org.apache.jmeter:bom:5.5. Required by: project > ... ---- when executing one of the jmeter-tasks. As a convenient workaround, the `jmeter-gradle-plugin` provides the `jmeter.tool.applyBomWorkaround` function. You can apply it to the affected dependencies like this: [source,kotlin] ---- dependencies { // in case a library is affected jmeterLibrary("org.apache.jmeter:a-library:1.2.3") { jmeter.tool.applyBomWorkaround(this) } // or in case a plugin is affected jmeterPlugin("org.jmeter:a-plugin:1.2.3") { jmeter.tool.applyBomWorkaround(this) } } ----