Tags Syntax in Cucumber JVM

What Are Tags in Cucumber?

Tags in Cucumber are special labels that begin with the @ symbol and are used to categorize, organize, filter, and control the execution of features and scenarios. A tag does not change the business meaning of a scenario by itself. Instead, it adds metadata that helps the automation framework and the team understand how a scenario should be grouped, selected, reported, or prepared for execution.

In simple terms, a tag is a label attached to a feature, scenario, scenario outline, or examples block. Common examples include @Smoke, @Regression, @Login, @API, @UI, @Critical, and @Sprint1. These labels help teams run a focused subset of tests instead of running the entire automation suite every time.

Tags are especially important in large Cucumber JVM projects. A small project may have ten or twenty scenarios, and running everything may be easy. A real enterprise project may have hundreds or thousands of scenarios across multiple modules, browsers, environments, and test layers. Without tags, selecting the right scenarios becomes slow and error-prone. With tags, the team can run only smoke tests, only regression tests, only API scenarios, only payment scenarios, or only high-priority tests.

Good tag syntax is not only about writing @ before a word. It is about creating a consistent tagging strategy that supports execution, reporting, ownership, and maintenance. When tags are clear and consistent, the test suite becomes easier to operate. When tags are random, duplicated, or overloaded with hidden meaning, they create confusion and brittle execution rules.

Why Tags Are Needed

Tags solve a practical problem: not every test should run in every situation. During development, a tester may want to run only login scenarios. Before a release, the team may want to run the full regression suite. During a CI pull request build, the pipeline may run only fast smoke tests. During nightly execution, the pipeline may run long end-to-end scenarios. Tags make these choices possible.

Imagine a project with two thousand Cucumber scenarios. Five hundred may be smoke tests, twelve hundred may be regression tests, three hundred may be API tests, and a smaller group may be critical business flows. If all scenarios are mixed without labels, the team has to rely on folder paths, feature names, manual selection, or separate runners. This becomes difficult as the suite grows. Tags provide a direct and readable way to classify scenarios.

@Smoke
Scenario: Successful login with valid credentials
  Given the user has valid credentials
  When the user logs in
  Then the user should be authenticated

Once the scenario is tagged as @Smoke, Cucumber can execute only smoke scenarios when needed. The same scenario can also carry other tags if it belongs to multiple groups. For example, a login smoke scenario may also be part of regression, UI automation, and critical path testing.

Tags also help reports. A report that shows failures by tag can help teams understand whether smoke tests are stable, whether API tests are failing, or whether critical scenarios are blocked. This gives tags value beyond execution selection. They become a way to understand test coverage and risk.

Basic Tag Syntax

The basic syntax is straightforward. A tag starts with the @ symbol followed by a tag name. The tag is placed above the feature, scenario, scenario outline, or examples block that it should apply to.

@Smoke
Scenario: Login with valid credentials
  Given the user has valid credentials
  When the user logs in
  Then the dashboard should be displayed

Multiple tags can be placed on the same line or across multiple lines. Both styles are valid, but teams should choose one convention and follow it consistently. Placing tags on one line is compact. Placing each tag on its own line can be easier to scan when scenarios have many tags.

@Smoke @UI @Login
Scenario: Login with valid credentials
  Given the user has valid credentials
  When the user logs in
  Then the dashboard should be displayed

A tag applies to the element directly below it. If a tag appears above a feature, it applies to all scenarios inside that feature. If it appears above a scenario, it applies only to that scenario. If it appears above an examples block, it applies only to examples in that block. Understanding this placement rule is essential because incorrect placement can cause the wrong scenarios to run.

Naming Rules for Tags

A valid tag begins with @ and then uses a name that is meaningful to the project. Common tag names contain letters, numbers, underscores, and sometimes hyphens depending on the team's convention and tooling support. Examples of readable tags include @Smoke, @Regression, @API, @UI, @Critical, @HighPriority, @Sprint1, @Checkout, and @Payment.

Although Cucumber supports flexible tag names, teams should not treat tags as free text. Consistency matters. A suite that contains @Smoke, @smoke, @SMOKE, and @smokeTest becomes hard to filter reliably. Decide on a naming style early. Many teams prefer simple PascalCase tags such as @Smoke and @Regression, or lowercase tags such as @smoke and @regression. The exact style matters less than consistency.

Tags should be short but meaningful. A tag such as @A is too vague. A tag such as @RunThisScenarioOnlyForTheLatestPaymentGatewayRegressionBuild is too long and hard to maintain. Good tags communicate category, purpose, priority, layer, module, or execution group without becoming sentences.

Invalid and Poor Tag Examples

Some tag mistakes are syntactically invalid. For example, writing Smoke without the @ symbol is not a tag. Writing @@Smoke is incorrect because only one @ should be used. Writing @Smoke Test is also wrong because tag names should not contain spaces.

Smoke
Scenario: Login

@Smoke Test
Scenario: Login

@@Smoke
Scenario: Login

Other tag mistakes may be technically accepted but poor in practice. Tags such as @test, @new, @temp, @done, and @working are usually weak because they do not communicate lasting meaning. Temporary tags are sometimes useful during local debugging, but they should not remain in the committed test suite unless the team has a defined convention for them.

Another poor practice is using tags as secret instructions. For example, a tag named @Login may be acceptable as a category, but it becomes dangerous if it silently triggers login behavior through a hook. Tags should primarily classify tests. They should not hide important business actions unless the team is using them for explicit technical setup and everyone understands the convention.

Feature-Level Tags

Feature-level tags are written above the Feature keyword. They apply to every scenario and scenario outline inside that feature file. This is useful when all scenarios in a file belong to the same module, layer, or execution category.

@Regression
Feature: Login Feature

  Scenario: Valid login
    Given the user has valid credentials
    When the user logs in
    Then the user should be authenticated

  Scenario: Invalid login
    Given the user has invalid credentials
    When the user tries to log in
    Then an error message should be displayed

In this example, both scenarios inherit the @Regression tag. This keeps the file concise because the same tag does not need to be repeated above every scenario. Feature-level tags are helpful for broad classification.

However, feature-level tags should be used carefully. If only some scenarios in the feature are smoke tests, do not place @Smoke at the feature level. Put @Smoke only on the specific scenarios that belong to the smoke suite. Over-tagging at the feature level can cause too many scenarios to run in focused executions.

Scenario-Level Tags

Scenario-level tags are placed directly above a specific scenario. They apply only to that scenario. This is the most common form of tagging because different scenarios inside the same feature often belong to different categories.

Feature: Login

  @Smoke @Positive
  Scenario: Valid login
    Given the user has valid credentials
    When the user logs in
    Then the dashboard should be displayed

  @Regression @Negative
  Scenario: Invalid login
    Given the user has invalid credentials
    When the user tries to log in
    Then an invalid credentials error should be displayed

Here, the valid login scenario is part of smoke and positive testing, while the invalid login scenario is part of regression and negative testing. This allows precise selection. A smoke run executes the first scenario. A regression run may execute both if the feature or other runner settings include them.

Scenario-level tags are best for categories that vary from scenario to scenario, such as priority, test type, risk, defect coverage, or specific business flow. They keep classification accurate and reduce accidental execution.

Scenario Outline Tags

Tags can be applied to scenario outlines in the same way they are applied to scenarios. A tag above a Scenario Outline applies to all examples inside that outline unless examples-level tags are used to narrow or separate groups.

@Regression @Login
Scenario Outline: Login validation
  Given the user enters "<username>" and "<password>"
  When the user tries to log in
  Then the login result should be "<result>"

Examples:
  | username | password | result  |
  | valid    | valid    | success |
  | invalid  | valid    | failure |

This is useful when every row in the examples table belongs to the same category. If some rows are smoke and others are regression-only, examples-level tags may be better. This avoids splitting the whole outline unnecessarily while still supporting selective execution.

Examples-Level Tags

Cucumber allows tags above examples blocks in a scenario outline. This is useful when different data sets in the same outline belong to different execution groups. For example, one examples block may contain smoke data, while another contains broader regression data.

Scenario Outline: Login validation
  Given the user enters "<username>" and "<password>"
  When the user tries to log in
  Then the login result should be "<result>"

  @Smoke
  Examples: Smoke data
    | username | password | result  |
    | valid    | valid    | success |

  @Regression
  Examples: Regression data
    | username | password | result  |
    | invalid  | valid    | failure |
    | valid    | invalid  | failure |

This pattern is powerful because it keeps related data-driven behavior in one outline while still allowing filtered execution. A smoke run can execute only the smoke examples. A regression run can execute the broader set. However, examples-level tags should be used only when the behavior is the same and the difference is genuinely the data category. If outcomes and rules differ significantly, separate scenarios may be clearer.

Multiple Tags on One Scenario

A scenario can have multiple tags because a test can belong to multiple categories at the same time. A checkout scenario may be @Smoke, @Regression, @UI, @Checkout, and @Critical. Each tag answers a different question. Is it part of smoke? Is it part of regression? Is it a UI test? Which module does it cover? How important is it?

@Smoke @Regression @UI @Checkout @Critical
Scenario: Successful checkout with card payment
  Given the user has items in the cart
  And the user provides valid card details
  When the user places the order
  Then the order should be confirmed

Multiple tags are useful, but they should not be excessive. If every scenario has ten or fifteen tags, the tagging system may be too complicated. Tags should make selection and reporting easier, not create noise. A good tagging strategy uses a small number of meaningful tag dimensions.

Common Tag Categories

Most Cucumber JVM projects use tags across a few common categories. Execution group tags include @Smoke, @Regression, @Sanity, and @EndToEnd. Layer tags include @UI, @API, and @DB. Module tags include @Login, @Checkout, @Payment, @Search, and @Profile. Priority tags include @Critical, @High, @Medium, and @Low.

Teams may also use ownership or sprint tags, such as @TeamPayments, @Sprint12, or @Release2026_08. These can be useful temporarily for planning and reporting, but they should be reviewed regularly. Tags that were useful during one sprint can become stale after release.

The best tag categories are stable and actionable. A tag is stable if it remains meaningful over time. A tag is actionable if it helps someone run, filter, report, triage, or organize scenarios. If a tag does not support a real workflow, it may not be needed.

Tags and Test Execution

One of the main reasons teams use tags is execution filtering. Cucumber can run scenarios based on tag expressions. For example, a runner or command can request only smoke tests, exclude slow tests, or run scenarios that match multiple tags. This makes tags central to CI pipeline design.

A simple expression such as @Smoke runs scenarios tagged with smoke. An expression such as @Smoke and @UI runs only scenarios that have both tags. An expression such as @Smoke or @Sanity runs scenarios that have either tag. An expression such as not @WIP excludes work-in-progress scenarios.

Tag filtering should match how the team actually executes tests. If the CI pipeline has a smoke stage, the @Smoke tag should identify a small, fast, high-value set of scenarios. If the nightly pipeline runs regression, the @Regression tag should represent the broader suite. If tags are inaccurate, pipeline results become misleading.

Tags in Cucumber Runner

In Cucumber JVM, tags are often configured in the runner class or build command. The exact syntax depends on the version, test runner, and build tool, but the concept is the same: Cucumber receives a tag expression and executes matching scenarios.

@CucumberOptions(
    features = "src/test/resources/features",
    glue = "stepdefinitions",
    tags = "@Smoke"
)
public class TestRunner {
}

This runner executes scenarios tagged with @Smoke. A more specific runner might use a tag expression:

@CucumberOptions(
    tags = "@Smoke and @UI"
)

Modern projects often pass tag expressions through Maven, Gradle, or CI variables instead of hardcoding them in the runner. This is more flexible because the same runner can execute different suites based on command-line configuration.

Tags in Maven or CI Execution

Build tools and CI pipelines often pass tags dynamically. This allows the same codebase to run smoke tests during pull requests, regression tests during nightly builds, and critical tests before deployment. The tag expression becomes part of the pipeline configuration.

mvn test -Dcucumber.filter.tags="@Smoke"

For a regression build, the command may change:

mvn test -Dcucumber.filter.tags="@Regression and not @WIP"

This approach avoids creating many runner classes for every execution group. It also makes CI jobs easier to control. The pipeline can expose the tag expression as a parameter so testers can trigger focused runs without editing code.

When using dynamic tags, teams should document commonly used expressions. Otherwise, people may invent slightly different expressions for the same purpose. A short README or framework guide can list standard commands for smoke, regression, API, UI, and critical-path execution.

Tags and Hooks

Tags can also control hooks. A tagged hook runs only for scenarios that match the tag expression. This is useful for technical setup. For example, UI tests may need a browser, while API tests may not. A @UI hook can initialize WebDriver only for UI scenarios.

@Before("@UI")
public void startBrowser() {
    DriverFactory.initializeDriver();
}

This is a good use of tags because it controls technical setup. A browser is a framework resource, not business behavior. The scenario does not need to say "Given the browser is opened" because opening a browser is an automation concern.

However, using tags to hide business flow is a hook anti-pattern. A tag such as @Login should not silently perform login unless the team has very clearly defined it as technical context and the scenario still communicates its business precondition. In most cases, Given the user is logged in is clearer than a hidden login hook.

Tags as Metadata, Not Business Logic

A strong tagging strategy treats tags as metadata. They describe category, priority, layer, module, risk, or execution behavior. They should not carry hidden business meaning that changes what a scenario does. The scenario body should remain the primary source of business truth.

For example, @Payment is a good module tag because it says the scenario belongs to the payment area. But if @Payment causes a hook to create a payment, submit it, and validate it, the tag has become hidden business logic. That makes the feature file harder to trust.

Good metadata supports tooling. It helps the runner select scenarios, helps reports group results, helps teams identify ownership, and helps CI pipelines decide what to execute. It does not replace readable Gherkin.

Tag Naming Conventions

Every team should define tag naming conventions. Without conventions, tag sprawl happens quickly. One person writes @Smoke, another writes @smoke, another writes @SmokeTest, and another writes @Sanity for the same purpose. Eventually, no one is sure which tag the pipeline should use.

A simple convention may define categories such as execution, layer, module, priority, and status. Execution tags might be @Smoke, @Regression, and @Sanity. Layer tags might be @UI, @API, and @DB. Priority tags might be @Critical, @High, @Medium, and @Low.

Teams should also decide case style. If the project uses @Smoke, avoid @smoke. If the project uses lowercase tags, avoid uppercase alternatives. Consistency improves search, filtering, and report interpretation.

Tag Granularity

Tag granularity means deciding how broad or specific tags should be. A broad tag such as @Regression may apply to many scenarios. A specific tag such as @InvalidPasswordLockout may apply to one small behavior. Both can be useful, but overusing very specific tags can create clutter.

Good tags are specific enough to support useful selection but broad enough to remain manageable. Module tags such as @Login, @Checkout, and @Orders are usually useful. Extremely narrow tags for every scenario often become redundant because the scenario name already identifies the behavior.

If a tag is used only once and has no reporting, execution, or ownership purpose, ask whether it is needed. Tags should serve the framework and the team, not duplicate scenario titles.

Tags and Reporting

Reports can use tags to group scenarios and analyze failures. If all payment scenarios carry @Payment, the team can quickly see whether payment failures are concentrated. If critical scenarios carry @Critical, release reports can highlight whether high-risk flows passed. If UI and API tests are tagged separately, reports can show which layer is unstable.

This reporting value depends on tag accuracy. If scenarios are tagged randomly or inconsistently, report insights become unreliable. For example, if some smoke tests are missing @Smoke, the smoke report is incomplete. If too many low-value scenarios are tagged as @Critical, the critical report loses meaning.

Tag review should be part of test maintenance. When scenarios are added, changed, moved, or deprecated, their tags should be reviewed. Tags are not one-time decoration. They are part of the test suite's operational model.

Tags and Ownership

Tags can also help with ownership when a test suite is maintained by multiple teams. A large organization may have separate teams for checkout, payments, profile, search, order management, and reporting. Module tags such as @Checkout and @Payments make it easier to identify which team should review a failure. Some projects also use ownership tags such as @TeamPayments or @TeamIdentity when module names and team names are not the same.

Ownership tags should be used carefully because teams change over time. If ownership tags are added, they should be reviewed during release planning or framework maintenance. Stale ownership tags can send failures to the wrong group and slow down triage. For long-term stability, module tags are usually more durable than team-name tags, while team tags are useful when the organization needs direct routing in reports or dashboards.

Tags and Test Suite Design

Tags should reflect how the suite is designed. A well-designed suite usually has layers and execution groups. Smoke tests are small and fast. Regression tests are broader. UI tests validate browser-level behavior. API tests validate service behavior. Critical tests cover business risks. Tags should make these distinctions visible.

When tags are planned well, a team can answer practical questions quickly. Which tests should run before deployment? Which tests cover checkout? Which tests are UI-only? Which scenarios are unstable and temporarily excluded? Which scenarios belong to the current release scope? Tags provide those answers without requiring a manual search through hundreds of files.

Poor suite design often shows up as tag confusion. If every scenario is tagged with everything, tags no longer help. If no scenario is tagged consistently, execution cannot be controlled. If tags are used to hide setup flow, readability suffers. Tag design and suite design are closely connected.

Common Tag Mistakes

Using Too Many Tags

Too many tags make scenarios hard to scan. If a scenario has a long row of tags, readers may stop paying attention to them. Use tags that support real execution, reporting, or ownership needs.

Using Duplicate Meanings

Tags such as @Smoke, @Sanity, and @Quick may overlap if the team does not define them clearly. Duplicate meanings create confusion in CI and reporting.

Using Tags as Hidden Steps

Tags should not silently perform business actions through hooks. If a scenario requires a logged-in user or an item in the cart, that context should be visible in Gherkin.

Leaving Temporary Tags Forever

Temporary tags such as @WIP, @debug, or @local should be reviewed before code is committed. Stale temporary tags can accidentally exclude or include scenarios.

Inconsistent Case and Spelling

@Smoke, @smoke, and @smoketest may all look similar to humans, but filtering tools treat them as different tags. Consistent spelling and case are essential.

Best Practices

Use tags for execution groups, test layers, modules, priorities, ownership, and temporary control when needed. Keep names short, readable, and consistent. Define standard tags in a framework guide so all team members use the same vocabulary. Prefer a small number of meaningful tags over many random labels.

Apply broad tags at the feature level only when every scenario in the feature truly belongs to that category. Apply scenario-level tags when classification differs between scenarios. Use examples-level tags when different data groups inside the same scenario outline need different execution treatment.

Avoid using tags to hide business behavior. Do not make tags a replacement for clear Gherkin steps. Use tag-based hooks for technical setup such as browser initialization, database setup, API clients, screenshots, or special reporting. Keep business preconditions visible through meaningful steps.

Review tags regularly. Remove stale tags, merge duplicate tags, and correct inconsistent casing. Make sure CI tag expressions match the intended execution strategy. Tags are only useful when they remain accurate.

Real-Time Tagging Example

Consider an e-commerce automation suite. The login feature may include smoke and regression scenarios. Checkout may include critical UI scenarios. Payment may include API and UI tests. Search may include regression-only scenarios. A practical tagging strategy can make this suite easy to run and report.

@Regression @Login
Feature: Login

  @Smoke @UI @Critical
  Scenario: Successful login with valid credentials
    Given the user has valid credentials
    When the user logs in
    Then the dashboard should be displayed

  @Regression @UI @Negative
  Scenario: Login fails with invalid password
    Given the user has an invalid password
    When the user tries to log in
    Then an invalid password message should be displayed

In this example, the feature-level tags classify the whole file as login regression coverage. Scenario-level tags refine each scenario. The first scenario belongs to smoke, UI, and critical execution. The second scenario belongs to regression, UI, and negative testing. The tags are readable and actionable.

A CI pull request pipeline may run @Smoke and @UI. A nightly pipeline may run @Regression and not @WIP. A payment team may run @Payment. These commands work only because the tags are designed consistently.

Interview-Ready Explanation

Tags in Cucumber are labels that start with the @ symbol and are used to categorize, organize, filter, and control scenario execution. They can be applied at feature level, scenario level, scenario outline level, and examples level. Feature-level tags apply to all scenarios in the feature, while scenario-level tags apply only to a specific scenario.

Tags are commonly used for smoke, regression, UI, API, module, priority, and CI execution control. Cucumber can run scenarios using tag expressions such as @Smoke, @Smoke and @UI, or @Regression and not @WIP. Good tags are meaningful, consistent, and used as metadata rather than hidden business logic.

Summary

Tags syntax in Cucumber JVM is simple, but tag strategy is important. A tag begins with @ and acts as a label for features, scenarios, outlines, or examples. Tags help teams organize large suites, run focused test groups, control CI pipelines, and improve reporting.

The golden rule is to use tags as clear metadata. Keep tag names consistent, avoid spaces and duplicate meanings, apply tags at the right level, and do not use tags to hide business steps. When tags are designed well, Cucumber execution becomes flexible, reports become more useful, and the automation suite becomes easier to maintain.