behave-data

July 19, 2026 · View on GitHub

PyPI Python Tests Docs Coverage License

Data management for Behave — typed tables, diffs, dynamic examples, fixtures, and secrets with zero boilerplate.

Built on top of behave-tables.

Full documentation: mathiaspaulenko.github.io/behave-data


Why?

Behave data tables are strings. Everything is "42", "true", "". You write boilerplate in environment.py to convert types, handle nulls, load examples, and manage test data.

behave-data fixes this:

Without behave-dataWith behave-data
row["age"]"42" (string)row["age"]42 (int)
Empty cell → ""Empty cell → None
Hardcoded Examples in .featureLoad from CSV, JSON, YAML, Excel, SQL, HTTP
Manual before_all / after_scenario@needs_data, @with_fixture, @cleanup_after tags
Secrets in feature filesenv:VAR, file:path, secret:name with masking

Features

  • Typed Tablesname:str, age:int, active:bool, price:float, created:date with automatic conversion
  • Null Resolution — Empty cells become None, configurable markers ("", "null", "N/A"), per-column overrides
  • Table Diff — Cucumber-style diff output with row/column mismatch detection
  • Raw Tables — Access tables without header assumption, vertical tables, transposed data
  • Dynamic Examples@load_examples:csv:users.csv replaces static Examples blocks
  • Fixtures — Reusable data recipes with nesting (ref:other) and parametrization
  • Builders — Construct test data with derived fields and overrides
  • Secretsenv:, file:, secret: placeholders with Vault and AWS backends, automatic masking
  • Declarative Tags@needs_data, @with_fixture, @cleanup_after for zero-boilerplate setup/teardown

Install

pip install behave-data

Optional extras:

ExtraPackagesUse case
yamlPyYAMLYAML loader
excelopenpyxlExcel loader
sqlSQLAlchemySQL loader
httprequestsHTTP loader
vaulthvacHashiCorp Vault secrets
awsboto3AWS Secrets Manager
allall aboveAll optional loaders and backends
devpytest, ruff, mypy, buildDevelopment
pip install behave-data[yaml,excel]    # multiple extras
pip install behave-data[dev]           # contribute

Quickstart

# features/environment.py
from behave_data import (
    setup_data,
    before_feature_hook,
    before_scenario_hook,
    before_step_hook,
    after_scenario_hook,
)

def before_all(context):
    setup_data(context)

def before_feature(context, feature):
    before_feature_hook(context, feature)

def before_scenario(context, scenario):
    before_scenario_hook(context, scenario)

def before_step(context, step):
    before_step_hook(context, step)

def after_scenario(context, scenario):
    after_scenario_hook(context, scenario)
# features/login.feature
@load_examples:csv:features/data/users.csv
Scenario Outline: User login
  Given a user with name "<name>" and email "<email>"
  When they log in
  Then they see the dashboard

  Examples:
# features/steps/login.py
from behave_data import typed_wrap, diff

@then("the users should match")
def step_match(context):
    table = typed_wrap(context.table)
    for row in table.typed_dicts():
        assert isinstance(row["age"], int)      # typed, not string
        assert row["city"] is None or row["city"]  # None for empty cells

That's it. Type annotations in headers, nulls resolved, examples from external files, tags for setup/teardown — all automatic.

Documentation

SectionLink
QuickstartQuickstart
Typed TablesTyped Tables
Null HandlingNull Handling
Table DiffDiff
Dynamic ExamplesDynamic Examples
FixturesFixtures
BuildersBuilders
SecretsSecrets
Declarative TagsTags
HooksHooks
ConfigurationConfiguration
CookbookCookbook
TroubleshootingTroubleshooting
API ReferenceAPI
Migration GuideMigration
ChangelogChangelog

Migration from behave-tables

behave-data depends on behave-tables and extends it:

  1. pip install behave-databehave-tables comes as a dependency
  2. Use typed_wrap() instead of wrap() for typed column conversion
  3. Add setup_data(context) in before_all() to enable hooks, fixtures, builders, and secrets

All behave-tables APIs (as_dicts, as_models, transpose, to_csv, to_json, find_row, select, etc.) remain available via the re-exported TableWrapper and wrap().

See the Migration Guide for details.

Configuration

# behave_data.yml
null_markers: ["", "null", "None", "N/A"]
null_markers_by_column:
  age: ["", "unknown"]
secret_backend: env
secret_path: secrets/
load_base_dir: features/data/

See Configuration for all options.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for setup, development commands, and the release checklist.

For security issues, see SECURITY.md.

Acknowledgements

  • Built on behave-tables for table manipulation.
  • Inspired by the Behave community's need for first-class data handling in Gherkin scenarios.

License

MIT