Modern sheets report formatter for Behave that generates CSV, XLSX and ODS execution reports.
Project description
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
-
Register the formatters in your
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
-
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
Register formatters 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 |
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file behave_modern_sheets_report-1.0.0.tar.gz.
File metadata
- Download URL: behave_modern_sheets_report-1.0.0.tar.gz
- Upload date:
- Size: 53.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
647fe82ab8074057b59de67465fa21cba6c4eeb16356d7eda170fdf02143a131
|
|
| MD5 |
9c86e91ea59202f05203cac269f6e608
|
|
| BLAKE2b-256 |
8d2ee6bf6c009561130daed453334262862046a53e94c0c5c2caafe176b2cf14
|
Provenance
The following attestation bundles were made for behave_modern_sheets_report-1.0.0.tar.gz:
Publisher:
release.yml on MathiasPaulenko/behave-modern-sheets-report
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
behave_modern_sheets_report-1.0.0.tar.gz -
Subject digest:
647fe82ab8074057b59de67465fa21cba6c4eeb16356d7eda170fdf02143a131 - Sigstore transparency entry: 2171992492
- Sigstore integration time:
-
Permalink:
MathiasPaulenko/behave-modern-sheets-report@d079ef913d36d800e201017dd8d1d67af7367d20 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/MathiasPaulenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d079ef913d36d800e201017dd8d1d67af7367d20 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file behave_modern_sheets_report-1.0.0-py3-none-any.whl.
File metadata
- Download URL: behave_modern_sheets_report-1.0.0-py3-none-any.whl
- Upload date:
- Size: 29.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
08ab998ac3a425297b73d027da58ae4fce3f9d9a1aadf064dde0c03d573b304c
|
|
| MD5 |
0367c1b9e4190f38c5bf8b1c55fd1a31
|
|
| BLAKE2b-256 |
bc05213131c60e20e8ed44846ae058e3b518ed925b0fc8c9255242e0a86d52ca
|
Provenance
The following attestation bundles were made for behave_modern_sheets_report-1.0.0-py3-none-any.whl:
Publisher:
release.yml on MathiasPaulenko/behave-modern-sheets-report
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
behave_modern_sheets_report-1.0.0-py3-none-any.whl -
Subject digest:
08ab998ac3a425297b73d027da58ae4fce3f9d9a1aadf064dde0c03d573b304c - Sigstore transparency entry: 2171992499
- Sigstore integration time:
-
Permalink:
MathiasPaulenko/behave-modern-sheets-report@d079ef913d36d800e201017dd8d1d67af7367d20 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/MathiasPaulenko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d079ef913d36d800e201017dd8d1d67af7367d20 -
Trigger Event:
workflow_dispatch
-
Statement type: