Multi-language library providing Cucumber Expressions as a simpler alternative to regular expressions for BDD step definition matching
pkg:github/cucumber/cucumber-expressions@18.0.x
npx @tessl/cli install tessl/github-cucumber-expressions@18.0.0Cucumber Expressions is a multi-language library providing a simpler alternative to Regular Expressions for matching step definitions with Gherkin steps in Behavior-Driven Development (BDD) testing. It offers an intuitive syntax using parameter types like {int}, {float}, {string}, and {word}, supports optional text with parentheses and alternative text with forward slashes, and includes advanced features like custom parameter types and expression generation.
JavaScript/TypeScript (npm):
npm install @cucumber/cucumber-expressionsPython (PyPI):
pip install cucumber-expressionsJava (Maven):
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-expressions</artifactId>
<version>18.0.1</version>
</dependency>Ruby (Gem):
gem install cucumber-cucumber-expressionsGo (Module):
go get github.com/cucumber/cucumber-expressions/go/v18.NET (NuGet):
dotnet add package Cucumber.CucumberExpressionsJavaScript/TypeScript:
import { CucumberExpression, ParameterTypeRegistry, ExpressionFactory } from '@cucumber/cucumber-expressions';Python:
from cucumber_expressions import CucumberExpression, ParameterTypeRegistry, CucumberExpressionGeneratorJava:
import io.cucumber.cucumberexpressions.CucumberExpression;
import io.cucumber.cucumberexpressions.ParameterTypeRegistry;
import io.cucumber.cucumberexpressions.ExpressionFactory;import { CucumberExpression, ParameterTypeRegistry } from '@cucumber/cucumber-expressions';
// Create parameter type registry with built-in types
const registry = new ParameterTypeRegistry();
// Create a Cucumber Expression
const expression = new CucumberExpression('I have {int} cucumber(s) in my belly', registry);
// Match text against the expression
const args = expression.match('I have 42 cucumbers in my belly');
if (args) {
console.log(args[0].getValue()); // 42 (as number)
}
// Expression with different parameter types
const floatExpr = new CucumberExpression('I have {float} cucumbers in my belly', registry);
const floatArgs = floatExpr.match('I have 42.5 cucumbers in my belly');
if (floatArgs) {
console.log(floatArgs[0].getValue()); // 42.5 (as number)
}Cucumber Expressions is built around several key components:
The library uses a grammar-based parser to convert expressions like I have {int} cucumber(s) into regular expressions with appropriate capture groups, enabling type-safe parameter extraction.
All implementations support these built-in parameter types:
| Parameter Type | Description | Example Match | Converted Type |
|---|---|---|---|
{int} | 32-bit signed integers | 42, -19 | Integer |
{float} | 32-bit floating point | 3.6, .8, -9.2 | Float |
{word} | Single word (no whitespace) | banana | String |
{string} | Quoted strings | "banana split", 'hello' | String (without quotes) |
{bigdecimal} | High-precision decimals | 123.456789 | BigDecimal/Decimal |
{double} | 64-bit floating point | 3.14159 | Double |
{biginteger} | Arbitrary precision integers | 12345678901234567890 | BigInteger |
{byte} | 8-bit signed integer | 127, -128 | Byte |
{short} | 16-bit signed integer | 32767 | Short |
{long} | 64-bit signed integer | 9223372036854775807 | Long |
{} (anonymous) | Matches anything | anything | String (varies by language) |
Core functionality for parsing Cucumber expressions and matching them against text, with support for parameter extraction and type conversion.
class CucumberExpression implements Expression {
constructor(expression: string, parameterTypeRegistry: ParameterTypeRegistry);
match(text: string): readonly Argument[] | null;
readonly source: string;
readonly regexp: RegExp;
readonly ast: Node;
}
interface Expression {
readonly source: string;
match(text: string): readonly Argument[] | null;
}JavaScript/TypeScript Implementation
Comprehensive parameter type system with built-in types and support for custom parameter types with regex patterns and transformation functions.
class ParameterType<T> {
constructor(
name: string | undefined,
regexps: RegExps,
type: Constructor<T> | Factory<T> | null,
transform?: (...match: string[]) => T | PromiseLike<T>,
useForSnippets?: boolean,
preferForRegexpMatch?: boolean
);
readonly name: string | undefined;
readonly regexpStrings: readonly string[];
transform(thisObj: unknown, groupValues: string[] | null): T;
}
class ParameterTypeRegistry implements DefinesParameterType {
constructor();
defineParameterType(parameterType: ParameterType<unknown>): void;
lookupByTypeName(typeName: string): ParameterType<unknown> | undefined;
lookupByRegexp(parameterTypeRegexp: string, expressionRegexp: RegExp, text: string): ParameterType<unknown> | undefined;
}Factory pattern for creating expressions and generator for creating expressions from example text, useful for step definition creation.
class ExpressionFactory {
constructor(parameterTypeRegistry: ParameterTypeRegistry);
createExpression(expression: string | RegExp): Expression;
}
class CucumberExpressionGenerator {
constructor(parameterTypes: () => Iterable<ParameterType<unknown>>);
generateExpressions(text: string): readonly GeneratedExpression[];
}
class GeneratedExpression {
constructor(expressionTemplate: string, parameterTypes: readonly ParameterType<unknown>[]);
readonly source: string;
readonly parameterNames: readonly string[];
readonly parameterInfos: readonly ParameterInfo[];
}Expression Factory and Generation
Complete Python implementation with Pythonic API patterns, built-in parameter types, and full feature compatibility.
class CucumberExpression:
def __init__(self, expression: str, parameter_type_registry: ParameterTypeRegistry): ...
def match(self, text: str) -> Optional[List[Argument]]: ...
@property
def source(self) -> str: ...
class ParameterType:
def __init__(
self,
name: Optional[str],
regexp: Union[List[str], str, List[Pattern], Pattern],
type: type,
transformer: Optional[Callable] = None,
use_for_snippets: bool = True,
prefer_for_regexp_match: bool = False
): ...Enterprise-grade Java implementation with strong typing, comprehensive built-in types, and extensive configuration options.
public final class CucumberExpression implements Expression {
public CucumberExpression(String expression, ParameterTypeRegistry parameterTypeRegistry);
public List<Argument<?>> match(String text, Type... typeHints);
public String getSource();
public Pattern getRegexp();
}
public final class ParameterType<T> implements Comparable<ParameterType<?>> {
public ParameterType(String name, List<String> regexps, Class<T> type, CaptureGroupTransformer<T> transformer);
public T transform(List<String> groupValues);
public String getName();
public List<String> getRegexps();
}Support for Ruby, Go, and .NET implementations with language-specific patterns and conventions while maintaining API compatibility.
Ruby Implementation
Go Implementation
.NET Implementation
interface Argument {
readonly group: Group;
readonly parameterType: ParameterType<unknown>;
getValue<T>(thisObj: unknown): T | null;
getParameterType(): ParameterType<unknown>;
}
interface GeneratedExpression {
readonly source: string;
readonly parameterNames: readonly string[];
readonly parameterInfos: readonly ParameterInfo[];
readonly parameterTypes: readonly ParameterType<unknown>[];
}
interface ParameterInfo {
type: string | null;
name: string;
count: number;
}
interface Group {
value: string | null;
start: number;
end: number;
children: Group[];
}
interface Node {
type: NodeType;
nodes?: Node[];
token?: Token;
text(): string;
}
enum NodeType {
text = 'text',
optional = 'optional',
alternation = 'alternation',
alternative = 'alternative',
parameter = 'parameter',
expression = 'expression'
}Cucumber Expressions support several powerful syntax features:
Use curly braces to define typed parameters:
I have {int} cucumbers - matches integersI have {float} cucumbers - matches floating point numbersI have {string} cucumbers - matches quoted stringsI have {word} cucumbers - matches single wordsUse parentheses for optional text:
I have {int} cucumber(s) - matches both "cucumber" and "cucumbers"Use forward slashes for alternatives:
I have {int} cucumber(s) in my belly/stomach - matches either "belly" or "stomach"Escape special characters with backslashes:
I have {int} \\{what} cucumber(s) - matches literal {what}I have {int} cucumber(s) \\(amazing!) - matches literal (amazing!)Use empty braces for catch-all matching:
I have {} cucumbers - matches any text