pytest-gherkinator
A pytest plugin that controls the execution of pytest-bdd scenarios
according to the classification tags that
gherkinator renders into
generated *.feature files.
gherkinator transpiles centralized YAML test plans into Gherkin feature
files, rendering each plan's classification as a feature-level tag line:
@functional @stable @implemented @multi-node
Feature: GPU job submission
As a cluster user I want to be able to successfully submit jobs
to the partitions that I have access to.
Scenario: Submit a job
Given my user '<username>' exists
pytest-bdd turns Gherkin tags into pytest marks, and pytest-gherkinator
uses those marks to order, mark, and skip the collected scenarios. The plugin
is deliberately thin: its only contract with gherkinator is the set of
classification marks below, and it never reads gherkinator YAML test plans.
✨ Getting Started
Installation
Option 1: Install from PyPI
$ python3 -m pip install pytest-gherkinator
Option 2: Install from source
$ pip install .
Usage
What the plugin does
-
Sorts execution order by risk level, then by test type within each risk level:
Dimension Execution order Risk edge→beta→candidate→stableType functional→solution→reliability→security→performance -
Skips scenarios whose plan status is
plannedordeprecated, so onlyimplementedscenarios run. -
Registers all twelve classification values as
pytestmarks, so tag-derived marks are first-class citizens:pytest -m edge # only edge-risk scenarios pytest -m implemented # exclude planned/deprecated pytest -m "edge and functional" # combine classifications
Items sharing the same classification keep their original relative order, so scenarios that build state on each other within one feature file stay in definition order.
Classification rules
| Situation | Behavior |
|---|---|
Feature tagged @planned or @deprecated |
Scenario is skipped |
Feature tagged @implemented, or no status tag |
Scenario runs |
| No risk tag | Scenario runs after all risk-classified scenarios |
| No type tag | Scenario runs last within its risk level |
| No classification tags at all | Scenario runs after all classified items, in original order |
Conflicting tags (e.g. feature @edge plus scenario @beta) |
Scenario runs unclassified with a warning; the plugin never guesses |
Because classification is purely mark-driven, plain pytest tests marked
with @pytest.mark.edge, @pytest.mark.functional, and friends are ordered
exactly like BDD scenarios.
Run-time requirements
- Python 3.12+
pytest-bdd8.x
Limitations
pytest-xdistdistributes items to workers independently of execution order, so the ordering applies to single-process runs only.- Reordering plugins such as
pytest-randomlycan undo the plugin's ordering. - Custom plan tags (for example
@multi-node) become marks too, butpytest-gherkinatordoes not register them. Register custom marks in your own configuration to silencePytestUnknownMarkWarning.
🛠️ Development
The project uses just and uv for development, which provides some useful commands that will help you while hacking on pytest-gherkinator:
just fmt # Apply formatting standards to code
just lint # Check code against coding style standards
just typecheck # Run static type checks
just unit # Run unit tests
If you're interested in contributing your work to pytest-gherkinator, take a look at our contributing guidelines for further details.
🤝 Project and community
pytest-gherkinator is part of the tooling built around the
gherkinator test plan format,
is a project of the Ubuntu High-Performance Computing community.
Interested in contributing bug fixes, new features, documentation, or
feedback? You’ve come to the right place 🤩
Here’s some links to help you get started with joining the community:
Check out the gherkinator repository to learn
more about the format this plugin is built on.
📋 License
pytest-gherkinator is free software, distributed under the Apache License, v2.0. See the LICENSE file for further details.
Metadata
Release files for pytest-gherkinator 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_gherkinator-0.1.0.tar.gz | 41.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytest_gherkinator-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 53.9 kB
Release files / pytest_gherkinator-0.1.0.tar.gz
| Download URL | pytest_gherkinator-0.1.0.tar.gz |
|---|---|
| Size | 41.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
51ef65faf557b0924b1dd8bc98795a7237e0566e1d7246a2fb301ce4d82b10bd
|
|
BLAKE2b-256 checksum How to use checksums |
d4c407b4f237cb28cb1075cd2451227f07a58b56b2d8361846860296b0d28757
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pytest_gherkinator-0.1.0-py3-none-any.whl
| Download URL | pytest_gherkinator-0.1.0-py3-none-any.whl |
|---|---|
| Size | 12.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6d725f8c4c6a8c23934aa36752756817f179c19f9e71ac578208c6cf6de4be6b
|
|
BLAKE2b-256 checksum How to use checksums |
efdd34eccfad907da8c29c333528008be01dde707ec3e83a24e1e0a140d945d1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|