Step Contract¶
A behave-steplib step is a regular Python function decorated with
@steplib.step. The decorator attaches structured metadata
(StepInfo) used for documentation, validation
and the CLI, while delegating to behave’s native step registration under the
hood.
Design principles¶
Cohesive — a step does one action or one assertion.
Pure logic — the implementation delegates to action functions; it contains no selectors, queries or protocol details.
Parameterisable — every relevant constant enters via the pattern or
context.config.userdata.
The @step decorator¶
from steplib import Param, step
@step(
"I send a {method} request to {url}",
category="api",
backend="httpx",
description="Send an HTTP request and store the response.",
parameters=[
Param("method", type=str, required=True, default="GET",
description="HTTP method (GET, POST, PUT, PATCH, DELETE)."),
Param("url", type=str, required=True,
description="Request URL (relative URLs resolve against base_url)."),
],
example='When I send a GET request to "/users"',
i18n={
"es": "envío una petición {method} a {url}",
"pt": "envio uma requisição {method} para {url}",
},
tags=["api", "http"],
version="1.0.0",
)
def step_send_request(context, method, url):
...
Stacked decorators¶
The same step can expose multiple patterns (one per language or per backend)
by applying the decorator multiple times on the same function. Each call
generates an independent StepInfo entry while
sharing the implementation:
@step("I send a {method} request to {url}", backend="httpx", category="api")
@step("I send a {method} request to {url}", backend="requests", category="api")
def step_send_request(context, method, url):
...
When declaring multiple backends for the same concept, use backend to
differentiate them and let autoload filter the active variant.
Metadata fields¶
Field |
Required |
Description |
|---|---|---|
|
Yes |
Matching pattern for behave ( |
|
Yes |
Module or domain: |
|
Recommended |
Human-readable explanation. Defaults to the function docstring. |
|
Optional |
List of typed |
|
Recommended |
Example usage in Gherkin. |
|
Optional |
Tags for grouping and filtering in the CLI. |
|
Optional |
Semantic version of the step. |
|
Optional |
|
|
Optional |
Underlying technology: |
|
Optional |
Translations of the pattern keyed by language code. |
|
Optional |
Context attributes the step needs (e.g. |
Parameter types (Param)¶
from steplib.core import Param
Param(
name="method",
type=str, # or a registered type name like "HttpMethod"
required=True,
default="GET",
description="HTTP method (GET, POST, PUT, PATCH, DELETE).",
choices=["GET", "POST", "PUT", "PATCH", "DELETE"],
)
Built-in type names usable in patterns:
Name |
Python type |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Registering custom types¶
from steplib.core import register_type
register_type("Json", str) # register a custom type name
Custom types are resolved by resolve_type() when
validating parameter declarations.
Step function signature¶
The decorated function receives context followed by the parameters
extracted from the pattern, in the order they appear:
@step("I wait {seconds:d} seconds")
def step_wait(context, seconds):
...
Optional parameters with defaults that do not appear in the pattern are injected as keyword arguments:
@step("I wait a bit")
def step_wait_default(context, seconds=1):
...
Context namespaces¶
Steps operate on context.steplib. Each module reserves a namespace:
Namespace |
Class |
Module |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Module namespaces are created lazily by each module’s _get_* helper on
first use, and reset/closed by SteplibState
lifecycle methods.
Ecosystem integration¶
Steps can leverage existing ecosystem libraries without duplicating functionality:
``behave-kit`` — soft assertions, typed context,
env, fixtures,assert_json_equals.``behave-tables`` — convert
context.tableto dicts, columns, models.``behave-data`` — load test data from CSV / JSON / YAML / Excel.
from behave_kit import assert_soft
from behave_tables import wrap
from steplib import step
@step("the users should be", category="example")
def step_check_users(context):
expected = wrap(context.table).as_dicts()
actual = context.steplib.api.last_response.json()
for exp, act in zip(expected, actual, strict=False):
assert_soft(exp == act)
Validation¶
steplib validate checks:
Each
patternis parseable byparse.Declared
Paramnames match pattern placeholders.No duplicate patterns within the same backend.
i18ntranslations have the same placeholders as the base pattern.Stacked patterns share the same placeholders and order.
Each step has a
category.
API reference¶
See Core API Reference for the full autodoc reference of steplib.core.decorators,
steplib.core.metadata and steplib.core.params.