Plugin Configuration in Cucumber JVM
What Is Plugin Configuration?
Plugin Configuration is the process of configuring Cucumber plugins that format console output, generate reports, save failed scenario references, or integrate Cucumber execution with reporting tools and CI/CD systems. Cucumber executes scenarios, gathers results, and passes those results to configured plugins. Each plugin processes the same execution data in a different format.
In simple terms, plugins tell Cucumber what extra output or reports to generate during or after test execution. Without plugins, a test run may show only basic console information. With plugins, teams can produce readable logs, HTML reports, JSON files, JUnit XML reports, rerun files, message streams, and timeline views.
Why Are Plugins Needed?
Automation execution without reporting has limited value. Developers need failure details. Testers need step-level results. QA leads need summaries. Managers need pass/fail visibility. CI/CD systems need machine-readable outputs. Plugins provide those outputs. They convert Cucumber execution events into artifacts people and tools can use.
A simple console line saying that a scenario failed is not enough for a professional framework. The team needs to know which feature failed, which scenario failed, which step failed, what the error was, how long execution took, and where evidence such as screenshots or logs can be found. Plugin configuration is the foundation for this reporting workflow.
Where Are Plugins Configured?
In JUnit 4 and TestNG projects, plugins are usually configured inside @CucumberOptions. Multiple plugins can be declared together.
@CucumberOptions(
plugin = {
"pretty",
"html:target/cucumber-report.html",
"json:target/cucumber.json",
"junit:target/cucumber.xml"
}
)
In JUnit 5 projects, plugin configuration is commonly handled through JUnit Platform configuration, junit-platform.properties, Maven or Gradle configuration, or system properties. The mechanism changes, but the purpose remains the same: define the output Cucumber should produce.
Execution Flow
During execution, Cucumber runs feature scenarios and emits events. Plugins listen to those events and generate output. One plugin may print readable console logs. Another may write an HTML report. Another may write JSON data. Another may write failed scenario references.
Runner
-> Execute Scenarios
-> Plugins Receive Results
-> Generate Reports
-> Store Output
-> CI/CD Publishes Reports
Multiple plugins can run in the same execution. They do not usually control test behavior. They consume execution results and create useful output. This difference matters: plugins are for reporting and output, while hooks are for setup, teardown, screenshots, cleanup, and scenario-level lifecycle actions.
Common Cucumber Plugins
| Plugin | Purpose |
|---|---|
pretty | Readable console output |
html | Browser-viewable HTML report |
json | JSON report for tools and dashboards |
junit | JUnit XML report for CI servers |
rerun | Stores failed scenario locations |
message | Cucumber Messages format for advanced integrations |
timeline | Timeline view in supported setups |
Pretty Plugin
The pretty plugin produces readable console output. It is useful during local execution because the console displays features, scenarios, steps, and statuses in a more understandable format. This is especially helpful when writing or debugging scenarios from an IDE or terminal.
plugin = "pretty"
The pretty plugin does not generate an external report file. It improves console readability. For file-based reports, use HTML, JSON, JUnit XML, or other report plugins.
HTML, JSON, and JUnit XML Plugins
The HTML plugin creates a browser-viewable report. It is useful for testers, developers, and leads who want to review scenario results after execution.
plugin = "html:target/cucumber-report.html"
The JSON plugin writes structured execution data that can be consumed by advanced reporting tools, custom dashboards, or integrations.
plugin = "json:target/cucumber.json"
The JUnit plugin writes XML in a format understood by Jenkins, GitHub Actions, Azure DevOps, Bamboo, TeamCity, and many other CI tools.
plugin = "junit:target/cucumber.xml"
Enterprise projects commonly generate HTML, JSON, and JUnit XML together because each output serves a different audience. HTML is for humans, JSON is for tools, and JUnit XML is for CI dashboards.
Rerun and Message Plugins
The rerun plugin writes failed scenario locations to a file. A failed file may contain entries such as features/login.feature:15. This file can later be used to rerun only failed scenarios.
plugin = "rerun:target/failed.txt"
Rerun is useful, but it should not hide flaky tests. If a scenario fails first and passes on rerun, the team should still investigate why. Rerun improves efficiency, not quality by itself.
The message plugin writes Cucumber Messages in NDJSON format. It is useful for advanced reporting, analytics, and integrations that consume Cucumber's event stream.
plugin = "message:target/messages.ndjson"
Output Locations
Generated reports should usually go inside the build output folder such as target for Maven or build for Gradle. This keeps generated artifacts separate from source code and makes cleanup easier.
target
cucumber-report.html
cucumber.json
cucumber.xml
failed.txt
messages.ndjson
Relative paths are better than absolute paths because they work across local machines, CI agents, and different operating systems. Avoid paths such as C:/Reports/report.html unless there is a very specific reason.
Plugin Configuration in CI/CD
CI/CD pipelines rely heavily on plugin outputs. Jenkins can publish HTML reports and read JUnit XML. GitHub Actions can upload artifacts. Azure DevOps can publish test results. Reporting tools can consume JSON. Good plugin configuration turns test execution into actionable feedback.
A typical CI flow is Git checkout, Maven or Gradle execution, Cucumber scenario execution, plugin report generation, artifact archiving, and result publication. If reports are not generated in predictable locations, CI publishing fails or becomes inconsistent. This is why report paths should be standardized across runners.
Plugin vs Hooks vs Logger
Plugins, hooks, and loggers have different responsibilities. Plugins generate reports and output from execution results. Hooks run setup and teardown logic around scenarios. Loggers record framework or application execution details. A screenshot on failure is often captured in a hook and attached to a report. A plugin then renders or stores the report data.
| Component | Responsibility |
|---|---|
| Plugin | Generate execution reports and output |
| Hook | Setup, teardown, cleanup, screenshot capture |
| Logger | Record technical runtime logs |
Common Mistakes
Common mistakes include writing reports outside the build output directory, using duplicate plugins, generating reports nobody reads, forgetting JSON when a reporting tool needs it, using absolute paths, and configuring different report paths across runners. Another mistake is expecting plugins to control execution logic. Plugins process results; they should not decide business flow.
Too many reports can also become a problem. Reports consume disk space and may slow execution. Generate the reports that provide real value. A practical enterprise baseline is pretty console output, HTML report, JSON report, and JUnit XML report.
Best Practices
Generate reports inside target or the equivalent build directory. Use pretty during development for readable console output. Generate HTML for human review, JSON for advanced tools, and JUnit XML for CI systems. Use the rerun plugin when rerunning failed scenarios is part of the workflow. Keep reporting configuration consistent across runner classes.
Review reports regularly. If a report is never opened or consumed, remove it. If a report is essential for debugging or CI publishing, protect its configuration and make sure the pipeline archives it. Reporting should help the team understand execution quality quickly.
Real-Time Enterprise Plugin Setup
A practical enterprise setup usually generates multiple outputs in one run. The pretty plugin helps local developers and testers read console execution. The HTML plugin gives a quick browser-viewable report. The JSON plugin feeds reporting tools such as advanced dashboards, custom parsers, or report aggregators. The JUnit XML plugin allows CI systems to show test results directly in the build interface. The rerun plugin stores failed scenario locations for focused reruns.
@CucumberOptions(
plugin = {
"pretty",
"html:target/cucumber-report.html",
"json:target/cucumber.json",
"junit:target/cucumber.xml",
"rerun:target/failed.txt"
}
)
This does not mean every project needs every plugin. A small learning project may need only pretty and HTML. A professional CI/CD project usually needs at least one human-readable report and one machine-readable report. The plugin list should match how results are consumed. If Jenkins publishes JUnit XML, keep the JUnit plugin. If a dashboard consumes JSON, keep the JSON plugin. If nobody uses a report, remove it.
Reporting Strategy for Failed Scenarios
Failed scenarios need enough evidence for quick diagnosis. Plugin reports show feature, scenario, step, status, and error details. Hooks can attach screenshots, logs, request payloads, response bodies, or browser state. The plugin then renders or stores that information depending on the report type. This is why hooks and plugins often work together even though they have different responsibilities.
A good failure report answers practical questions: Which scenario failed? Which step failed? What was the error? Which browser and environment were used? Was a screenshot captured? Was the failure repeated on rerun? How long did the scenario take? If reports do not answer these questions, the plugin setup or hook evidence strategy needs improvement.
Plugin Configuration Across Multiple Runners
Large frameworks often have smoke, regression, API, and UI runners. If each runner writes reports to the same file path, reports can overwrite each other. If each runner writes to completely random paths, CI publishing becomes complicated. The team should choose a naming convention. For example, smoke reports may go to target/smoke, regression reports to target/regression, and API reports to target/api.
Consistency matters more than cleverness. Build tools and CI jobs should know exactly where artifacts will be created. When reports are predictable, automation results become easier to publish, archive, compare, and share.
Troubleshooting Plugin Issues
If reports are not generated, check whether the runner being executed actually contains the plugin configuration. Then check the output path. Then check whether the build failed before Cucumber reached report generation. Also confirm that the target directory is writable in the local machine or CI agent. Permission and path problems are more common in pipelines than in local IDE runs.
If JSON reports are generated but a third-party report tool fails, inspect the JSON file path and Cucumber version compatibility. Reporting tools often expect a particular Cucumber JSON structure. If JUnit XML does not appear in CI, verify both the Cucumber plugin and the CI publishing configuration. Cucumber can generate the file correctly while Jenkins is looking in the wrong folder.
Interview-Ready Summary
Plugin Configuration determines what reports and output Cucumber generates during test execution. Common plugins include pretty, html, json, junit, rerun, and message. In JUnit 4 and TestNG projects, plugins are often configured through @CucumberOptions. In JUnit 5 projects, they are commonly configured through JUnit Platform or build-tool settings.
The golden rule is to use plugins for reporting and output, not for test logic. Generate only the artifacts your team and CI/CD system actually use, and keep report paths portable and consistent.