pytest-deck
An interactive browser dashboard for pytest. Collect your suite as a foldable tree, pick what to run with checkboxes or marker chips, and watch results stream in test by test, with tracebacks and captured output one click away.
Its defining promise: a deck run matches a real command-line pytest run.
Every collect, reload, and run is a fresh python -m pytest subprocess, never
in-process. What you see in the browser is what your terminal would say, and a
crashing or hanging test can't take the dashboard down with it.
Beta. Collect, select, run with live streaming, reload with diff, plugin switches, coverage down to a source gutter, benchmark timings, and per-test attachments all work. See the changelog and the docs for the full picture.
Install
pip install pytest-deck
Quick start
pytest-deck is a pytest plugin. Launch the dashboard with --deck:
pytest --deck # dashboard for the current project (rootdir)
pytest --deck path/to/tests # dashboard for a specific path
Nothing runs in the terminal. The deck prints its URL
(http://127.0.0.1:8765/ by default); open it in your browser and your suite
is there as a foldable tree.
Without --deck the plugin is inert: your normal pytest runs are completely
unaffected.
To see everything at once, point the deck at this repo's
examples/ suite.
Install the plugins you want to try and run
pytest --deck examples/.
For the full tour, start with the quickstart.
Features
The live basics
- A foldable file → class → test → parametrized-variant tree with rollup counts on every group.
- Select with checkboxes, marker chips that bulk-select every matching
test, and
-k/-mexpression fields. - Hit ▶ Run and PASS / FAIL / ERROR / SKIP stream in live as each test
finishes, tracebacks in pytest's own colors, captured output alongside. The
run summary's
FAILEDlines carry the same clickable badge, and every traceback has a copy button. - Re-run failed: one click re-runs everything currently failed or errored, regardless of the selection.
- ↻ Collect to re-collect after an edit: added, removed, and changed tests are flagged, and selection plus results are preserved for tests that still exist.
Plugins
Installed plugins appear as switches in the sidebar, each with a typed config form, so you never have to hunt through a plugin's flags. Switches ship ready-made for:
- pytest-cov
- pytest-benchmark
- pytest-mpl
- pytest-metadata
- pytest-mock
- pytest-asyncio
- pytest-django
For any other plugin, a one-file TOML description (a manifest) in
.pytest-deck/plugins/ adds a switch of your own.
Your ini addopts aren't lost either. Each token either prefills a switch's
config form, follows its plugin's switch automatically, or shows up as a
clickable suggestion chip. Nothing is dropped silently.
→ Plugins guide · Writing your own manifest
Standalone server
The dashboard also runs without the pytest CLI:
pytest-deck path/to/tests # console script
python -m pytest_deck.server path/to/tests
One difference from pytest --deck path/to/tests: the standalone command
roots the project at the path you give, with no walk up to find the root.
Options: --host (default 127.0.0.1), --port (must be free; default:
first free port from 8765, up to 8785, announcing any fallback), and
--open (open a browser tab on launch; off by default). Through pytest,
--deck-port is the same as --port.
How it works
Every collect and run is a fresh pytest subprocess. A small plugin injected into those subprocesses emits structured JSON on a dedicated file descriptor, a private channel that keeps machine-readable results separate from pytest's captured output. A FastAPI backend streams those events to the browser over Server-Sent Events. The deep dive lives in the docs: How It Works.
Documentation
Full documentation is at pytest-deck.readthedocs.io:
- Getting started: install and first run.
- User guide: the dashboard, plugins, coverage, attachments, troubleshooting.
- Plugin integration: how manifests work and how to write one.
- How it works: architecture and design invariants.
Limitations
- pytest-xdist is not supported. The deck reads each run's results over a
dedicated pipe, and xdist's worker subprocesses don't inherit that pipe, so
results would never reach the dashboard. The deck therefore forces
-p no:xdistfor its own runs: if xdist is installed in your project it stays disabled here, and runs are serial. - Localhost only. The server binds to
127.0.0.1with no auth, and it executes your test code. Don't expose it on an untrusted network.
Development
Requires Python 3.11+ and Node 24 LTS (for the frontend build).
# backend
pip install -e ".[test]"
pytest # the full suite
# frontend (Svelte 5 + Vite); builds into pytest_deck/static/
cd frontend
npm install
npm run build
Run the full matrix (Python 3.11 to 3.14 × pytest 8/9, plus the frontend build)
with tox. The
development guide
has the details.
pytest-deck is written with AI assistance. The design decisions, the reviews, and the bugs are mine. AI-assisted contributions are welcome here, held to the same bar.
License
MIT
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 pytest_deck-0.1.1.tar.gz.
File metadata
- Download URL: pytest_deck-0.1.1.tar.gz
- Upload date:
- Size: 485.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb52cf12afc2e46920444b55fbe4ad9bcc90eef6851806f182bdff62db603486
|
|
| MD5 |
8c7b51f41b6ca4aaa69b22010f3a6e38
|
|
| BLAKE2b-256 |
a0b226ae40130986a7dd85572d4823d6d1096d3d213d3a47777ce487bfb1bf99
|
File details
Details for the file pytest_deck-0.1.1-py3-none-any.whl.
File metadata
- Download URL: pytest_deck-0.1.1-py3-none-any.whl
- Upload date:
- Size: 118.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b68456cbdd1803ba7cfaff6331dceeeede778930687ae2ba867a9b4959d902b4
|
|
| MD5 |
721e7d8e73a6e0b2ae298d67d8a7bf00
|
|
| BLAKE2b-256 |
b5e888656a2787b6685d4a0795468f7c65b0911b712dc8fc68e0169bea3dda0e
|