ScreenshotNeo

BlogGuides

What’s New in Cucumber JVM 6

Cucumber-JVM 6.0.0 adds Gherkin Rule support, new report formats and individual configuration properties, while changing default test outcomes and console output.

By the ScreenshotNeo team4 October 20268 min read

Cucumber-JVM v6.0.0 added support for Gherkin’s Rule keyword, introduced a message-based formatter, replaced the HTML formatter with a single-file report, removed cucumber.options, and changed default test outcomes and console output. When upgrading from v5, first move to v5.7.0 and remove deprecated features; then check undefined or pending steps, report configuration, and any Spring setup. This guide covers the v6.0.0 release specifically, not later Cucumber-JVM releases. See the official v6.0.0 release notes and the general Cucumber upgrading guide.

What changed in Cucumber-JVM 6.0.0

Area Before or prior behavior v6.0.0 change Upgrade action
Gherkin Rule was not supported by Cucumber-JVM Support for Rule, connecting feature files with example mapping Use Rule to group scenarios around a business rule where it clarifies the feature
Machine-readable reports JSON output had no schema, high memory use, and differences across implementations, according to the release notes A message-based formatter was added Try message: output and check whether report consumers can read it
HTML report Old formatter produced a collection of files Improved formatter emits one report file Use an output path ending in .html
Configuration cucumber.options combined command-line arguments in one property The property was removed in favor of individual properties Replace it with the appropriate separate properties for your runner and options
Spring Spring context could be configured through cucumber.xml or on step-definition classes Those setups are no longer supported Add a dedicated Cucumber context configuration class
Test outcome Pending and undefined steps could be tolerated under non-strict behavior Strict behavior is the default; pending and undefined steps fail the test or build Resolve them or exclude unfinished scenarios deliberately with tags
Console output JUnit and TestNG displayed progress and a summary by default These are no longer printed by default Add progress and/or summary plugins if the team relies on them

1. Use the Gherkin Rule keyword

Rule makes it possible to express a business rule as a named part of a feature and put the scenarios that illustrate it underneath. For example:

Feature: Account access

  Rule: Locked accounts cannot sign in

    Scenario: A locked account is rejected
      Given an account is locked
      When the user submits valid credentials
      Then access is denied

This changes feature-file organization and readability; it does not replace step definitions or make a scenario executable by itself. Adopt it where grouping examples under a rule helps readers understand the behavior. Existing features do not need to be rewritten merely to upgrade.

2. Add message output for report consumers

The v6 message formatter writes newline-delimited JSON messages (NDJSON). Each line represents a message in the test run stream. The release notes describe it as addressing limitations in the previous JSON formatter, including no schema, high memory use, and inconsistent output across Cucumber implementations. The notes said it was intended eventually to replace the existing JSON formatter; they did not say it had already replaced JSON in every use.

For a JUnit runner using @CucumberOptions, configure the plugin like this:

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(
    features = "src/test/resources/features",
    glue = "example.steps",
    plugin = {"message:target/cucumber-report.ndjson"}
)
public class RunCucumberTest {
}

This uses the runner annotation style shown in the v6-era release notes. Keep other runner configuration, such as your feature and glue paths, aligned with the integration already used by the project. The NDJSON file is machine-readable output, not an HTML report. Confirm downstream report tooling supports the message format before replacing a JSON input it currently consumes.

3. Update HTML report output paths

The improved HTML formatter writes the report as one file. Give the target an .html extension:

@CucumberOptions(
    plugin = {"html:target/cucumber-report.html"}
)

If the current configuration points to a directory or a path without the extension, update it to a filename such as target/cucumber-report.html. If you generate multiple formats, list each plugin using the syntax your runner supports.

4. Replace cucumber.options with individual properties

The combined property was removed. Its arguments could be interpreted by intermediate tools such as Maven or a CI server, making quoting and forwarding difficult. Move each setting to its own property instead of forwarding a single string.

The release notes illustrate individual properties for ANSI color output and tag filtering:

mvn clean test \
  -Dcucumber.ansi-colors.disabled=true \
  -Dcucumber.filter.tags="not @ignored"

Check the property names supported by the exact Cucumber-JVM runner and integration versions in your project. The release notes give these examples, but build integrations can differ in how they accept and pass properties. Do not assume every old command-line option has a direct property equivalent: verify each option and configure it through the runner’s supported mechanism.

5. Configure Cucumber Spring explicitly

Cucumber Spring’s preferred configuration became a dedicated class annotated with @CucumberContextConfiguration plus a Spring context annotation such as @ContextConfiguration or @SpringBootTest. The release notes say cucumber.xml and context configuration placed on step-definition classes are no longer supported.

A minimal shape for a Spring Boot suite is:

import cucumber.api.java.Before;
import cucumber.api.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;

@CucumberContextConfiguration
@SpringBootTest
public class CucumberSpringConfiguration {
}

For a non-Boot Spring test context, use @ContextConfiguration with the project’s configuration, for example:

import cucumber.api.spring.CucumberContextConfiguration;
import org.springframework.test.context.ContextConfiguration;

@CucumberContextConfiguration
@ContextConfiguration(classes = TestApplicationConfiguration.class)
public class CucumberSpringConfiguration {
}

Keep this configuration class in the glue package scanned by Cucumber. Remove the old cucumber.xml fallback and move Spring context annotations off step-definition classes. Imports can differ if the project uses a different Cucumber Spring package layout; match the v6 dependency artifacts actually in use.

6. Account for strict behavior and console output changes

In v6 strict behavior became the default. Undefined steps (no matching definition) and pending steps (deliberately unfinished definitions) cause test or build failure. This can expose work-in-progress scenarios that previously did not fail the build.

  • Implement missing steps where the scenario is expected to run.
  • For intentionally unfinished features, use tags to identify them and a tag filter to exclude them from the relevant run.
  • Keep a separate run or workflow for excluded work if the team needs visibility; otherwise an exclusion can hide unfinished coverage.

JUnit and TestNG also stopped printing the progress indicator and summary by default. Add the plugins back when that output is useful:

@CucumberOptions(
    plugin = {"progress", "summary", "html:target/cucumber-report.html"}
)

You can configure only the output you need. For example, a CI job may retain the summary while a local run uses progress output. Whether annotations or individual properties are most appropriate depends on the runner and build integration.

A practical v5 to v6.0.0 migration sequence

  1. Upgrade to v5.7.0 first. The v6.0.0 release notes recommend this intermediate step.
  2. Remove deprecated features while still on v5. Resolve deprecation warnings rather than carrying those usages across the major upgrade.
  3. Upgrade the Cucumber-JVM modules together. Keep the project’s Cucumber artifacts on a compatible v6.0.0 release line instead of mixing unrelated versions.
  4. Replace cucumber.options. Translate each setting to an individual supported property or runner configuration.
  5. Run the suite and inspect undefined or pending failures. Decide which should be implemented and which unfinished scenarios should be filtered deliberately.
  6. Fix report destinations. Add .html to HTML output paths and evaluate the message formatter with any report consumers.
  7. Review Spring glue configuration. Add the dedicated context configuration class and remove unsupported XML or step-definition class setup.
  8. Restore console plugins if needed. Configure progress and summary explicitly where users or CI logs rely on them.
  9. Check the full changelog and exact integrations. The release notes cover notable changes, not every change in the 6.x patch history.

Common upgrade problems

Symptom Likely cause What to do
Build starts failing on scenarios that used to pass Strict behavior now fails pending and undefined steps by default Implement the missing step, or tag and filter intentionally unfinished scenarios
No progress indicator or summary appears JUnit/TestNG no longer print them by default Add progress and/or summary to the plugin list
Old Maven/CI command no longer applies settings cucumber.options was removed or arguments were reinterpreted by an intermediate tool Use separate supported properties, and check shell/CI quoting for tag expressions
HTML report path is missing or output is unexpected Configuration still targets a directory or omits the extension Set a file path ending with .html
Machine report consumer rejects the new file NDJSON message output is not the same format as the consumer’s current JSON input Keep the existing format where required and migrate the consumer separately after verifying message support
Spring context fails to initialize Configuration is still in cucumber.xml, on a step-definition class, or the new configuration class is outside glue Use a dedicated @CucumberContextConfiguration class with a Spring context annotation in the glue package
Property appears accepted but has no effect The spelling, supported options, runner, or integration version differs Check the supported properties for the exact v6 integration; do not infer a universal mapping from one release-note example

Performance, reliability, and cost considerations

The release notes identify high memory consumption as a limitation of the previous JSON formatter and present message output as a response to that problem. They do not provide benchmark numbers, so assess memory and report generation using the project’s own suite and consumers. Message output also introduces a format compatibility decision: confirm parsers and CI report generation before switching.

Strict behavior can make CI more reliable by surfacing unfinished or unimplemented steps as failures, but it can also turn previously tolerated work-in-progress scenarios into build breaks. Tag filters can control scope, provided excluded scenarios remain visible to the team.

Cucumber-JVM is open-source software; the v6.0.0 changes described here do not introduce a per-test usage charge. Account for engineering time and CI runtime when planning the migration, but do not infer a performance or cost saving from the release notes.

Or skip the browser setup

If your test workflow also needs website captures for documentation or visual review, ScreenshotNeo offers a one-request screenshot API. This is separate from Cucumber-JVM and does not replace Cucumber test execution.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation. Cookie banners, popups and chat widgets are removed before the shot; bot checks, blank pages and failed loads are never billed. An MCP server lets AI agents use screenshot tools. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. Learn more about ScreenshotNeo or sign up free for 1,000 screenshots a month, with no card.

FAQ

Does v6.0.0 require rewriting existing feature files?

No. Existing feature files can remain as they are; the new Rule keyword is available when it improves how a feature is organized.

Should every project replace its JSON report immediately?

No. The message formatter was introduced as a new format and intended eventually to replace the old JSON formatter. Check report consumer support and migrate deliberately.

Is this a guide to every Cucumber-JVM 6.x release?

No. It explains notable changes in v6.0.0. Consult the project changelog and relevant release notes for a complete patch-level migration review.

Sources