pytest-sugar
A pytest plugin that replaces the default test runner output with a live progress bar, instant failure display, and colorized results.
Repository Health
Technical Analysis
pytest-sugar is a plugin for pytest that changes the default look and feel of test runs. Instead of the stock dot-per-test output, it swaps in a colorized, in-place status line per file, a live progress bar with percentage complete, and instant display of failures and errors the moment they happen rather than bunched at the end of the run. It works by replacing pytest’s built-in terminal reporter with a subclass that intercepts every test report and rewrites the terminal in place using ANSI cursor control, so long test suites are far easier to watch and to spot regressions in as they run.
Beyond the visual layer, it supports theming through a .pytest-sugar.conf ini file, has explicit compatibility handling for pytest-xdist parallel runs, and can detect and surface Playwright trace files next to failed tests so you can jump straight to playwright show-trace on a failure. It requires no code changes to adopt — installing it activates automatically, and -p no:sugar or --force-sugar toggle it off/on per run, including in non-interactive CI environments.
What You Get
- A live, colorized progress bar showing percent complete and which segments failed, updated in place as tests run
- Instant failure and error output printed the moment a test fails, instead of being deferred to an end-of-run summary
- Configurable color theme via a
.pytest-sugar.confini file (project-local or in your home directory) - Automatic pytest-xdist compatibility so the progress bar and counts stay correct under parallel test workers
- Playwright trace-file detection that prints a ready-to-run
playwright show-tracecommand next to failed tests - CLI flags (
--old-summary,--force-sugar,--sugar-trace-dir,--sugar-no-trace) to tune output for local runs or CI
Common Use Cases
- Making long or slow test suites easier to watch in real time during local development
- Getting immediate visibility into failing tests without scrolling through pass/fail dots first
- Producing more readable pytest output in CI logs via
--force-sugarwhen stdout isn’t a real terminal - Debugging Playwright-based end-to-end test failures by jumping straight to the recorded trace file
Under The Hood
Architecture
pytest-sugar is a single-module pytest plugin (pytest_sugar.py) registered through the standard pytest11 entry point declared in setup.py. Rather than only reacting to hooks, it takes over pytest’s own terminal reporter: pytest_configure (marked trylast) looks up the plugin manager’s registered terminalreporter, unregisters it, and installs a SugarTerminalReporter subclass of _pytest.terminal.TerminalReporter in its place. That subclass overrides the reporting hooks (pytest_collectreport, pytest_sessionstart, pytest_runtest_logreport, summary_stats, summary_failures, print_failure) to track per-file line positions and progress-bar state in module-level and instance globals, then repaints already-written terminal lines using raw ANSI cursor-movement escape codes. A small DeferredXdistPlugin is conditionally registered to keep test counts and the progress bar accurate when pytest-xdist distributes tests across workers. This approach gives full control over the terminal output, but ties the plugin’s correctness to pytest’s internal (non-public) _pytest reporter APIs, so a pytest core release that changes those internals is the primary architectural risk.
Tech Stack
The project targets Python 3.10+ and pytest 7+, with termcolor as its only runtime dependency for ANSI coloring. Packaging is handled by classic setuptools (per [build-system] in pyproject.toml) even though the file also carries Poetry-style metadata tables, suggesting a partial migration between tooling. Development tooling is comprehensive: black, flake8, and isort run through pre-commit, and tox drives a support matrix across multiple Python versions (3.10 through 3.14), pytest versions, and pytest-xdist, executed in GitHub Actions alongside a dedicated QA environment and an automated PyPI deploy job gated on the main branch.
Code Quality
The test suite (test_sugar.py) uses pytest’s own pytester fixture to run sample suites under faketests/ twice per scenario — once with the plugin disabled (-p no:sugar) and once with it forced on (--force-sugar) — then asserts the parsed pass/fail/skip/xfail counts are identical between the two runs. That’s a deliberate black-box invariant check: sugar’s cosmetic changes must never alter what pytest actually reports. Type hints are used throughout the reporter class and helper functions, including references to pytest’s private _pytest types, though there’s no dedicated mypy configuration enforcing them in CI. Error handling is narrow and intentional — a targeted try/except around Playwright trace-file lookups — rather than broad, defensive catching. Linting and formatting are enforced via pre-commit (black, flake8, isort), and CI runs the full tox matrix on every push and pull request.
What Makes It Unique
pytest-sugar is one of the longest-running plugins in the “prettier pytest output” niche, and its main technical distinction is committing fully to replacing the core terminal reporter rather than layering cosmetic hooks on top of the default one — giving it line-level control to redraw already-printed output as a live progress bar with per-segment pass/fail coloring. Its Playwright trace-file integration is a more recent, narrowly scoped addition: it recognizes the conventional test-results/<nodeid>/trace.zip layout Playwright’s pytest integration produces and surfaces a ready-to-copy playwright show-trace command directly beneath a failing test, saving a manual directory hunt after end-to-end test failures.