Architecture
behave-runner is a thin CLI and orchestration layer on top of the
BehaveLib ecosystem. It does not reimplement the behavior logic of any
library; it translates user flags into the right sequence of calls and
gracefully degrades when optional dependencies are missing.
Overview
The architecture has three layers:
- CLI —
Typerparses the user input and dispatches to one of the command modules inbehave_runner.commands. - Orchestrator —
behave_runner.corecollects configuration, resolves optional extras, merges config files with CLI flags, and builds the finalbehaveinvocation. - Backends — the actual runner libraries (
behave,behave-pool,behave-priority, etc.) execute the tests.
Orchestrator flow
For the run command, the orchestrator performs the following steps:
- Parse CLI flags into
RunConfig. - Load the base config from
pyproject.tomlorbehave.ini. - If a
--profileis selected, merge the profile values. - For each optional flag, check whether the required extra is installed.
- If missing, print a warning and degrade gracefully.
- Build the final
behavecommand list with appropriate flags and environment variables. - Execute the command via
subprocess.run, passing environment variables for features handled by optional extras (retries, priority, sharding, scenario timeout). - Return the same exit code as the underlying behave process.
Component diagram
┌─────────────────────────────────────────────────────────┐
│ behave-runner CLI │
│ (Typer + Rich) │
│ │
│ ┌──────┐ ┌───────┐ ┌───────┐ ┌──────┐ ┌──────┐ │
│ │ run │ │ watch │ │ list │ │select│ │ lint │ ... │
│ └──┬───┘ └───┬───┘ └───┬───┘ └──┬───┘ └──┬───┘ │
│ │ │ │ │ │ │
│ ┌──┴─────────┴─────────┴────────┴────────┴────────┐ │
│ │ Orchestrator (core) │ │
│ │ - Build behave command │ │
│ │ - Merge config and CLI flags │ │
│ │ - Check optional dependencies │ │
│ │ - Manage output directory │ │
│ └────────────────────┬─────────────────────────────┘ │
│ │ │
└───────────────────────┼──────────────────────────────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ behave │ │ behave- │ │ behave- │
│ (native) │ │ pool │ │priority │
└──────────┘ └──────────┘ └──────────┘
│ │ │
┌──────────┐ ┌──────────┐ ┌──────────┐
│ behave- │ │ behave- │ │ behave- │
│ retry │ │ trace │ │ kit │
└──────────┘ └──────────┘ └──────────┘
│ │ │
┌──────────┐ ┌──────────┐ ┌──────────┐
│ behave- │ │ behave- │ │ behave- │
│ model │ │ doctor │ │ gen │
└──────────┘ └──────────┘ └──────────┘
│ │ │
┌──────────┐ ┌──────────┐ ┌──────────┐
│ behave- │ │ behave- │ │ behave- │
│ lint │ │ format │ │ steplib │
└──────────┘ └──────────┘ └──────────┘
│ │ │
┌──────────┐ ┌──────────┐ ┌──────────┐
│ behave- │ │ behave- │ │ wavexis │
│ comments │ │ tables │ │ │
└──────────┘ └──────────┘ └──────────┘
│
┌─────────────────────────────────┐
│ behave-modern-*-report (x6) │
│ console / html / md / json / │
│ sheets / file │
└─────────────────────────────────┘
Core modules
| Module | Responsibility |
|---|---|
cli/app.py |
Register CLI commands and the main entry point. |
core/orchestrator.py |
Build and execute the final behave command. |
core/config.py |
Load config files and profiles. |
core/deps.py |
Check optional extras gracefully. |
core/output.py |
Manage output directories. |
core/watcher.py |
File watcher for the watch command. |
core/features.py |
Parse feature files and collect scenarios. |
utils.py |
Project root discovery and browser opening. |
exceptions.py |
Custom exceptions. |
Design principles
- Orchestrator, not implementor: every feature is delegated.
- Optional extras: missing libraries are a warning, not a crash.
- One command to rule them all:
runaccepts flags from every library. - Consistent output:
richpowers tables, colors, and progress messages. - Python only: no Node build steps.
Exit codes
behave-runner propagates the exit code of the underlying command:
| Code | Meaning |
|---|---|
0 |
Success. |
1 |
Test failures or tool errors. |
2 |
Missing base behave or a configuration error. |