Boolean Tag Expressions to Filter Cucumber Scenarios in CI
How to use boolean tag expressions and version‑aware filter config to precisely control which Cucumber scenarios run, with JUnit 5 and JUnit 4 examples.
06 May 2026, 19:03 UTC

Problem: Tag filters silently exclude scenarios, breaking CI confidence
You run cucumber --tags @smoke expecting only smoke tests, but regression scenarios also vanish—or worse, critical tests silently skip. The root cause is usually one of two things: using tag syntax that doesn't match your Cucumber version, or tagging scenarios inconsistently so the filter doesn't match what you think it matches.
Useful takeaway
Modern Cucumber (7.x+) supports boolean tag expressions like @smoke and not @slow, which replace the older comma‑separated (OR) and double‑AND syntax that are deprecated or removed in recent releases. Pairing boolean expressions with the version‑appropriate filter mechanism—cucumber.filter.tags for JUnit Platform or @CucumberOptions(tags = '@smoke and not @slow') for JUnit 4—gives you precise control over which scenarios run, without maintaining a separate tag list for every pipeline.
Prerequisites
- A Cucumber-JVM project (Maven or Gradle) with Cucumber 7.x or later installed.
- A consistent tag naming convention: purpose‑based tags such as
@smoke,@regression, and environment or work‑in‑progress tags such as@wip. - Knowledge of which test runner your project uses: JUnit 4 or JUnit Platform (JUnit 5).
Focused procedure
- Tag at the right level. Place tags on Feature blocks when all scenarios in that feature share the same tag. A tag on a Feature is inherited by every Scenario and Example within it, so you avoid redundant annotations.
- Write a boolean tag expression. For example, to run smoke tests excluding any that are marked slow:
cucumber.filter.tags = @smoke and not @slow - Configure the filter for your runner.
- JUnit Platform (JUnit 5): add the property to
junit-platform.properties: cucumber.filter.tags=@smoke and not @slow- JUnit 4: use the
@CucumberOptionsannotation: @CucumberOptions(tags = '@smoke and not @slow')
- JUnit Platform (JUnit 5): add the property to
- Combine path filtering with tag expressions. If you only want to run scenarios under
features/checkout/that match the tag, you can select the directory in your CI step and keep the tag expression separate; Cucumber will intersect the two criteria.
Expected checks
- Confirm that only the expected scenarios appear in the report and that the console shows the filter was applied.
- Invert the expression (e.g.,
not @smoke) and verify that the complementary set runs—this proves the filter is intersecting correctly rather than just excluding by name. - Deliberately misspell a tag in the filter (e.g.,
@smok) and observe that zero scenarios run. This confirms the silent‑exclusion behavior; make sure your team understands this before relying on it in production CI.
Limitations and recovery
Tag syntax and runner configuration differ across Cucumber implementations (JVM, JavaScript, Ruby) and across major versions. Older tutorials showing comma‑separated tag lists such as --tags @a,@b may not work on current Cucumber releases, where that syntax is interpreted as a logical OR only in legacy modes or not at all. Over‑tagging scenarios creates maintenance burden; tags without clear ownership or inconsistent naming quickly become unreliable as a filter mechanism. If you find yourself adding tags just to make a pipeline work, reconsider whether a tag expression or feature‑path selection better fits the goal. When a tag expression needs to be adjusted, the recovery step is simply updating the filter property or annotation to the corrected expression. Because tag filtering does not modify step definitions or feature files, the change is non‑destructive and can be committed like any other configuration update.
Comparison of tag‑filter syntax across Cucumber versions
| Cucumber version | Tag-filter syntax |
|---|---|
| Pre‑7.0 | --tags @a,@b (OR), --tags @a --tags @b (AND, deprecated) |
| 7.x+ | --tags '@a and not @b' or filter property boolean expressions |
| JUnit 4 vs Platform | @CucumberOptions(tags = '@smoke and not @slow') vs cucumber.filter.tags in junit-platform.properties |
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.