behave-modern-sheets-report
Modern spreadsheet report formatters for Behave BDD — generate CSV, XLSX, and ODS execution reports with multi-sheet layouts, conditional formatting, and automatic trend history.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Format Comparison
- Report Structure
- CLI Usage
- Configuration Options
- Available Columns
- Automatic History & Trends
- Programmatic Usage
- Architecture
- Ecosystem
- Contributing
- Security
- Changelog
- License
Features
| Feature | Description | |
|---|---|---|
| 📊 | Three output formats | CSV (stdlib, zero dependencies), XLSX (via openpyxl), and ODS (via odfpy) |
| 📑 | Multi-sheet workbooks | Summary, Details, Failures, and Trends sheets in XLSX and ODS |
| 🎨 | Conditional formatting | Color-coded pass/fail cells for at-a-glance status reading |
| 📈 | Automatic trend history | Every run is persisted to a JSON file and visualized in a Trends sheet |
| ⚙️ | Configurable columns | Choose which columns appear in the Details sheet via userdata |
| 🔒 | Atomic history writes | Corruption-proof file I/O using temp file + os.replace |
| ✅ | 100% test coverage | Fully tested across Python 3.11, 3.12, 3.13, and 3.14 on Linux, Windows, and macOS |
| 🪶 | Zero required dependencies | CSV works with Python stdlib alone; XLSX and ODS are opt-in extras |
Requirements
- Python 3.11 or higher
- Behave >= 1.2.6 (for running BDD tests)
openpyxl >= 3.1(optional, for XLSX output)odfpy >= 1.4(optional, for ODS output)
Installation
pip install behave-modern-sheets-report
Extras
| Extra | Packages | When to use |
|---|---|---|
[behave] |
behave>=1.2.6 |
You need Behave installed alongside the formatter |
[xlsx] |
openpyxl>=3.1 |
You want XLSX output |
[ods] |
odfpy>=1.4 |
You want ODS output |
[dev] |
pytest, ruff, mypy, build, twine |
Local development |
Install with multiple extras:
pip install "behave-modern-sheets-report[xlsx,ods]"
For full development setup:
git clone https://github.com/MathiasPaulenko/behave-modern-sheets-report.git
cd behave-modern-sheets-report
pip install -e ".[dev,xlsx,ods]"
pre-commit install
Quick Start
-
The formatters are registered as
behave.formattersentry points, so they are discoverable bybehave-runnerand other tools automatically. If you use plainbehave, register them in yourbehave.ini:[behave.formatters] csv-modern = behave_modern_sheets_report.csv_formatter:CSVFormatter xlsx-modern = behave_modern_sheets_report.xlsx_formatter:XLSXFormatter ods-modern = behave_modern_sheets_report.ods_formatter:ODSFormatter
-
Run Behave with any (or all) of the formatters:
behave -f xlsx-modern -o report.xlsx
-
Open
report.xlsxin Excel, LibreOffice, or Google Sheets.
Format Comparison
| Feature | CSV | XLSX | ODS |
|---|---|---|---|
| Dependency | stdlib | openpyxl |
odfpy |
| Multi-sheet | Single file | Yes | Yes |
| Conditional formatting | — | Cell fills | Cell styles |
| Auto-filters | — | Yes | — |
| Freeze panes | — | Yes | — |
| Bold headers | — | Yes | Yes |
| Trends sheet | — | Yes | Yes |
| Install extra | — | [xlsx] |
[ods] |
Report Structure
XLSX and ODS reports contain up to four sheets:
| Sheet | Content | When present |
|---|---|---|
| Summary | One row per feature with totals, pass rate, and duration | Always |
| Details | One row per scenario with configurable columns | Always |
| Failures | Failed scenarios only — error message, type, traceback, file, line | Always (empty if no failures) |
| Trends | Historical run entries with pass rate evolution over time | When history exists |
CSV reports produce a single flat file with one row per scenario (equivalent to the Details sheet).
Conditional formatting colors
| Status | Cell fill |
|---|---|
| Passed | Green (#C6EFCE) |
| Failed | Red (#FFC7CE) |
| Skipped | Yellow (#FFEB9C) |
CLI Usage
The formatters are registered as behave.formatters entry points in pyproject.toml, making them discoverable by behave-runner and compatible tools. When using plain behave, register them in behave.ini:
[behave.formatters]
csv-modern = behave_modern_sheets_report.csv_formatter:CSVFormatter
xlsx-modern = behave_modern_sheets_report.xlsx_formatter:XLSXFormatter
ods-modern = behave_modern_sheets_report.ods_formatter:ODSFormatter
Generate reports:
behave -f csv-modern -o report.csv
behave -f xlsx-modern -o report.xlsx
behave -f ods-modern -o report.ods
Multiple formatters can be used simultaneously to produce all formats in a single run:
behave -f csv-modern -o report.csv -f xlsx-modern -o report.xlsx -f ods-modern -o report.ods
You can also set userdata options directly in behave.ini:
[behave.userdata]
report_columns = feature,scenario,status,duration,error
report_only_failed = false
report_max_history = 50
Configuration Options
All options are passed via Behave's userdata (command-line -D or behave.ini):
| Option | Type | Default | Description |
|---|---|---|---|
report_columns |
CSV string | feature,scenario,status,duration,tags,error |
Columns shown in Details sheet |
report_only_failed |
bool | false |
Show only failed scenarios in Details |
report_delimiter |
string | comma |
CSV delimiter (comma, semicolon, tab) |
report_clear_history |
bool | false |
Clear history before appending current run |
report_history_path |
string | .behave-sheets-history.json |
Path to history JSON file |
report_max_history |
int | 100 |
Maximum history entries to retain |
Examples
Generate an XLSX report with only failed scenarios and a custom column set:
behave -f xlsx-modern -o report.xlsx \
-D report_only_failed=true \
-D report_columns=feature,scenario,status,error \
-D report_max_history=50
Use a semicolon delimiter for CSV (useful in European locales):
behave -f csv-modern -o report.csv -D report_delimiter=semicolon
Clear history before a fresh run (e.g. after changing the test suite):
behave -f xlsx-modern -o report.xlsx -D report_clear_history=true
Store history in a custom location (e.g. outside the working directory):
behave -f xlsx-modern -o report.xlsx -D report_history_path=/tmp/behave-history.json
Available Columns
The report_columns option accepts any combination of the following column names (comma-separated):
| Column | Description |
|---|---|
feature |
Feature name |
scenario |
Scenario name |
status |
Scenario status (passed, failed, skipped, undefined) |
duration |
Execution time (human-readable, e.g. 1.234s, 12ms) |
tags |
Scenario tags (semicolon-separated) |
error |
Error message with type if available (e.g. AssertionError [...]) |
error_type |
Exception type name |
traceback |
Full traceback string |
steps |
Total step count |
passed_steps |
Number of passed steps |
failed_steps |
Number of failed steps |
skipped_steps |
Number of skipped steps |
file |
Feature file path |
line |
Line number in the feature file |
rule |
Gherkin rule name (empty if none) |
is_outline |
true if scenario outline example row, false otherwise |
feature_tags |
Feature-level tags (semicolon-separated) |
background_steps |
Number of background steps executed before the scenario |
has_data_table |
true if any step includes a Gherkin data table |
has_docstring |
true if any step includes a Gherkin docstring |
Default columns: feature,scenario,status,duration,tags,error
Automatic History & Trends
Every run is automatically appended to a JSON history file (.behave-sheets-history.json by default). The history feeds the Trends sheet in XLSX and ODS reports, showing pass rate evolution across runs.
report_history_path— custom location for the history file.report_clear_history— clears all previous entries before appending the current run (useful for fresh starts).report_max_history— limits the number of retained entries (oldest are dropped).
History is managed atomically (write to .tmp, then os.replace) to prevent corruption.
History file format
The history file is a JSON array of entry objects:
[
{
"run_id": "run_a1b2c3d4e5f6",
"timestamp": "2025-01-15T10:30:00.123456+00:00",
"total_features": 3,
"total_scenarios": 15,
"passed": 14,
"failed": 1,
"skipped": 0,
"undefined": 0,
"pass_rate": 93.3,
"duration": 2.45
}
]
Programmatic Usage
You can use the collector, writers, and history directly without Behave:
from behave_modern_sheets_report import Collector, CSVWriter, XLSXWriter, History
from pathlib import Path
# Collect results from Behave events
collector = Collector()
collector.start_feature(feature_obj)
collector.start_scenario(scenario_obj)
collector.start_step(step_obj)
collector.end_step(step_obj)
collector.end_scenario()
collector.end_feature()
run_summary = collector.finalize()
# Write CSV (no extra dependencies needed)
with open("report.csv", "w", newline="") as f:
CSVWriter.write(run_summary, f)
# Write XLSX (requires openpyxl)
history = History(max_entries=50)
trends = history.append(run_summary)
XLSXWriter.write(run_summary, Path("report.xlsx"), trends=trends)
This is useful for integrating the report generation into custom test runners or CI pipelines.
Architecture
Behave Runner
│
├── CSVFormatter ──► Collector ──► RunSummary ──► CSVWriter ──► report.csv
├── XLSXFormatter ──► Collector ──► RunSummary ──► XLSXWriter ──► report.xlsx
└── ODSFormatter ───► Collector ──► RunSummary ──► ODSWriter ───► report.ods
│
└──► History ──► .behave-sheets-history.json
│
└──► Trends sheet
Collector processes Behave events (feature, scenario, step, result) and builds a RunSummary. Writers serialize the summary into the target format. History persists run metrics between executions for trend analysis.
Key design decisions
- Pure data models —
models.pyhas zero external dependencies. Dataclasses can be serialized to any format without importing Behave, openpyxl, or odfpy. - Single Behave integration point —
Collectoris the only module that touches Behave objects. Everything else operates on pure dataclasses, making the writers and history fully testable without Behave. - Opt-in dependencies — CSV works with stdlib alone.
openpyxlandodfpyare only imported when their respective writer is called. - Atomic file I/O — History writes to a
.tmpfile first, then usesos.replacefor an atomic swap. This prevents corruption if the process is killed mid-write.
Ecosystem
Part of the behave-modern-* formatter family:
| Package | Formats | Status |
|---|---|---|
behave-modern-json-report |
JSON | ✅ |
behave-modern-html-report |
HTML | ✅ |
behave-modern-md-report |
Markdown | ✅ |
behave-modern-console-report |
Console (rich terminal) | ✅ |
behave-modern-sheets-report |
CSV, XLSX, ODS | this package |
Contributing
Contributions are welcome! Please read the Contributing Guide and our Code of Conduct before submitting pull requests.
Development commands
make lint # ruff check + format check
make typecheck # mypy --strict
make test # pytest with verbose output
make format # ruff auto-fix + format
make build # build sdist + wheel
Security
If you discover a security vulnerability, please refer to our Security Policy for responsible disclosure instructions.
Changelog
See CHANGELOG.md for release history and notable changes.
License
MIT — see LICENSE for full text.
Made with care by Mathias Paulenko
Release files for behave-modern-sheets-report 1.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| behave_modern_sheets_report-1.1.1.tar.gz | 57.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| behave_modern_sheets_report-1.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 88.6 kB
Release files / behave_modern_sheets_report-1.1.1.tar.gz
| Download URL | behave_modern_sheets_report-1.1.1.tar.gz |
|---|---|
| Size | 57.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0cff3f5509bcd04b57b73e89a626a9d3c8bdc7308d51db10758d01e6e3ddaa4f
|
|
BLAKE2b-256 checksum How to use checksums |
6cfcf25bd74175df00f86c5b7622728072a419b9dedb9dc77b1de5f7e314294d
|
| 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 Aug 10, 2026.
Transparency logRelease files / behave_modern_sheets_report-1.1.1-py3-none-any.whl
| Download URL | behave_modern_sheets_report-1.1.1-py3-none-any.whl |
|---|---|
| Size | 31.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
39facf1ef089943ebf18cd742b6233db78596fdcacf5370c100bdc9d808591a0
|
|
BLAKE2b-256 checksum How to use checksums |
8b93e93cfa73e27c251d38e821be054be5eb41490541b48df7253f49959c0e2d
|
| 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 Aug 10, 2026.
Transparency log