Skip to main content

behave-format

CI Docs PyPI Python License

The opinionated formatter for Behave .feature files.

Black is for Python. gofmt is for Go. behave-format is for Gherkin.

Documentation: https://mathiaspaulenko.github.io/behave-format/


Overview

behave-format is a deterministic, opinionated formatter for Behave .feature files. It consumes the canonical domain model from behave-model and produces clean, consistent, beautifully formatted output.

Key principle: behave-format does NOT parse Gherkin. It does NOT lint. It does NOT validate. It ONLY transforms a behave-model.Project into formatted .feature files.

.feature files → behave-model (domain model) → behave-format → formatted .feature files

Features

  • Opinionated — minimal configuration, sensible defaults
  • Deterministic — same input always produces same output
  • Idempotent — format(format(x)) == format(x)
  • Fast — handles thousands of feature files efficiently
  • CI-friendly — --check mode with exit code 1 when formatting is needed
  • Safe — never changes semantics (names, step text, table values, docstrings)

Installation

pip install behave-format

Quick Start

CLI

# Format files in place (default)
behave-format features/

# Check mode (CI) — exit 1 if formatting is needed
behave-format --check features/

# Diff mode — show differences without writing
behave-format --diff features/

Python API

from behave_model import load_project
from behave_format import format_project, render_project, Settings

project = load_project("features/")

# Format the project model in place
format_project(project)

# Or render to text
text = render_project(project, Settings())

Formatting Rules

Tags

Tags are sorted alphabetically by default:

@api @smoke

Features

  • One blank line before each Feature
  • Clean title formatting

Scenarios

  • One blank line before each Scenario
  • Two-space indentation for steps
  Given user exists
  When user logs in
  Then dashboard is shown

Tables

Tables are always aligned:

Before:

|user|password|
|john|123|

After:

| user | password |
| john | 123      |

Blank Lines

  • No trailing blank lines
  • No multiple consecutive empty lines
  • Consistent spacing between blocks

Indentation

  • Spaces only (no tabs)
  • Default: 2 spaces

Configuration

Minimal configuration via pyproject.toml:

[tool.behave-format]
indent = 2
sort_tags = true
sort_features = false
sort_scenarios = false
line_length = 120
Option Default Description
indent 2 Number of spaces for indentation
sort_tags true Sort tags alphabetically
sort_features false Sort features by name
sort_scenarios false Sort scenarios by name
line_length 120 Maximum line length — wraps long tag lines

Before / After

Before

@smoke @auth
Feature: Login
  As a user
  I want to log in

  Background:
    Given a database connection

  @happy
  Scenario: Successful login
    Given the user is on the login page
    When the user enters "admin" and "password"
    Then the user should be logged in

After

@auth @smoke
Feature: Login
  As a user
  I want to log in

  Background:
    Given a database connection

  @happy
  Scenario: Successful login
    Given the user is on the login page
    When the user enters "admin" and "password"
    Then the user should be logged in

Architecture

behave_format/
├── config/
│   └── settings.py        # Settings dataclass + pyproject.toml loader
├── loader.py              # Parse via behave-model + restore comments/keywords
├── pipeline/
│   ├── normalize.py       # Whitespace, indentation, tag normalization
│   ├── sort.py            # Sort tags, features, scenarios
│   ├── align.py           # Table alignment, trailing whitespace
│   └── formatter.py       # Main orchestrator (format_project)
├── printer/
│   ├── feature_printer.py
│   ├── scenario_printer.py
│   ├── step_printer.py
│   ├── table_printer.py
│   └── tag_printer.py
└── cli/
    └── main.py            # CLI entry point

Pipeline

  1. Normalize — clean whitespace, standardize indentation, normalize tags
  2. Sort — order tags (alphabetically by default), optionally features and scenarios
  3. Align — align table columns, remove trailing spaces
  4. Print — convert behave-model → .feature text (deterministic)

Safety

The formatter NEVER changes semantics:

  • Feature names: preserved
  • Scenario names: preserved
  • Step text: preserved (only whitespace normalized)
  • DocString content: preserved
  • Table values: preserved (only alignment changes)
  • Comments content: preserved

Integration

behave-format integrates naturally with the Behave ecosystem:

Development

pip install -e ".[dev]"
pytest tests/ -v
ruff check .
ruff format --check .

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Run ruff check . and pytest tests/ before submitting
  4. Open a Pull Request

License

MIT

Metadata

Release files for behave-format 1.2.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-format 1.2.0
File Size Uploaded
behave_format-1.2.0.tar.gz 45.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for behave-format 1.2.0
File Interpreter ABI Platform
behave_format-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 69.7 kB

Release files / behave_format-1.2.0.tar.gz

Download URL behave_format-1.2.0.tar.gz
Size 45.9 kB
Tags Source
SHA-256 checksum
How to use checksums
c0f9b3c6434da4a32320c934775af3d559b233149f80a4de0930da7c90b157ab
BLAKE2b-256 checksum
How to use checksums
d3f5212363faec8790cd08a863c693cfc96ab42d7af61204c0fc52641eaeb55d
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 15, 2026.

Transparency log

Release files / behave_format-1.2.0-py3-none-any.whl

Download URL behave_format-1.2.0-py3-none-any.whl
Size 23.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f8ee40ed5730931968a5d97d242493172c6ee9899f64848fdc63d7aba51bfb7b
BLAKE2b-256 checksum
How to use checksums
69eb28a32216f728b1ec450aeafb5203da13e1d20a0d9e94f037c43378efc3ea
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 15, 2026.

Transparency log

Release history Release notifications | RSS feed

1.2.1

2 release files

This release

1.2.0 This release

2 release files

1.1.0

2 release files

1.0.1

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