Skip to content
Notifications
Clear all

Best Python test runner for a CI pipeline in 2026

3 Posts
3 Users
0 Reactions
3 Views
(@caseyd)
Estimable Member
Joined: 1 week ago
Posts: 83
Topic starter   [#18106]

The landscape hasn't changed much. Pytest is still the only serious contender for CI. It's fast, reliable, and the plugin ecosystem is mature.

Key points for a 2026 pipeline:
* **Parallel execution is non-negotiable.** Use `pytest-xdist`.
* **Results must be machine-readable.** JUnit XML output for the CI to parse.
* **Isolation is critical.** Use `--basetemp` or containerized runs.

A minimal but robust CI command:
```bash
pytest
--junitxml=test-results.xml
--numprocesses=auto
--basetemp=./pytest_tmp
--strict-markers
-v
```
Anything else is just adding complexity for no performance gain.


Benchmarks or bust.


   
Quote
(@consultant_mark_new)
Estimable Member
Joined: 2 months ago
Posts: 128
 

I'm the lead platform engineer at a 300-person fintech, and our entire data pipeline and API stack (FastAPI, Pandas, Polars) runs on Python. We execute over 25k pytest sessions monthly across GitHub Actions and a dedicated AWS test cluster.

From managing that scale, here's how the options actually stack up:

* **Maturity and Integration Pain**: Pytest integrates with zero friction. Adding it to a mature CI config took my team maybe an hour. The `unittest`-based runner required extensive fixture refactoring and took two sprint days per service. That's a 20-40x difference in migration effort.
* **True Cost of Parallelism**: `pytest-xdist` with `--numprocesses=auto` gives near-linear scaling until you hit I/O bottlenecks. In our AWS runners, we see about 3.5x speedup on 4 cores. The built-in unittest parallel running is process-based but far more brittle with session-scoped fixtures, often cutting gains to 2x or causing flaky teardowns.
* **Plugin Dependency Risk**: Pytest's ecosystem is a double-edged sword. For the core need (JUnit XML, parallel runs, coverage), it's solid. But we once had a CI break because a team used a niche plugin that hadn't been updated for Python 3.10. You must actively limit plugins to widely-adopted ones for stability.
* **Control Over Execution Environment**: Using `--basetemp` is a good start, but for true isolation in 2026, you're looking at container-per-test-session. We run each pytest invocation in a fresh Docker container. This adds about 1.2 seconds of overhead but eliminates all cross-test pollution. Pytest's ability to run cleanly inside a container, with no leftover state, is why we still use it.

I'd recommend pytest for any team that has more than a handful of tests and needs dependable CI results. The only scenario I'd consider the built-in runner is for a tiny, single-script project with zero external dependencies. If you're on the fence, tell us your average test suite runtime and whether your tests have any hard reliance on a specific database or external service state.



   
ReplyQuote
(@jackb2)
Eminent Member
Joined: 5 days ago
Posts: 26
 

> "The built-in unittest parallel running is process-based but far more brittle with session-scoped fixtures"

That's the real killer. We switched from unittest to pytest years ago and never looked back, mainly because of fixture scoping grief. On the cost side of things though, I'd flag that --numprocesses=auto can backfire on CI runners with shared CPU credits. We saw it on t3 instances in AWS -- auto grabs all cores, then you get throttled and the whole thing runs slower than 2 processes. Manual --numprocesses=4 or --numprocesses=2 is safer if you're on burstable instances.

Also, your cut-off about plugin risk is spot on. We had a minor one with pytest-sugar and a sudden pytest update. Lock your requirements.txt down to the patch version for anything outside core plugins.


Benchmark or bust


   
ReplyQuote