behave-hive 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- behave_hive-0.1.0/LICENSE +21 -0
- behave_hive-0.1.0/PKG-INFO +408 -0
- behave_hive-0.1.0/README.md +367 -0
- behave_hive-0.1.0/pyproject.toml +105 -0
- behave_hive-0.1.0/setup.cfg +4 -0
- behave_hive-0.1.0/src/behave_hive/__init__.py +1 -0
- behave_hive-0.1.0/src/behave_hive/batching.py +34 -0
- behave_hive-0.1.0/src/behave_hive/cli.py +71 -0
- behave_hive-0.1.0/src/behave_hive/config.py +358 -0
- behave_hive-0.1.0/src/behave_hive/discovery.py +58 -0
- behave_hive-0.1.0/src/behave_hive/errors.py +39 -0
- behave_hive-0.1.0/src/behave_hive/execution.py +235 -0
- behave_hive-0.1.0/src/behave_hive/expand.py +302 -0
- behave_hive-0.1.0/src/behave_hive/formatters/__init__.py +0 -0
- behave_hive-0.1.0/src/behave_hive/formatters/allure.py +151 -0
- behave_hive-0.1.0/src/behave_hive/formatters/cucumber.py +269 -0
- behave_hive-0.1.0/src/behave_hive/html_report.py +327 -0
- behave_hive-0.1.0/src/behave_hive/lock.py +36 -0
- behave_hive-0.1.0/src/behave_hive/merge.py +150 -0
- behave_hive-0.1.0/src/behave_hive/privacy.py +46 -0
- behave_hive-0.1.0/src/behave_hive/roots.py +76 -0
- behave_hive-0.1.0/src/behave_hive/runner.py +299 -0
- behave_hive-0.1.0/src/behave_hive/selection.py +26 -0
- behave_hive-0.1.0/src/behave_hive/status.py +51 -0
- behave_hive-0.1.0/src/behave_hive/summary.py +56 -0
- behave_hive-0.1.0/src/behave_hive/templates/report.html +226 -0
- behave_hive-0.1.0/src/behave_hive/worker.py +61 -0
- behave_hive-0.1.0/src/behave_hive.egg-info/PKG-INFO +408 -0
- behave_hive-0.1.0/src/behave_hive.egg-info/SOURCES.txt +31 -0
- behave_hive-0.1.0/src/behave_hive.egg-info/dependency_links.txt +1 -0
- behave_hive-0.1.0/src/behave_hive.egg-info/entry_points.txt +2 -0
- behave_hive-0.1.0/src/behave_hive.egg-info/requires.txt +17 -0
- behave_hive-0.1.0/src/behave_hive.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Alberto Zapata
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: behave-hive
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Run behave scenarios in parallel with Examples read from CSV files, and get Allure, Cucumber JSON and HTML reports
|
|
5
|
+
Author: Alberto Zapata
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/albertor03/behave-hive
|
|
8
|
+
Project-URL: Issues, https://github.com/albertor03/behave-hive/issues
|
|
9
|
+
Keywords: behave,bdd,csv,parallel,allure,cucumber
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Framework :: Pytest
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
15
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing :: BDD
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: behave<1.4,>=1.3
|
|
27
|
+
Provides-Extra: allure
|
|
28
|
+
Requires-Dist: allure-behave==2.16.2; extra == "allure"
|
|
29
|
+
Provides-Extra: playwright
|
|
30
|
+
Requires-Dist: playwright>=1.40; extra == "playwright"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
33
|
+
Requires-Dist: jsonschema>=4; extra == "dev"
|
|
34
|
+
Requires-Dist: build>=1; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff; extra == "dev"
|
|
36
|
+
Requires-Dist: pylint; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=7; extra == "dev"
|
|
38
|
+
Requires-Dist: coverage>=7.10; extra == "dev"
|
|
39
|
+
Requires-Dist: pip-audit; extra == "dev"
|
|
40
|
+
Dynamic: license-file
|
|
41
|
+
|
|
42
|
+
# behave-hive
|
|
43
|
+
|
|
44
|
+
Run [behave](https://github.com/behave/behave) 1.3.x scenarios in parallel, read `Examples:` from CSV files and get Allure, Cucumber JSON and HTML reports in one run.
|
|
45
|
+
|
|
46
|
+
- **Examples from CSV:** point an `Examples:` table at a file with its path, `| data/users.csv |`, or the equivalent `| read('data/users.csv') |`. CSV and hand-written tables can live in the same outline.
|
|
47
|
+
- **Sequential or parallel runs:** set in the `[behave_hive]` section of `behave.ini`, or with `--parallel/--no-parallel`.
|
|
48
|
+
- **Consolidated reports:** Allure results, standard Cucumber JSON and a self-contained HTML report with filters, metrics and screenshots.
|
|
49
|
+
|
|
50
|
+
Your steps, your `environment.py` and the way you write features stay the same. A `.feature` without CSV cells runs exactly as it does with behave. behave-hive complements behave; if you only need a parallel runner with its own report, [BehaveX](https://github.com/hrcorval/behavex) is another option.
|
|
51
|
+
|
|
52
|
+
**Contents:** [Installation](#installation) · [Quick start](#quick-start) · [Examples from CSV](#examples-from-csv) · [Running](#running) · [Configuration](#configuration) · [Reports](#reports) · [Examples](#examples) · [Limitations](#limitations) · [Roadmap](#roadmap) · [Contributing](#contributing) · [Releasing](#releasing)
|
|
53
|
+
|
|
54
|
+
## Installation
|
|
55
|
+
|
|
56
|
+
Install behave-hive in the same environment as your behave project, with [uv](https://docs.astral.sh/uv/):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uv add behave-hive # in a uv project; or: uv pip install behave-hive
|
|
60
|
+
uv add "behave-hive[allure]" # adds allure-behave 2.16.2 for the Allure format
|
|
61
|
+
uv add "behave-hive[playwright]" # only needed to run the example
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
pip works too: `pip install behave-hive`, `pip install "behave-hive[allure]"`.
|
|
65
|
+
|
|
66
|
+
Requires Python 3.11 or newer. macOS and Linux are supported; Windows is not (see [Limitations](#limitations)). Run the commands in this guide with `uv run` (for example `uv run behave-hive run`), or activate the environment first.
|
|
67
|
+
|
|
68
|
+
## Quick start
|
|
69
|
+
|
|
70
|
+
`features/login.feature`:
|
|
71
|
+
|
|
72
|
+
```gherkin
|
|
73
|
+
Feature: Login
|
|
74
|
+
|
|
75
|
+
Scenario Outline: Login as <user>
|
|
76
|
+
Given I open the login page
|
|
77
|
+
When I sign in with user "<user>" and password "<password>"
|
|
78
|
+
Then I see the message "<message>"
|
|
79
|
+
|
|
80
|
+
Examples:
|
|
81
|
+
| data/login.csv |
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`features/data/login.csv`:
|
|
85
|
+
|
|
86
|
+
```csv
|
|
87
|
+
user,password,message
|
|
88
|
+
admin,1234,Welcome
|
|
89
|
+
admin,wrong,Invalid credentials
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
uv run behave-hive run --parallel -w 2
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
Examples: 0 inline, 1 from CSV
|
|
98
|
+
- features/data/login.csv
|
|
99
|
+
Mode: parallel (2 workers, scheme scenario)
|
|
100
|
+
batch 1 · worker 1 · 1 scenario · passed · 1.6s
|
|
101
|
+
batch 2 · worker 2 · 1 scenario · passed · 1.6s
|
|
102
|
+
1 feature · 2 scenarios (2 passed) · 6 steps (6 passed) · 1.7s
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+

|
|
106
|
+
|
|
107
|
+
Open `report.html` (project root by default) for the result; the Cucumber JSON, Allure results and logs are in `reports/`. The steps used here are in [`example/`](example/), which runs as is.
|
|
108
|
+
|
|
109
|
+
## Examples from CSV
|
|
110
|
+
|
|
111
|
+
```gherkin
|
|
112
|
+
Feature: Login
|
|
113
|
+
|
|
114
|
+
Scenario Outline: Login as <user>
|
|
115
|
+
Given I open the login page
|
|
116
|
+
When I sign in with user "<user>" and password "<password>"
|
|
117
|
+
Then I see the message "<message>"
|
|
118
|
+
|
|
119
|
+
Examples: valid credentials
|
|
120
|
+
| data/login.csv |
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`data/login.csv`:
|
|
124
|
+
|
|
125
|
+
```csv
|
|
126
|
+
user,password,message
|
|
127
|
+
admin,1234,Welcome
|
|
128
|
+
admin,wrong,Invalid credentials
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
A table is read from CSV when its first row has **one cell** that is a path ending in `.csv`. That plain path is the default form:
|
|
132
|
+
|
|
133
|
+
```gherkin
|
|
134
|
+
Examples:
|
|
135
|
+
| data/login.csv |
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`read('path.csv')` and `read("path.csv")` mean exactly the same; use them if you prefer the explicit spelling:
|
|
139
|
+
|
|
140
|
+
```gherkin
|
|
141
|
+
Examples:
|
|
142
|
+
| read('data/login.csv') |
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Any other table is a regular, hand-written one. Both kinds can live in the same outline, each under its own `Examples:`, and each keeps its own tags:
|
|
146
|
+
|
|
147
|
+
```gherkin
|
|
148
|
+
@smoke
|
|
149
|
+
Examples: from a file
|
|
150
|
+
| data/login.csv |
|
|
151
|
+
|
|
152
|
+
Examples: written by hand
|
|
153
|
+
| user | password | message |
|
|
154
|
+
| guest | guest | Invalid credentials |
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The CSV path is relative to the directory of the `.feature` file (subdirectories and `..` are fine). The `Examples:` keyword follows the language of the feature (`# language:` directive or `lang` in `[behave]`).
|
|
158
|
+
|
|
159
|
+
### CSV contract
|
|
160
|
+
|
|
161
|
+
- UTF-8, with or without a BOM. The first row is the header; its names are the `<placeholders>`.
|
|
162
|
+
- Physically empty lines are ignored. Empty cells are kept.
|
|
163
|
+
- Spaces around a cell are lost, as in any Gherkin table. A `|` inside a cell is written as `\|` for you, and the step receives it intact.
|
|
164
|
+
- Rejected, with exit code 2 and a message naming the `.feature`, the line, the CSV and the CSV row: no data rows, empty or duplicated headers (after stripping spaces), rows whose width differs from the header, cells with a line break, a missing file and invalid UTF-8.
|
|
165
|
+
- Text inside `"""` or `'''` docstrings is never interpreted as `Examples:`.
|
|
166
|
+
|
|
167
|
+
### What behave-hive writes
|
|
168
|
+
|
|
169
|
+
When a CSV table is present, the whole features root is copied to a working directory: `.feature` files are written expanded and every other file is a symlink to the original. `uri`s in the reports are the original ones; the HTML report shows `path.csv:row` next to each scenario. To see the result:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
behave-hive expand features /tmp/expanded
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`expand` refuses, without deleting anything, a destination that is the source or one of its ancestors, a symlink, or a non-empty directory not created by a previous expansion.
|
|
176
|
+
|
|
177
|
+
## Running
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
behave-hive run # uses [behave_hive] from behave.ini
|
|
181
|
+
behave-hive run --parallel -w 4 # 4 processes
|
|
182
|
+
behave-hive run --no-parallel # one process per features root
|
|
183
|
+
behave-hive run features/login.feature # a directory or a single .feature file
|
|
184
|
+
behave-hive run -- --tags=@smoke -D env=qa # everything after -- goes to behave
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Every path belongs to a **features root**: the closest directory, walking up, that contains `steps/`. Inputs with the same root share one expansion, and a scenario reachable through two inputs runs once.
|
|
188
|
+
|
|
189
|
+
| Option | Meaning |
|
|
190
|
+
|---|---|
|
|
191
|
+
| `--parallel` / `--no-parallel` | Override `parallel`. |
|
|
192
|
+
| `-w`, `--workers N` | Number of processes. |
|
|
193
|
+
| `--scheme scenario\|feature` | Distribute scenarios (and outline rows) or whole features. |
|
|
194
|
+
| `--chunk N` | Units per process; `0` splits the units of a root evenly among the workers. |
|
|
195
|
+
| `--results-dir DIR` | Where JSON, Allure results and logs go; HTML uses `report_path`. |
|
|
196
|
+
| `--formats LIST` | Any of `allure`, `cucumber`, `html`. |
|
|
197
|
+
| `--config FILE` | Read `[behave_hive]` from this file only. |
|
|
198
|
+
| `--keep-tmp` | Keep `results_dir/tmp/` (partial results, locations files). |
|
|
199
|
+
|
|
200
|
+
### Parallel by scenario or by feature
|
|
201
|
+
|
|
202
|
+
With `parallel = true`, behave-hive splits the suite into **units** and gives them to up to `workers` processes. `scheme` decides what a unit is:
|
|
203
|
+
|
|
204
|
+
| `scheme` | A unit is | Use it when |
|
|
205
|
+
|---|---|---|
|
|
206
|
+
| `scenario` (default) | One scenario, or one row of a Scenario Outline (from CSV or written by hand). | Scenarios are independent. A file with 4 data rows runs as 4 units, in parallel. |
|
|
207
|
+
| `feature` | One whole `.feature` file; its scenarios run in order in the same process. | Scenarios of a feature depend on each other, share an expensive `before_feature`, or use `@setup`/`@teardown`. The same 4-row file is 1 unit. |
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
behave-hive run --parallel --scheme scenario -w 4 # rows and scenarios spread over 4 processes
|
|
211
|
+
behave-hive run --parallel --scheme feature -w 2 # one process per feature, 2 at a time
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
The same keys work in the configuration file (`parallel`, `workers`, `scheme`, `chunk`); [`example/configs/`](example/configs/) has a ready-made file for each case. A scenario's own steps never run in parallel. `chunk` sets how many units each process receives (`0` shares them evenly). `before_all` and `after_all` in `environment.py` run once per process, so use [`BEHAVE_HIVE_WORKER`](#worker-identification) to keep ports or users apart.
|
|
215
|
+
|
|
216
|
+
Exit codes: `0` all good, `1` a `failed`, `undefined` or `pending` scenario or a batch error, `2` usage, configuration or CSV error, `130` interrupted with Ctrl+C. When nothing matches, `No scenarios found` is printed and the exit code is 0.
|
|
217
|
+
|
|
218
|
+
## Configuration
|
|
219
|
+
|
|
220
|
+
Put a `[behave_hive]` section next to `[behave]` in `behave.ini`, `.behaverc`, `setup.cfg` or `tox.ini`, or a `[tool.behave_hive]` table in `pyproject.toml`. Files are looked up in the working directory in that order and the first one with the section wins. behave ignores the section.
|
|
221
|
+
|
|
222
|
+
```ini
|
|
223
|
+
[behave]
|
|
224
|
+
default_tags = not @expected_fail
|
|
225
|
+
|
|
226
|
+
[behave_hive]
|
|
227
|
+
parallel = true
|
|
228
|
+
workers = 3
|
|
229
|
+
scheme = scenario
|
|
230
|
+
formats = allure, cucumber, html
|
|
231
|
+
report_name = My QA project
|
|
232
|
+
report_path = reports/report.html
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
| Key | Default | Notes |
|
|
236
|
+
|---|---|---|
|
|
237
|
+
| `parallel` | `false` | `true/false`, `yes/no`, `on/off`, `1/0`. Sequential mode ignores `workers`, `scheme` and `chunk`. |
|
|
238
|
+
| `workers` | number of CPUs | At least 1. |
|
|
239
|
+
| `scheme` | `scenario` | `scenario` or `feature`. |
|
|
240
|
+
| `chunk` | `0` | At least 0. |
|
|
241
|
+
| `results_dir` | `reports` | |
|
|
242
|
+
| `report_name` | project name | HTML title and heading only; blank also uses the fallback. |
|
|
243
|
+
| `report_path` | `<project-root>/report.html` | Full HTML filename; relative to the project root, or absolute. Parents are created. |
|
|
244
|
+
| `formats` | `cucumber, html` | Comma or space separated; TOML arrays work too. |
|
|
245
|
+
| `work_dir` | `.behave-hive` | Each run uses its own subdirectory. |
|
|
246
|
+
| `behave_args` | empty | Shell-style string (`--tags="@a and not @b" -D env=qa`) or a TOML array. `%` is literal. |
|
|
247
|
+
| `paths` | `features` | What to run when no path is given. |
|
|
248
|
+
|
|
249
|
+
Precedence, lowest to highest: default, file, command line. Arguments after `--` are appended after `behave_args`. An unknown key is an error. behave's own settings (`default_tags`, `tags`, `lang`, ...) keep their meaning; `--tags` on the command line overrides `default_tags`, as in behave.
|
|
250
|
+
|
|
251
|
+
The project root is the selected configuration file's directory, or the working
|
|
252
|
+
directory when no configuration section is selected. An omitted/blank HTML name
|
|
253
|
+
uses `[project].name` from that root's `pyproject.toml`, then the folder name.
|
|
254
|
+
HTML is now written at the project root by default. Set
|
|
255
|
+
`report_path = reports/report.html` to retain the earlier destination.
|
|
256
|
+
These settings do not change the generated Allure report's name.
|
|
257
|
+
|
|
258
|
+
### Arguments behave-hive controls
|
|
259
|
+
|
|
260
|
+
These are rejected, in `behave_args` and after `--`, with exit code 2:
|
|
261
|
+
|
|
262
|
+
- positional arguments and `@file`s (paths go before `--`);
|
|
263
|
+
- `-f/--format`, `-o/--outfile`, `-r/--runner`, `--junit`, `--junit-directory`;
|
|
264
|
+
- `-d/--dry-run`, `--stop`, `-i/--include`, `-e/--exclude`, `-n/--name`, `-w/--wip`.
|
|
265
|
+
|
|
266
|
+
The same applies to the *effective* behave configuration: `stop`, `dry_run`, `steps_catalog`, `junit`, `wip`, name filters, `include`/`exclude`, `stage` and a custom runner in `[behave]` are rejected, and so are `--version`, `--tags-help`, `--lang-list` and `--lang-help`. `format` and `outfiles` from `[behave]` are ignored.
|
|
267
|
+
|
|
268
|
+
### Worker identification
|
|
269
|
+
|
|
270
|
+
Each behave process receives `BEHAVE_HIVE_WORKER` (the slot, `1..workers`; always `1` in sequential mode) and `BEHAVE_HIVE_BATCH` (the 1-based batch index). Two active processes never share a slot, so they can pick ports, users or databases:
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
import os
|
|
274
|
+
port = 9000 + int(os.environ.get("BEHAVE_HIVE_WORKER", "1"))
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### `@setup` and `@teardown`
|
|
278
|
+
|
|
279
|
+
behave runs scenarios tagged `@setup` or `@teardown` even when they are not selected. With `parallel = true` and `scheme = scenario`, a feature containing them is rejected; use `scheme = feature` or sequential mode.
|
|
280
|
+
|
|
281
|
+
## Reports
|
|
282
|
+
|
|
283
|
+
JSON, Allure and logs are written to `results_dir` (default `reports/`). The HTML
|
|
284
|
+
file uses `report_path` independently (default `<project-root>/report.html`):
|
|
285
|
+
|
|
286
|
+
| Path | Format |
|
|
287
|
+
|---|---|
|
|
288
|
+
| `cucumber.json` | Standard Cucumber JSON, scenarios in line order, each preceded by its background. |
|
|
289
|
+
| `allure-results/` | One Allure result per scenario that behave selected, including scenarios inside a `Rule`, with `context.attach(...)` data as attachments of their step and an `environment.properties` file. Open it with the Allure CLI: `npx allure@3 generate reports/allure-results`. |
|
|
290
|
+
| `report_path` | Self-contained HTML with inline filters, no external requests, light and dark mode; project name in title and heading. |
|
|
291
|
+
| `logs/batch-<n>.log` | Output of each behave process. |
|
|
292
|
+
|
|
293
|
+
Every generated HTML carries a `behave-hive-report-4f9c2e7a` generator marker in its head. At the start of a run behave-hive deletes the previous file at `report_path` only when it is a regular file with that marker, so an aborted run never leaves an old report that looks current, and any other file at `report_path` is never touched.
|
|
294
|
+
|
|
295
|
+
At the start of a run behave-hive deletes only what it manages (`cucumber.json`, `report.html`, `allure-results/`, `logs/`, `tmp/`); anything else in `results_dir` is kept. A second run on the same `results_dir` exits with code 2.
|
|
296
|
+
|
|
297
|
+
Scenario and feature ids are stable: they do not depend on `workers`, `chunk` or input order. Hook failures and failed `context.add_cleanup` functions count as `failed` (`broken` in Allure). A `pending` step counts as `pending`, except inside a `@wip` scenario.
|
|
298
|
+
|
|
299
|
+
### Allure attachments and environment
|
|
300
|
+
|
|
301
|
+
Data attached with `context.attach(mime_type, data)` (for example a screenshot in
|
|
302
|
+
`after_step`) is stored in `allure-results/` and attached to the step that made it;
|
|
303
|
+
data attached after the last step goes to the last step, and data attached before any
|
|
304
|
+
step is ignored. `environment.properties` lists `behave-hive`, `behave` and `python`
|
|
305
|
+
versions, `mode` (`parallel` or `sequential`), `workers` and `scheme`.
|
|
306
|
+
|
|
307
|
+
### The HTML report
|
|
308
|
+
|
|
309
|
+
- **Failures first:** inside each feature, failed, undefined and pending scenarios come
|
|
310
|
+
first and are open; each shows the first line of its error (the last line when the
|
|
311
|
+
first one is only a prefix such as `ASSERT FAILED:`) and a **Copy error** button.
|
|
312
|
+
- **Run context:** start time, mode, workers, scheme, versions, the command without your
|
|
313
|
+
home or project path, the wall-clock time, the sum of scenario times and, in parallel
|
|
314
|
+
mode, the speedup between them.
|
|
315
|
+
- **Worker and batch:** each scenario names its worker, its batch and `logs/batch-<n>.log`.
|
|
316
|
+
- **Outline groups:** the rows of a Scenario Outline are grouped under the outline, with
|
|
317
|
+
the row count and the number of rows that did not pass.
|
|
318
|
+
- **Shareable filters:** the search text, status and tag filters are kept in the address
|
|
319
|
+
as `#search=...&status=...&tag=...`, for example `report.html#status=failed&tag=@smoke`.
|
|
320
|
+
Unknown values are ignored.
|
|
321
|
+
|
|
322
|
+
A failed scenario opens with its error headline, a **Copy error** button, the worker and batch that ran it, and the screenshot taken by your `after_step` hook (the traceback below the steps is hidden in this picture):
|
|
323
|
+
|
|
324
|
+

|
|
325
|
+
|
|
326
|
+
Filters live in the address, so a filtered view can be shared; `#status=passed&tag=@smoke` shows this:
|
|
327
|
+
|
|
328
|
+

|
|
329
|
+
|
|
330
|
+
### Privacy and security of the HTML
|
|
331
|
+
|
|
332
|
+
The HTML carries a default-deny Content-Security-Policy with the hash of its exact
|
|
333
|
+
inline script, inline styles and `data:` images. Paths in error messages and in the
|
|
334
|
+
command are rewritten as described under [Limitations](#limitations): the run directory
|
|
335
|
+
becomes the original path, the project directory becomes relative and your home becomes
|
|
336
|
+
`~`. Screenshots and error texts are reported as they are.
|
|
337
|
+
|
|
338
|
+
`CucumberJSONFormatter` also works without behave-hive:
|
|
339
|
+
|
|
340
|
+
```bash
|
|
341
|
+
behave features -f behave_hive.formatters.cucumber:CucumberJSONFormatter -o out.json
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Examples
|
|
345
|
+
|
|
346
|
+
[`example/`](example/) is a runnable project (Playwright and a local login page) with one example for each feature. Its [README](example/README.md) lists them with the command to run each one.
|
|
347
|
+
|
|
348
|
+
| Example | Shows |
|
|
349
|
+
|---|---|
|
|
350
|
+
| [`features/login.feature`](example/features/login.feature) | CSV table, hand-written table and a table that fails on purpose (screenshot as evidence). |
|
|
351
|
+
| [`features/csv/forms.feature`](example/features/csv/forms.feature) | The plain path (the default form), `read('...')` with single and double quotes, and a shared file through `..`. |
|
|
352
|
+
| [`features/csv/mixed_and_tagged.feature`](example/features/csv/mixed_and_tagged.feature) | CSV (plain path and `read()`) and hand-written tables in one outline, each with its own tags. |
|
|
353
|
+
| [`features/csv/special_characters.feature`](example/features/csv/special_characters.feature) | Pipes, commas and percent signs inside cells. |
|
|
354
|
+
| [`features/structure/background_and_rule.feature`](example/features/structure/background_and_rule.feature) | `Background` and `Rule` with CSV `Examples:`. |
|
|
355
|
+
| [`features/structure/step_data.feature`](example/features/structure/step_data.feature) | Step tables and docstrings, never read as `Examples:`. |
|
|
356
|
+
| [`configs/`](example/configs/) | Sequential, `scheme = feature` and TOML configurations. |
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
git clone https://github.com/albertor03/behave-hive && cd behave-hive/example
|
|
360
|
+
uv venv && uv pip install "behave-hive[allure,playwright]"
|
|
361
|
+
uv run python -m playwright install chromium
|
|
362
|
+
uv run behave-hive run # as configured in behave.ini
|
|
363
|
+
uv run behave-hive run --config configs/sequential.ini
|
|
364
|
+
uv run behave-hive run -- --tags=@smoke # only the @smoke Examples table
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
Gherkin in other languages works too: the `Examples:` keyword follows the feature's language, as shown in [`tests/fixtures/i18n/`](tests/fixtures/i18n/).
|
|
368
|
+
|
|
369
|
+
## Limitations
|
|
370
|
+
|
|
371
|
+
- **Lines in expanded features:** rows generated from a CSV, and everything after them in the file, report the lines of the expanded file. The `uri` is the original one and the HTML shows `csv:row`; files without CSV keep their lines.
|
|
372
|
+
- **`Path(__file__)` in steps:** steps run through symlinks in the expanded tree. Use `Path(__file__).resolve()` to reach files next to the original step.
|
|
373
|
+
- **Unbalanced batches:** units are split into consecutive chunks. Use `chunk = 1` for dynamic balancing, at the cost of one process per unit.
|
|
374
|
+
- **`allure-behave` is pinned to 2.16.2**, because the Allure formatter relies on its internals.
|
|
375
|
+
- **POSIX only (macOS and Linux):** the run lock uses `fcntl.flock`, interruption signals whole process groups (`os.killpg`) so browsers started by a step do not survive Ctrl+C, and the expanded copy of your features links every non-feature file with symlinks. None of these exist, or work without special privileges, on Windows. CI covers Linux and macOS only. WSL runs Linux and should work, but it is not tested.
|
|
376
|
+
- **Not supported:** `--stop`, `--dry-run`, `--include`, `--exclude`, `--name`, `--wip`, retries, and data sources other than CSV (JSON files are planned, see the [Roadmap](#roadmap)).
|
|
377
|
+
- **CSV access is not sandboxed:** a feature may reference any CSV readable by the
|
|
378
|
+
current user, including paths with `..`; its rows can appear in reports.
|
|
379
|
+
- **Retained run configuration:** `--keep-tmp` preserves private plans and
|
|
380
|
+
locations, including `-D key=value` arguments. These files are owner-only
|
|
381
|
+
(`0600`, inside a `0700` temporary directory); remove retained runs when no
|
|
382
|
+
longer needed. The results lock is also owner-only.
|
|
383
|
+
- **Report privacy:** behave-hive rewrites expanded roots, the working directory
|
|
384
|
+
and the home prefix in error messages to original relative paths or `~`.
|
|
385
|
+
The directly used Cucumber formatter (`behave -f`) has no run path map and
|
|
386
|
+
does not perform this rewriting. Screenshots and attached data are not scrubbed
|
|
387
|
+
and may contain sensitive application data; scenario inputs can also appear.
|
|
388
|
+
- **Expansion race window:** destination checks are repeated before deletion
|
|
389
|
+
and marker creation. This narrows, but does not eliminate, filesystem races.
|
|
390
|
+
|
|
391
|
+
## Roadmap
|
|
392
|
+
|
|
393
|
+
Next on the list:
|
|
394
|
+
|
|
395
|
+
- **Windows support:** replace the POSIX-only pieces described under [Limitations](#limitations) (file lock, process groups and symlinks) and add Windows to CI.
|
|
396
|
+
- **JSON data files:** read `Examples:` from a `.json` file, next to CSV, with the same plain-path form.
|
|
397
|
+
|
|
398
|
+
## Contributing
|
|
399
|
+
|
|
400
|
+
Pull requests are welcome. [CONTRIBUTING.md](CONTRIBUTING.md) explains how to set up the project, the checks that must pass and how CI works. [AGENTS.md](AGENTS.md) describes the layout and the conventions.
|
|
401
|
+
|
|
402
|
+
## Releasing
|
|
403
|
+
|
|
404
|
+
Releases are tagged and published to PyPI by a workflow; the maintainer's checklist is in [docs/RELEASING.md](docs/RELEASING.md).
|
|
405
|
+
|
|
406
|
+
## License
|
|
407
|
+
|
|
408
|
+
MIT, see [LICENSE](LICENSE).
|