Skip to content

behave-pool

Parallel test execution for Behave BDD via native ITestRunner. Workers run in isolated processes with the spawn start method for clean interpreter state on every platform.

Why behave-pool?

Standard Behave runs all features sequentially in a single process. As test suites grow, wall-clock time becomes a bottleneck. behave-pool solves this by:

  • Splitting features across N worker processes that run in parallel.
  • Using the spawn start method so every worker gets a clean interpreter state — no inherited global registries, no fork-related bugs on Linux.
  • Providing LPT load balancing so the slowest features start first, minimizing total wall-clock time.
  • Supporting @serial tags for scenarios that cannot run in parallel (database migrations, shared resources, etc.).

Features

  • Native ITestRunner — Registered via --runner= or behave.ini. Zero monkey-patching.
  • Process isolationspawn start method ensures clean state in every worker, on every OS.
  • Dynamic dispatchmultiprocessing.Process + Queue. Workers consume work units as they finish.
  • @serial tag — Non-parallelizable scenarios run sequentially after the parallel phase.
  • LPT load balancing — Historical durations for optimal work distribution.
  • Timing persistence.behave-pool-timing.json stores durations between runs.
  • Unified JSON report — Merges all worker reports into a single behave-modern-json-report ExecutionReport (schema v1.1.0) with statistics, environment info, and full feature/scenario/step details.
  • Ecosystem integration — Optional behave-priority, behave-modern-json-report. The unified report is directly consumable by any tool in the ecosystem.
  • Zero heavy dependencies — Only stdlib multiprocessing + behave>=1.3.0.

Quick start

pip install behave-pool

Register the runner in behave.ini:

[behave.runners]
parallel = behave_pool:ParallelRunner

Run Behave with parallel workers:

behave --runner=parallel --parallel 4 --parallel-scheme feature features/

How it works

┌─────────────────────────────────────────────────┐
│                  ParallelRunner                  │
│                                                  │
│  1. Plan    — parse features, create work units  │
│  2. Split   — separate @serial from parallel     │
│  3. Dispatch — N workers consume from queue      │
│  4. Collect — gather results, update timings     │
│  5. Serial  — run @serial units one at a time    │
└─────────────────────────────────────────────────┘
         │                          │
    ┌────▼────┐               ┌────▼────┐
    │ Worker 0 │               │ Worker N │
    │ (spawn)  │    ...        │ (spawn)  │
    │          │               │          │
    │ parse    │               │ parse    │
    │ features │               │ features │
    │ run      │               │ run      │
    │ report   │               │ report   │
    └──────────┘               └──────────┘

When --parallel is 1, the runner falls back to standard sequential Behave execution with no overhead.

Requirements

  • Python >=3.11
  • behave >=1.3.0

Documentation