Skip to main content

behave-steplib

Reusable step libraries for Behave BDD — share, discover and install step definitions across projects. Zero mandatory dependencies; each technology is an optional extra.

CI Release PyPI Python 3.11+ License: MIT

Why behave-steplib?

Writing BDD step definitions for HTTP APIs, web browsers, databases and Kafka is repetitive. Every project re-implements the same "send a request", "check the status code", "query the database" steps. behave-steplib provides a curated, typed, multilingual library of reusable steps that you install once and share across projects.

  • Modular — api, web, db, kafka, data, io, cli modules activated via extras and lazy imports. Install only what you need.
  • Auto-registered — autoload(context) discovers every installed step via Python entry points and registers it with behave in one line.
  • Multilingual — steps defined in English with es and pt translations; all patterns are registered with behave so matching works regardless of the language used in feature files.
  • Typed — full type hints, mypy --strict clean, py.typed marker included.
  • CLI — steplib list / show / search / validate / init / install powered by Typer for inspecting and validating your step library from the terminal. Also available as behave-steplib.
  • Pluggable — third-party packages can register steps via the steplib.plugins entry point group; autoload discovers them automatically.
  • Ecosystem — integrates with behave-kit (soft assertions), behave-tables (table conversion) and behave-data (test data loading) when installed.
  • Backends — each module supports multiple backends (e.g. stdlib/httpx/requests for API, selenium for web) selectable at autoload time.

Installation

pip install behave-steplib            # core only (behave, parse, typer)
pip install behave-steplib[api]       # + httpx HTTP client
pip install behave-steplib[requests]  # + requests HTTP client
pip install "behave-steplib[api,requests,web,db,kafka,data,io]"  # + all technology extras
pip install "behave-steplib[all]"     # + every technology extra
pip install behave-steplib[dev]       # + pytest, ruff, mypy, build, twine
Extra Packages Description
[api] httpx HTTP API testing with httpx
[requests] requests HTTP API testing with requests
[web] selenium Browser testing with Selenium
[db] sqlalchemy Database testing with SQLAlchemy
[kafka] kafka-python-ng Kafka producer/consumer testing
[io] jsonschema File, JSON, CSV and directory operations
[cli] — Shell command execution and assertions
[kit] behave-kit Soft assertions, typed context, fixtures
[data] behave-data Test data loading (CSV, JSON, YAML, Excel)
[tables] behave-tables Table conversion helpers
[dev] pytest, ruff, mypy, build, twine Development tools
[docs] sphinx, furo, myst-parser, sphinx-autodoc-typehints Documentation tools
[all] api, requests, web, db, kafka, kit, data, tables, io Everything except dev/docs

Requirements

  • Python 3.11+ (tested on CPython 3.11, 3.12, 3.13 and 3.14)
  • behave — the only mandatory runtime dependency alongside parse and typer

Quickstart

Level 1 — Automatic wiring

Add three hooks to your environment.py and every installed step is wired automatically:

# features/environment.py
from steplib.behave import autoload


def before_all(context):
    context.steplib = autoload(context)


def before_scenario(context, scenario):
    context.steplib.reset()


def after_scenario(context, scenario):
    context.steplib.cleanup()

Or generate it with the CLI:

steplib init

Level 2 — Explicit load

Load only the modules you need by dotted path:

from steplib.behave import load


def before_all(context):
    context.steplib = load(context, "steplib.modules.api.steps")

Level 3 — Filtered autoload

When multiple extras are installed, narrow which steps are active:

from steplib.behave import autoload


def before_all(context):
    context.steplib = autoload(
        context,
        categories=["api"],
        backends={"api": "httpx"},
    )

Example feature

Feature: API health check

  Scenario: GET users returns 200
    Given the API base url is "https://api.example.com"
    When I send a GET request to "/users"
    Then the response status is 200
    And the response body is valid JSON
    And the JSON path "$.users[0].name" equals "Ada"

Multilingual features

Steps are defined in English and translated to Spanish and Portuguese. All patterns are registered with behave — no language switch needed:

# es
Cuando envío una petición GET a "/users"
Entonces el estado de la respuesta es 200

# pt
Quando envio uma requisição GET para "/users"
Então o status da resposta é 200

Modules

API

HTTP API testing with stdlib (urllib), httpx or requests backends. 54 steps covering configuration, authentication, SSL/redirects, requests (body, form, JSON, query params, headers), status/body/JSON Path/header/response-time assertions, store/extract, variable reuse and table comparison.

Given the API base url is "https://api.example.com"
And I set the bearer token to "eyJhbGciOi..."
When I send a POST request with JSON body to "/users"
  """
  {"name": "Ada", "email": "ada@example.com"}
  """
Then the response status is 201
And the JSON path "$.id" is not null
And the response time is less than 5 seconds
And I store the JSON path "$.id" as "user_id"

Web

Browser testing with Selenium (Chrome, Firefox, headless). 34 steps covering configuration, navigation, interactions (click, type, clear, select, screenshot), waits, assertions (title, URL, element presence/visibility/enabled/text/attribute, page content), cookies, frame switching and store/extract.

Given the web base url is "https://example.com"
When I navigate to "/login"
And I type "admin" into the element id "username"
And I type "secret" into the element id "password"
And I click the element id "submit"
Then the page title is "Dashboard"
And the element id "welcome" is visible
And I store the text of element id "username" as "displayed_name"

DB

Database testing with SQLAlchemy (SQLite, PostgreSQL, MySQL, ...). 22 steps covering connection management, query execution (with bind parameters), row count assertions, column assertions (equals, not equals, contains, null, not null), scalar queries, table assertions, transactions and store/extract.

Given the database connection string is "sqlite:///test.db"
When I connect to the database
And I execute the SQL query "SELECT * FROM users" without bind parameters
Then the query returns 3 rows
And the column "name" in the first row equals "Ada"
And the column "email" in the first row contains "@"
And I store the column "id" from the first row as "user_id"

Kafka

Kafka producer and consumer testing with kafka-python-ng. 20 steps covering bootstrap/group/offset configuration, producer/consumer config overrides, message production (single, JSON, batch from table), consumption (with optional timeout), assertions (count, contains, key/value by index, regex, order) and store/extract.

Given the Kafka bootstrap servers are "localhost:9092"
And the Kafka consumer group is "test-group"
When I produce a message to topic "events" with key "id" and value "hello"
And I consume messages from topic "events" using a timeout of 10000 ms
Then the consumed messages count is 1
And the message at index 0 has value "hello"
And I store the message count as "total_messages"

Data

Generic variable management and environment variable handling — cross-module variable store, file loading (JSON/YAML), dot-path extraction, scenario-safe env var modifications, regex/string assertions, numeric comparisons, and a wait utility. 32 steps covering variable set/assert/delete/copy/clear, JSON parsing, file loading, key-path extraction, regex match, starts/ends with, increment, greater/less than, full environment variable lifecycle, and sleep.

Given I set the variable "user_id" to "42"
Then the variable "user_id" equals "42"
And the variable "user_id" has length 2
When I load the JSON file "data/user.json" and store it in the variable "user"
And I extract the key path "address.city" from the variable "user" as "city"
Then the variable "city" equals "Berlin"
And the variable "email" matches the pattern ".*@.*\..*"
When I increment the variable "counter" by 1
Then the variable "counter" is greater than 0
When I wait for 0.5 seconds
Given I set the environment variable "API_KEY" to "secret123"
Then the environment variable "API_KEY" exists
When I store the environment variable "API_KEY" as "api_key"

IO

File, JSON, CSV and directory operations with optional JSON Schema validation. 38 steps covering file CRUD (read, write, append, delete, copy, move, rename, create empty), file assertions (exists, not exists, same, size, extension), JSON operations (load, save, path get/set/delete, validity, schema match, diff, merge, type check), CSV operations (create, write row, save, header row), directory operations (create, exists, not exists, list, delete) and read file as lines.

Given I create the directory "output/logs"
When I write "hello" to the file "output/logs/test.txt"
Then the file "output/logs/test.txt" exists
When I read the file "output/logs/test.txt" as lines into "lines"
Then the variable "lines" has length 1
Given I load the JSON file "data/config.json" as the last JSON
Then the JSON key path "version" equals "1.0"
And the JSON matches the schema "schemas/config.json"
And the last JSON is valid
When I create the CSV file "output/data.csv" from the data '[{"name":"Alice","age":30}]'
Then the directory "output" exists
When I delete the directory "output"
Then the directory "output" does not exist

CLI

Shell command execution with subprocess, capturing exit code, stdout and stderr. 10 steps covering command execution (with optional timeout), exit code assertions, stdout assertions (contains, not contains, equals, matches pattern), stderr assertions, and storing output (stdout and stderr) into variables.

When I run the command "echo hello" using the default timeout
Then the command exit code equals 0
And the command output contains "hello"
And the command output does not contain "error"
And the command output matches the pattern "hell."
When I store the command output as "result"
Then the variable "result" contains "hello"
When I run the command "echo error 1>&2" using a timeout of 10 seconds
And I store the command error output as "errors"
Then the command error output contains "error"

CLI

steplib list                         # list all registered steps
steplib list --category api          # filter by category
steplib list --backend httpx         # filter by backend
steplib list --tag smoke             # filter by tag
steplib list --json                  # output as JSON

steplib search "send a request"      # search by partial pattern (case-insensitive)
steplib search --category api        # search within a category
steplib search --backend httpx       # search within a backend
steplib search --tag http --json     # search by tag with JSON output

steplib show "I send a {method} request to {url}"
steplib show "I send a {method} request to {url}" --json

steplib validate                     # validate step contracts
steplib validate --json              # output as JSON: {"valid": true, "errors": []}

steplib init                         # generate features/environment.py
steplib init --path custom/env.py    # custom output path
steplib init --json                  # output as JSON: {"created": true, "path": "..."}

steplib install                      # informative message (use pip instead)
steplib install api                  # suggests: pip install behave-steplib[api]

Both steplib and behave-steplib are installed as console commands and accept the same subcommands: list, show, search, validate, init, install.

JSON output schema

All commands support --json for machine-readable output:

Command Schema
list --json [{ "pattern", "category", "backend", "description", "module", "tags", "version", "deprecated", "example", "i18n" }]
search --json Same as list --json
show --json { "pattern", "category", "backend", "description", "module", "function", "example", "tags", "version", "deprecated", "requires", "i18n", "parameters" }
validate --json { "valid": bool, "errors": [str] }
init --json { "created": bool, "path": str }

install — not a steplib command

behave-steplib does not install packages. Use pip directly to install extras:

pip install behave-steplib[api]      # install the api extra (httpx)
pip install behave-steplib[all]      # install all technology extras

Running steplib install prints an informative message with the correct pip command.

Writing custom steps

Use the @step decorator to define your own steps with full metadata:

from steplib import Param, step


@step(
    "the invoice total is {total:f}",
    category="invoice",
    description="Assert the invoice total matches.",
    parameters=[Param("total", type=float, required=True)],
    example="Then the invoice total is 19.99",
    i18n={
        "es": "el total de la factura es {total:f}",
        "pt": "o total da fatura é {total:f}",
    },
    tags=["invoice"],
    version="1.0.0",
)
def step_invoice_total(context, total):
    assert context.invoice.total == total

Register steps in a register(registry) function and declare an entry point:

# pyproject.toml
[project.entry-points."steplib.plugins"]
mycompany = "mycompany.steps:register"

Once installed, autoload(context) discovers your package automatically.

Development

make dev        # install with api, requests, dev and docs extras
make lint       # ruff + mypy --strict
make test-cov   # pytest with >=80% coverage gate
make docs-build # build Sphinx documentation
make build      # build sdist + wheel

Documentation

Full documentation is available at https://mathiaspaulenko.github.io/behave-steplib.

Acknowledgements

  • Behave — the BDD framework this library extends.
  • parse — pattern matching for step definitions.
  • Typer — CLI framework.
  • Sphinx + furo — documentation.

License

MIT — see LICENSE.

Metadata

Release files for behave-steplib 1.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for behave-steplib 1.6.0
File Size Uploaded
behave_steplib-1.6.0.tar.gz 165.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for behave-steplib 1.6.0
File Interpreter ABI Platform
behave_steplib-1.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 266.2 kB

Release files / behave_steplib-1.6.0.tar.gz

Download URL behave_steplib-1.6.0.tar.gz
Size 165.8 kB
Tags Source
SHA-256 checksum
How to use checksums
11bb97ef508dc765007b5a56129e0e5daf8ec1d892fea0ef29f489f81a708b23
BLAKE2b-256 checksum
How to use checksums
bb0852fcfd5718874c80071b915a63632f0b0ad28b155119ce7441ab3db23615
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / behave_steplib-1.6.0-py3-none-any.whl

Download URL behave_steplib-1.6.0-py3-none-any.whl
Size 100.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1adcdde27d00d8c7eb41886f4a8bfb72ed7ec2e84f281c90745e2420f659fa7e
BLAKE2b-256 checksum
How to use checksums
47c10c105d28554e04ad91df5929d189ff1d93433e37551496dc3ef215f313c7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.6.0 This release

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.0

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page