C.W.K.
Stream
Lesson 13 of 13 · published

Parallel Jobs

~12 min · parallel, jobs, split

Level 0Apprentice
0 XP0/101 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

Wall-clock time is the metric

If your test suite takes 30 minutes serial, splitting it across 6 parallel jobs brings the wall clock to ~5 minutes (plus a fixed checkout/install overhead per shard). On a paid runner pricing model, you spend the same minutes — but the developer waits 5 minutes instead of 30.

How to split tests

  • By directorypytest tests/api/ in one job, pytest tests/db/ in another.
  • By markerpytest -m 'unit' vs -m 'integration'.
  • By auto-shardpytest-xdist --dist=loadgroup -n 4 splits within a single runner; combine with matrix to split across runners.
  • By time-bucket — record per-test timing, group into buckets of equal duration. pytest-split does this.

Coordination challenges

  • Each shard does its own install. Cache aggressively.
  • Coverage reports must be merged across shards. Use coverage combine.
  • Flaky tests are amplified by sharding — re-run only the failing shard.

Code

Sharded pytest with pytest-split·yaml
  test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v3
      - run: uv sync --all-extras --dev
      - name: Run shard ${{ matrix.shard }} of 4
        run: uv run pytest --splits 4 --group ${{ matrix.shard }} --cov=src --cov-report=xml:coverage.${{ matrix.shard }}.xml
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-${{ matrix.shard }}
          path: coverage.${{ matrix.shard }}.xml

  coverage:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v4
        with: { pattern: coverage-*, merge-multiple: true }
      - run: pip install coverage && coverage combine && coverage report

External links

Exercise

Time your test suite serial. If it's over 10 minutes, split it 4-way with pytest-split. Compare wall-clock and total minutes. The wall-clock should drop ~3.5×; total minutes should be roughly stable plus per-shard overhead.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.