Skip to main content

Canonical object model for Behave projects

Project description

behave-model

The canonical object model for Behave projects.

CI PyPI Python License: MIT Coverage

Documentation · Quick Start · API Reference


behave-model provides a clean, stable, and extensible Python API that represents every element of a Behave project — features, rules, scenarios, steps, tags, tables, docstrings, and more. It is the foundation for an entire ecosystem of tools: formatters, linters, analyzers, report generators, and anything else that needs to understand .feature files.

Why?

Every Behave tooling project currently parses .feature files independently. behave-model provides a single, well-tested domain model so that future tools can depend on it instead of reinventing the parser.

  • Compatible with Behave 1.3.x — Tag Expression v2 and Gherkin v6 (including Rule blocks)
  • Clean domain model — Pure dataclasses, no external runtime dependencies beyond Behave
  • Visitor pattern — Traverse the entire tree with custom visitors
  • Query API — Find features, scenarios, steps, and tags by name, tag, or keyword
  • Serializers — Dict, JSON, and pretty-printed Gherkin output
  • Transformations — Safe in-place modifications (rename tags, sort, normalize)
  • Validation framework — Pluggable rules with built-in checks
  • 95% test coverage — Comprehensive unit, integration, and golden file tests

Installation

pip install behave-model

For development:

pip install -e ".[dev]"

Quick Start

from behave_model import load_project

# Load all .feature files from a directory
project = load_project("features/")

# Access features, rules, and scenarios
print(len(project.features))          # number of features
print(project.features[0].name)       # first feature name
print(len(project.features[0].rules)) # rules (Gherkin v6)

# Query the model
for scenario in project.find_scenarios(tag="@smoke"):
    print(scenario.name)

# Statistics
stats = project.statistics()
print(f"{stats['features']} features, {stats['scenarios']} scenarios, {stats['steps']} steps")

# Traverse the tree
for node in project.walk():
    print(type(node).__name__)

Domain Model

Project
├── Metadata
├── Feature
│   ├── Tag
│   ├── Background
│   │   └── Step
│   ├── Scenario
│   │   ├── Tag
│   │   └── Step
│   ├── ScenarioOutline
│   │   ├── Tag
│   │   ├── Step
│   │   └── Examples
│   │       └── Table
│   └── Rule (Gherkin v6)
│       ├── Tag
│       ├── Background
│       │   └── Step
│       ├── Scenario
│       └── ScenarioOutline
└── ...

Every node has a Location (filename, line, column) for precise source mapping.

Features at a Glance

Loading

from behave_model import load_project, load_feature

project = load_project("features/")               # all .feature files
feature = load_feature("features/login.feature")  # single file

Visitor Pattern

from behave_model import Visitor

class StepCounter(Visitor):
    def __init__(self):
        self.count = 0

    def visit_step(self, step):
        self.count += 1

visitor = StepCounter()
project.accept(visitor)
print(f"Total steps: {visitor.count}")

Query API

project.find_feature("Login")
project.find_tag("@smoke")
project.find_scenarios(tag="@api")
project.find_scenarios(name_contains="login")
project.find_steps(keyword="Given")
project.find_steps(text_contains="user")

Serialization

from behave_model import JsonSerializer, DictSerializer, PrettyPrinter

# JSON
json_str = JsonSerializer().serialize_project(project)

# Dictionary
data = DictSerializer().serialize_project(project)

# Pretty-printed Gherkin
text = PrettyPrinter().print_feature(feature)

Transformations

from behave_model import rename_tag, sort_tags, normalize_whitespace

rename_tag(project, "@smoke", "@critical")
sort_tags(project)
normalize_whitespace(project)

Validation

from behave_model import Validator

validator = Validator()
issues = validator.validate(project)
for issue in issues:
    print(f"[{issue.severity}] {issue.rule_name}: {issue.message}")

Architecture

Feature File → Parser Adapter → Domain Model → Visitors → Queries → Transformations → Serializers

The Domain Model never depends on report generation or formatting. Each layer has a single responsibility and can be used independently.

Layer Package Responsibility
Parser Adapter behave_model.parser Wraps Behave's parser, adapts to domain model
Domain Model behave_model.model Pure dataclasses for every Gherkin element
Visitors behave_model.visitors Generic traversal pattern
Queries behave_model.queries High-level filtering API
Transformations behave_model.transformations Safe in-place modifications
Serializers behave_model.serializers Dict, JSON, Gherkin output
Validation behave_model.validation Pluggable rule framework

Compatibility

Feature Supported
Behave 1.3.x
Tag Expression v1
Tag Expression v2
Gherkin v6 (Rules)
Scenario Outlines
Data Tables
DocStrings
Background
Multi-language features

Development

# Clone and install
git clone https://github.com/MathiasPaulenko/behave-model.git
cd behave-model
pip install -e ".[dev]"

# Run tests
make test

# Run tests with coverage
make coverage

# Lint
make lint

# Format
make format

# Build
make build

Documentation

Full documentation is available at mathiaspaulenko.github.io/behave-model.

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

behave_model-1.0.0.tar.gz (38.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

behave_model-1.0.0-py3-none-any.whl (34.9 kB view details)

Uploaded Python 3

File details

Details for the file behave_model-1.0.0.tar.gz.

File metadata

  • Download URL: behave_model-1.0.0.tar.gz
  • Upload date:
  • Size: 38.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for behave_model-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5ed612885400971f0478239f7df96b61bbb31054f53a09bee10b6e3524d8c2df
MD5 f3a5d9e76439ff6a4b1707ecb269e477
BLAKE2b-256 0555a9ddada9af2fbf2f8d46f7f8943327597823cf19ebabc3839c188aa73a12

See more details on using hashes here.

Provenance

The following attestation bundles were made for behave_model-1.0.0.tar.gz:

Publisher: release.yml on MathiasPaulenko/behave-model

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file behave_model-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: behave_model-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 34.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for behave_model-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a5089a342caf15bcf550095af4aa898b9de117ed34e695f09e3adee61ad5c5fc
MD5 c67737fb51d1f9e86a84b6d60460d458
BLAKE2b-256 f124b5716a5a83d12d2dc0a67b212943881837bac6bdb91a89ee43d66d3ae209

See more details on using hashes here.

Provenance

The following attestation bundles were made for behave_model-1.0.0-py3-none-any.whl:

Publisher: release.yml on MathiasPaulenko/behave-model

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page