pytest-devant-cloud
pytest plugin that streams runs, results, and per-test step trees into Devant.net while your suite runs.
Requirements
Python 3.10 or newer, and pytest 7 or newer.
Quick start
Install the plugin:
pip install pytest-devant-cloud
Point it at your project. Copy the token and project id from your Devant CI/CD settings:
export DEVANT_API_URL=https://acme.devant.net
export DEVANT_TOKEN=your-ci-token
export DEVANT_PROJECT_ID=42
Run pytest as you normally would:
pytest
Results show up in Devant while the suite is still running. There is nothing
to add to conftest.py; the plugin registers itself through pytest's
pytest11 entry-point group.
Upgrading from 0.1.x
Every environment variable was renamed, and all config defaults were removed. Upgrade without changing your CI and the plugin disables itself — your suite still passes, so reporting stops without anything failing.
| 0.1.x | 0.4.0+ |
|---|---|
DEVANT_CLOUD_API_URL (or DEVQ_API_URL) |
DEVANT_API_URL — required |
DEVANT_CLOUD_TOKEN (or DEVQ_TOKEN) |
DEVANT_TOKEN — required |
DEVANT_CLOUD_PROJECT_ID (or DEVQ_PROJECT_ID) |
DEVANT_PROJECT_ID — required |
DEVANT_CLOUD_RUN_NAME / DEVANT_CLOUD_RUN_ID |
DEVANT_RUN_NAME / DEVANT_RUN_ID |
0.1.x silently fell back to http://localhost:32124, the token
dev-admin-token, and project 1. A misconfigured CI job therefore either
401'd against a real tenant or filed its results under whatever project
happened to be id 1. There are no fallbacks now.
When configuration is missing or unusable, the plugin writes one JSON line to stderr and does nothing further:
{"level":"error","source":"pytest-devant-cloud","msg":"not configured","missing":["DEVANT_TOKEN"]}
After upgrading, grep your CI logs for "msg":"not configured".
Configuration
Configure with environment variables:
| Variable | Default | Notes |
|---|---|---|
DEVANT_API_URL |
required | Your tenant's URL |
DEVANT_TOKEN |
required | CI token from Settings → CI/CD |
DEVANT_PROJECT_ID |
required | Devant project id |
DEVANT_RUN_NAME |
pytest — <ISO date> |
Display name on the run |
DEVANT_RUN_ID |
(unset) | Attach to an externally-created run instead of creating one |
DEVANT_COVERAGE |
./coverage.xml, then <rootdir>/coverage.xml |
Cobertura report to submit as the run's coverage |
The same settings work as CLI flags, which win over the environment:
pytest \
--devant-api-url=https://acme.devant.net \
--devant-token=$DEVANT_TOKEN \
--devant-project-id=42
Turn the plugin off for a single run without uninstalling it:
pytest -p no:devant_cloud
Binding tests to cases
Each test maps to one case in Devant. The plugin chooses the case in this order:
- The
@pytest.mark.devant("DEF-AB12")marker on the test, if present. - An existing case whose name matches the test.
- A new case, created on the spot, with a key like
DEF-XYZ9.
An auto-created case is tied to the test's name and its place in the suite tree, so renaming or moving the test starts a fresh case. To keep a test's history across renames, copy its key from your Devant dashboard and pin it in source:
@pytest.mark.devant("DEF-XYZ9")
def test_login(): ...
Coverage
Coverage is read from the Cobertura XML pytest-cov writes, so you need
--cov-report=xml — an HTML-only report produces no XML and the upload
silently no-ops:
pytest --cov=myapp --cov-report=xml --cov-report=html
The plugin picks up coverage.xml from the working directory (then rootdir)
by default; point it elsewhere
with --devant-coverage path/to/coverage.xml or DEVANT_COVERAGE. Line and
branch percentages are sent; Cobertura carries no function metric, and
coverage.py's lines are its statements, so those two fields stay null.
A missing or unparseable report is warned-and-skipped, never fatal.
Suites
The plugin turns each test's location into a nested suite tree, built from the directories, module, and class around it. The leaf is the test function plus any parametrize id.
| Test | Suite path | Case name |
|---|---|---|
tests/test_x.py::test_foo |
tests / test_x | test_foo |
tests/api/test_x.py::TestThing::test_y[a-1] |
tests / api / test_x / TestThing | test_y[a-1] |
If you re-parent a suite by hand in the dashboard, the plugin leaves your change alone on later runs.
CI metadata
On GitHub Actions, GitLab CI, CircleCI, Jenkins, and Azure DevOps (or any
runner that sets CI=true), the plugin attaches the commit, branch, and
pull request to each run, so Devant can link a run back to the code that
triggered it.
Metadata
Release files for pytest-devant-cloud 0.7.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_devant_cloud-0.7.0.tar.gz | 29.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pytest_devant_cloud-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 56.4 kB
Release files / pytest_devant_cloud-0.7.0.tar.gz
| Download URL | pytest_devant_cloud-0.7.0.tar.gz |
|---|---|
| Size | 29.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
45da25c4016d2f364f6bb4300f46db5694e14f8277fc4148885013e5635529f2
|
|
BLAKE2b-256 checksum How to use checksums |
0c55534380c72f96026b00b27c76753b57b866a0b36447923280b36b8cc53b0c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.5
|
Release files / pytest_devant_cloud-0.7.0-py3-none-any.whl
| Download URL | pytest_devant_cloud-0.7.0-py3-none-any.whl |
|---|---|
| Size | 26.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c2779786ab214ed1cc70bc9e4636958c553fddd6733b4b8673c0e58397a27f0c
|
|
BLAKE2b-256 checksum How to use checksums |
3279d4c11ff6412962e6861e8b4c5119279957990d1ac72fb6736bce30f26066
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.5
|