Cucumber Expressions with String and Int in Cucumber JVM
1. Introduction to Cucumber Expressions
Cucumber Expressions are a simple, readable pattern-matching syntax used in Cucumber JVM step definitions. They connect Gherkin steps from feature files to Java methods while allowing values from the step text to be captured and passed into method parameters. Instead of writing complex Regular Expressions for common values, Cucumber Expressions use placeholders such as {string}, {int}, {double}, {float}, and {word}. These placeholders make step definitions easier to read, easier to write, and easier to maintain.
In a Cucumber framework, readability matters because step definitions are not only written by automation engineers. They are reviewed by testers, developers, SDETs, business analysts, and sometimes product owners. A pattern that looks close to the Gherkin sentence is easier to understand than a pattern filled with escape characters and capture groups. This is the main reason Cucumber Expressions became the preferred style in modern Cucumber projects.
For example, a Regex pattern for login role mapping may look like this:
@Given("^the user logs in as \"([^\"]*)\"$")
public void userLogsInAs(String role) {
}
The equivalent Cucumber Expression is much clearer:
@Given("the user logs in as {string}")
public void userLogsInAs(String role) {
}
Both patterns can capture Admin from the feature step, but the Cucumber Expression is easier for the team to read and maintain.
2. What Are Cucumber Expressions?
Readable Step Definition Patterns
Cucumber Expressions are pattern strings placed inside step definition annotations such as @Given, @When, and @Then. They describe the expected Gherkin sentence and use parameter placeholders where dynamic values should be captured. When Cucumber reads a scenario step, it compares the step text with the expression, extracts values, converts them to Java types when possible, and calls the matching method.
Given the user logs in as "Admin"
@Given("the user logs in as {string}")
public void loginAs(String role) {
loginService.loginAs(role);
}
In this example, {string} captures "Admin" from the feature file and passes Admin into the role parameter. The quotation marks are part of the feature syntax, but the Java parameter receives the inner text. The method does not need to parse the value manually.
Cucumber Expressions are not separate test cases and they are not assertions. They are mapping patterns. Their job is to make dynamic step definitions readable and type-aware.
3. Why Cucumber Expressions Were Introduced
Earlier Cucumber projects often relied heavily on Regular Expressions. Regex is powerful, but it can become hard to read. A simple quoted string capture may require escaped quotes and capture groups. A number may require digit patterns. Optional text and alternatives may require more advanced Regex syntax. For teams focused on behavior readability, this created unnecessary friction.
Cucumber Expressions were introduced to simplify common step definition patterns. Instead of writing Regex for ordinary strings, integers, decimals, and words, teams can use built-in placeholders. This reduces syntax errors, improves maintainability, and makes step definitions more approachable for beginners.
The goal is not to remove Regex completely. Regex still has value for complex matching. The goal is to make common BDD step definitions simple. Most business scenarios capture values like names, roles, quantities, prices, statuses, and messages. Cucumber Expressions handle those cases cleanly.
4. How Cucumber Expressions Work
From Feature Step to Java Parameter
The matching process is straightforward. Cucumber reads a feature step, compares it with registered step definition expressions, extracts values from placeholders, converts those values to Java types, and invokes the Java method with those arguments.
Feature file
|
v
Read Gherkin step
|
v
Match Cucumber Expression
|
v
Extract parameters
|
v
Convert to Java type
|
v
Execute step definition method
This automatic extraction and conversion is what makes expressions productive. A step such as "Given the account balance is 500" can pass an int value directly to a Java method. A step such as "Given the product price is 299.99" can pass a double value. The step definition remains focused on behavior instead of manual parsing.
5. Basic Syntax
The basic syntax is a normal sentence with placeholders where variable values appear. The static words must match the feature step text, and the placeholders capture dynamic values.
Feature file:
Given the user logs in as "Admin"
Step definition:
@Given("the user logs in as {string}")
public void loginAs(String role) {
}
Cucumber extracts Admin and passes it into role. The annotation remains close to the Gherkin step, so the mapping is easy to understand. This is much cleaner than writing a Regex capture group for the same value.
The static text still matters. If the feature says "Given the user signs in as \"Admin\"" but the expression says "the user logs in as {string}", the step will not match unless another expression supports that wording. Cucumber Expressions improve readability, but they do not remove the need for consistent vocabulary.
6. Built-In Parameter Types
Cucumber provides several predefined parameter types for common Java values. These placeholders eliminate many common Regex patterns.
| Expression | Java Type | Example |
|---|---|---|
| {string} | String | "Admin" |
| {int} | int / Integer | 100 |
| {long} | long / Long | 9999999999 |
| {double} | double / Double | 99.95 |
| {float} | float / Float | 10.5 |
| {word} | String | Admin |
| {bigdecimal} | BigDecimal | 1234.56 |
| {biginteger} | BigInteger | 98765432101234567890 |
| {byte} | byte / Byte | 120 |
| {short} | short / Short | 32000 |
These parameter types are enough for many automation scenarios. The key is choosing the placeholder that matches the feature text and the Java method argument type.
7. The {string} Expression
Capturing Quoted Text
{string} captures text enclosed in quotes. It is the best choice for values that may contain spaces or special characters, such as names, roles, messages, product names, email subjects, statuses, and labels.
Given the user logs in as "Admin"
@Given("the user logs in as {string}")
public void userLogsInAs(String role) {
loginService.loginAs(role);
}
The captured value is Admin. The quotes are not included in the Java String. This is convenient because the feature file remains readable and the method receives clean data.
{string} is also useful for multi-word values:
Given the customer name is "John Smith"
@Given("the customer name is {string}")
public void customerNameIs(String name) {
customer.setName(name);
}
Because John Smith contains a space, {string} is more appropriate than {word}. The quotes make the value boundary clear.
8. Multiple {string} Parameters
A step can capture more than one quoted string. This is common for login credentials, form fields, search filters, source and destination values, or expected and actual labels.
Given the user enters "John" and "Password123"
@Given("the user enters {string} and {string}")
public void enterCredentials(String username, String password) {
loginPage.enterCredentials(username, password);
}
Cucumber maps the first captured string to username and the second captured string to password. Parameter order is important. If the method arguments are reversed, the code may still compile but the automation behavior will be wrong.
When a step needs many string values, consider whether a Data Table would be clearer. Multiple placeholders are fine for two or three values, but long sentences with many parameters become hard to read.
9. The {int} Expression
Capturing Whole Numbers
{int} captures integer values and converts them automatically into an int or Integer method parameter. This is useful for counts, balances, quantities, retry attempts, order numbers that are numeric, and other whole-number values.
Given the account balance is 500
@Given("the account balance is {int}")
public void accountBalanceIs(int amount) {
account.setBalance(amount);
}
Cucumber converts 500 into an int before calling the method. No Integer.parseInt call is needed. This keeps the step definition clean and avoids unnecessary parsing code.
{int} should be used when the business value is naturally a whole number. If the feature step contains a decimal value such as 500.50, {int} is not the right placeholder. Use {double}, {float}, or {bigdecimal} depending on the domain need.
10. The {double} Expression
{double} captures decimal numeric values and converts them to double or Double. It is commonly used for product prices, tax amounts, percentages, measurements, ratings, and totals.
Given the product price is 299.99
@Given("the product price is {double}")
public void productPriceIs(double amount) {
product.setPrice(amount);
}
For many tutorial and automation examples, double is convenient. For real financial applications, BigDecimal may be better because floating-point types can introduce precision concerns. The step expression should support readable scenarios, while the implementation should respect the domain's precision requirements.
11. The {float} Expression
Capturing Floating-Point Values
{float} captures decimal values and passes them to float or Float parameters. It is less common than {double}, but it can be used when the Java API or domain model expects a float value.
Given the temperature is 27.5
@Given("the temperature is {float}")
public void temperatureIs(float temperature) {
weather.setTemperature(temperature);
}
As with double, use float carefully for financial values. It is better suited for measurements or examples where exact decimal precision is not the main concern.
12. The {word} Expression
{word} captures a single unquoted word. It is useful for simple values such as Admin, active, approved, pending, Chrome, Firefox, yes, or no. It does not capture spaces.
Given the user role is Admin
@Given("the user role is {word}")
public void userRoleIs(String role) {
loginService.setRole(role);
}
This works because Admin is one word. It will not work for Super Admin if the feature step is unquoted because {word} captures only one word. For multi-word values, use {string} and quote the value:
Given the user role is "Super Admin"
@Given("the user role is {string}")
public void userRoleIs(String role) {
}
13. The {long} Expression
Large Numeric Identifiers
{long} captures larger whole numbers and converts them into long or Long. It is useful for transaction IDs, numeric account identifiers, external reference numbers, and values that may exceed the int range.
Given the transaction ID is 1234567890123
@Given("the transaction ID is {long}")
public void transactionIdIs(long id) {
transactionService.load(id);
}
Use {long} when the value is numeric and large enough that int may be unsafe. If an ID contains letters, hyphens, or leading zeros that must be preserved, use {string} or a custom parameter type instead.
14. BigDecimal and BigInteger Expressions
{bigdecimal} and {biginteger} are useful when values need larger range or more precise representation. BigDecimal is especially relevant for money, tax, interest, and financial calculations. BigInteger is useful for very large integer values.
@Given("the invoice total is {bigdecimal}")
public void invoiceTotalIs(BigDecimal total) {
invoice.setTotal(total);
}
When using BigDecimal or BigInteger, remember to import the correct Java classes. These types are more explicit than double or long and can make the step definition better aligned with serious business domains.
15. Multiple Parameter Types in One Step
Combining Strings, Integers, and Decimals
Cucumber Expressions can combine different parameter types in one annotation. This is useful when a business step naturally contains a name, quantity, and amount.
Given the customer "John" purchased 5 products worth 1500.50
@Given("the customer {string} purchased {int} products worth {double}")
public void customerPurchasedProducts(String name, int quantity, double amount) {
orderService.recordPurchase(name, quantity, amount);
}
Cucumber maps John to the String parameter, 5 to the int parameter, and 1500.50 to the double parameter. This keeps the scenario readable while passing typed data into Java.
Use this style when the values are all essential to the behavior. If the step starts to become long or crowded, a Data Table may communicate the data more clearly.
16. Parameter Order
Parameters are passed to the Java method in the same order they appear in the expression. The names of Java parameters do not affect mapping. Only the order matters.
Given "John" has 5 orders
@Given("{string} has {int} orders")
public void customerHasOrders(String customer, int orders) {
}
Here, John maps to customer and 5 maps to orders. If the method signature were written as public void customerHasOrders(int orders, String customer), the argument order would not match the expression and the method would be invalid or behave incorrectly depending on conversion. Keep expression order and method signature order aligned.
17. Expression Matching Process
Automatic Extraction and Conversion
When Cucumber matches an expression, it does more than string comparison. It identifies placeholders, extracts corresponding text, converts those values into Java types, and passes them into the method.
Feature step
|
v
Find matching expression
|
v
Extract values
|
v
Convert data types
|
v
Pass arguments to Java method
This automatic conversion is why Cucumber Expressions reduce boilerplate. You do not need to manually remove quotes from strings or parse integers in most cases. The framework handles normal conversion based on the placeholder type.
18. Advantages of Cucumber Expressions
Cucumber Expressions improve readability and maintainability. They are easy to write, easy to review, and less error-prone than Regex for common patterns. They also make built-in parameter types visible directly in the annotation.
- They are easier to read than Regex.
- They reduce escaping and capture-group syntax.
- They support automatic type conversion.
- They provide built-in parameter types.
- They improve team collaboration.
- They are preferred in modern Cucumber projects.
The biggest benefit is that the mapping pattern remains close to business language. This helps keep the BDD framework understandable for the whole team.
19. Limitations of Cucumber Expressions
Not Designed for Every Complex Pattern
Cucumber Expressions are not designed to replace every Regex use case. They are excellent for common parameters, but they are not always the best choice for strict format validation or complex matching rules. For example, validating an order number like ORD-2026-123456 may be easier with Regex or a custom parameter type.
@Given("^the order number is ([A-Z]{3}-\\d{4}-\\d{6})$")
public void orderNumberIs(String orderNumber) {
}
A simple {string} placeholder would capture many invalid formats. If the step should only match a strict pattern, Regex may be appropriate. Another clean option is to define a custom parameter type such as {orderId} and keep the annotation readable.
20. Common Mistake: Using {word} for Multiple Words
A frequent mistake is using {word} when the value may contain spaces. For example:
Given the customer name is "John Smith"
This should not be matched with {word}. The correct placeholder is {string}:
@Given("the customer name is {string}")
public void customerNameIs(String name) {
}
{word} is only for one unquoted word. When a value may contain spaces, quote it in the feature file and capture it with {string}.
21. Common Mistake: Missing Quotes with {string}
{string} Expects Quoted Text
{string} captures quoted text. If the feature step omits quotes, the expression may not match.
Feature step:
Given the user is Admin
Step definition:
@Given("the user is {string}")
public void userIs(String role) {
}
The feature should be written as:
Given the user is "Admin"
Alternatively, if the role is always one word and the team prefers no quotes, use {word}. The important part is making the feature text and expression agree.
22. Common Mistake: Wrong Data Type
Choose the placeholder that matches the value. If the feature says:
Given the amount is 500
{int} is usually more appropriate than {double} because the value is a whole number. If the feature says 500.75, {double} or {bigdecimal} may be better. Incorrect placeholders can cause undefined steps, conversion problems, or misleading method signatures.
The Java argument type should also align with the placeholder. If the expression uses {int}, the method should accept int or Integer. If it uses {double}, the method should accept double or Double. Keeping placeholder type and Java type aligned avoids unnecessary confusion.
23. Common Mistake: Overusing Regex
Another common mistake is continuing to write Regex for simple values even when Cucumber Expressions provide a clean placeholder. For example:
@Given("^the amount is (\\d+)$")
public void amountIs(int amount) {
}
This can be replaced with:
@Given("the amount is {int}")
public void amountIs(int amount) {
}
Regex is still useful for advanced matching, but using it for ordinary strings and numbers makes the framework harder to read than necessary.
24. Best Practices for Cucumber Expressions
Keep Expressions Simple and Business-Readable
Prefer Cucumber Expressions over Regex for standard step definitions. Use {string} for quoted text, {word} for one unquoted word, {int} for whole numbers, and {double} or {bigdecimal} for decimal values depending on precision needs. Keep expressions close to business language and avoid exposing UI mechanics.
- Use {string} for values that may contain spaces.
- Use {word} only for one-word unquoted values.
- Use {int} for whole numbers.
- Use {double} or {bigdecimal} for decimal values.
- Keep parameter order aligned with method arguments.
- Avoid creating separate step definitions for simple value variations.
- Use Regex only when advanced matching is required.
Good expressions make scenarios flexible without making them vague. Parameterize data, but keep the business intent explicit.
25. Real-Time Example: Login, Cart, and Checkout
A realistic scenario may use several Cucumber Expression types:
Scenario: Customer places an order
Given the user logs in as "Customer"
And the user has 3 items in the cart
When the user applies coupon "SAVE10"
Then the order total should be 250.75
The step definitions may look like this:
@Given("the user logs in as {string}")
public void userLogsInAs(String role) {
loginService.loginAs(role);
}
@Given("the user has {int} items in the cart")
public void userHasItemsInCart(int count) {
cartService.addItems(count);
}
@When("the user applies coupon {string}")
public void userAppliesCoupon(String coupon) {
checkoutPage.applyCoupon(coupon);
}
@Then("the order total should be {double}")
public void orderTotalShouldBe(double total) {
orderAssertions.verifyTotal(total);
}
This example shows why Cucumber Expressions are practical. The steps remain readable, values are visible in the scenario, and Java receives typed parameters automatically.
26. Debugging Expression Problems
A Practical Checklist
If a step does not match, first check whether the placeholder expects quotes. {string} needs quoted text. {word} does not. Next, check whether the value contains spaces. If it does, use {string}. Then check numeric formats. A decimal value will not fit an {int} placeholder.
If the method receives the wrong value, inspect parameter order. The first placeholder maps to the first method parameter, the second placeholder maps to the second method parameter, and so on. If a step is ambiguous, search for another expression that can match the same sentence.
Debugging should start with the annotation pattern before changing automation logic. Many problems that look like Selenium or application failures are actually mapping problems.
27. Custom Parameter Types
When Built-In Placeholders Are Not Enough
Built-in Cucumber Expression placeholders cover many everyday needs, but real projects sometimes need domain-specific values. A banking project may use account types such as savings and current. An e-commerce project may use order IDs with a specific format. A trading application may use symbols, order sides, or market types. In these cases, a custom parameter type can keep the step readable while still enforcing or converting a meaningful domain value.
For example, instead of writing a complex Regex in every order-related step, a framework can define a reusable orderId parameter type and then write readable steps like this:
@Given("the order {orderId} exists")
public void orderExists(String orderId) {
orderService.load(orderId);
}
The complexity of matching the order ID can live in one place. The step definition remains readable. This is often a better long-term solution than scattering the same Regex pattern across many annotations. Custom parameter types are especially useful when the same strict value format appears repeatedly across the framework.
28. Cucumber Expressions vs Data Tables
Cucumber Expressions are excellent for small numbers of inline values. If a step needs one role, one count, one amount, or two credentials, placeholders keep the sentence readable. But if a scenario needs several rows or many related fields, a Data Table is usually clearer than a long expression.
Given the following products are in the cart
| Product | Quantity | Price |
| Laptop | 1 | 999.99 |
| Mouse | 2 | 25.50 |
The matching step definition can use one annotation and receive the table separately:
@Given("the following products are in the cart")
public void productsAreInTheCart(DataTable table) {
cartService.addProducts(table.asMaps());
}
This is cleaner than trying to squeeze product names, quantities, and prices into one long sentence. A practical rule is simple: use Cucumber Expressions for a few meaningful values, and use Data Tables for structured sets of related data. Both tools can coexist in the same framework.
29. Cucumber Expressions and Business Vocabulary
Parameterize Data, Not Intent
A common design mistake is making expressions too generic. A step like "When the user performs {string}" may look reusable, but it hides the business action. It forces the real meaning into data instead of the sentence. This weakens living documentation because the step no longer communicates behavior clearly.
A better expression keeps the intent visible:
@When("the user places the order")
public void userPlacesTheOrder() {
}
Values such as role, quantity, amount, status, or product name are good candidates for placeholders. The business action itself should usually remain explicit. In other words, parameterize data, not vague intent. This keeps feature files readable and prevents a step library from becoming a collection of generic catch-all methods.
30. Framework Review Checklist
When reviewing Cucumber Expressions in a framework, look for clarity, correct data types, and controlled reuse. A good expression should be easy to read as a sentence. It should capture only the values that need to vary. It should not be so broad that unrelated steps can match it. It should also align with the Java method signature.
- Does {string} have quoted text in the feature file?
- Is {word} used only for one-word unquoted values?
- Does {int}, {double}, or {bigdecimal} match the business data type?
- Are placeholders passed to Java parameters in the correct order?
- Would a Data Table be clearer than a long parameterized sentence?
- Is the expression business-readable instead of UI-driven?
- Should a repeated domain format become a custom parameter type?
This review discipline keeps Cucumber Expressions helpful as the number of scenarios grows. The goal is not only to make steps execute. The goal is to keep mappings understandable for the whole team.
31. Cucumber Expressions in CI and Reports
Clean Cucumber Expressions also improve CI output and reports. When a scenario fails, the report shows the Gherkin step text. If the step text is readable and the expression captures values clearly, the failure is easier to understand. A failed step such as "Then the order total should be 250.75" gives useful information immediately. A vague step such as "Then the value should be correct" does not.
CI failures are often reviewed by people who did not write the step definition. Good expression design helps them understand what was being tested without opening Java code. This is part of the value of BDD: the same scenario can guide development, automation, debugging, and reporting.
32. Interview-Ready Summary
Short Explanation for Interviews
Cucumber Expressions are the modern way to parameterize step definitions in Cucumber JVM. They replace most Regular Expressions with simple placeholders such as {string}, {int}, {double}, {float}, and {word}. Cucumber automatically extracts values from Gherkin steps, converts them to the matching Java types, and passes them into the step definition method.
{string} captures quoted text, {int} captures whole numbers, {double} captures decimal values, and {word} captures a single unquoted word. Cucumber Expressions improve readability, reduce Regex complexity, and make step definitions easier to maintain. Regex should be reserved for advanced matching or strict format validation.
- Cucumber Expressions connect Gherkin steps to Java methods with readable placeholders.
- {string} is used for quoted text and multi-word values.
- {int} is used for whole-number values.
- {double} and {float} are used for decimal values.
- {word} captures only one unquoted word.
- Parameter order in the expression must match method argument order.
33. Golden Rule
The golden rule is simple: use Cucumber Expressions to keep step definitions readable, typed, and business-friendly. Use the placeholder that matches the data in the feature file, keep parameter order clear, and switch to Regex only when the matching requirement is too complex for a clean Cucumber Expression.
When Cucumber Expressions are used well, feature files stay readable, Java code receives clean typed values, and the framework becomes easier for the whole team to understand and maintain.