Skip to content

Run benchmark tests in CI only when benchmark code changes - #43

Merged
mykolamelnykml merged 1 commit into
mainfrom
ci-skip-slow-benchmarks
Oct 5, 2026
Merged

mykolamelnykml merged 1 commit into
mainfrom
ci-skip-slow-benchmarks

Conversation

@mykolamelnykml

Copy link
Copy Markdown
Contributor

The backend test job took about 6 minutes, much longer than any other job. pytest accounted for 327s of it (707 tests).

Where the time went

A local --durations profile of the full suite (188s):

  • Most of the time is benchmark tests. Each test that needs a scored submission spends about 3.3s in fixture setup, because finalize runs the real pdfredeval scorer inline (Q_CLUSTER is synchronous in tests).
  • The scorer parity test takes 17s on its own.
  • Without benchmark tests the suite runs in 14s locally.

What changes

  • Marking (backend/conftest.py): a collection hook marks tests benchmark if they are in a test_benchmark* or test_mcp_benchmarks file, or use benchmark_case, case_files or run_files. That catches four tests in other files (API keys, CLI login, badges), and new tests are marked without anyone remembering to. Both markers are registered in pyproject.toml, since --strict-markers is on.

  • Smoke test: test_an_uploaded_submission_is_scored_and_waits_for_review is marked benchmark_smoke. It covers the whole pipeline: case published, output uploaded, scored by the real scorer, waiting for review.

  • CI runs pytest -m "not benchmark or benchmark_smoke" (557 of 707 tests). It no longer installs tesseract-ocr, which only the parity test needs; the smoke test passes with tesseract unavailable.

  • New Benchmarks workflow (.github/workflows/benchmarks.yml) runs pytest -m benchmark (151 tests), with tesseract installed. It runs on PRs and pushes to main that touch:

    • backend/apps/benchmarks/**
    • the scorer submodule
    • the benchmark tests and fixtures
    • backend/conftest.py
    • the workflow file itself

    It can also be started by hand from the Actions tab. It is a separate workflow because paths filters a whole workflow, and because deploy.yml waits on "CI", which this must not hold up.

  • make backend-test-fast runs what CI runs. make backend-test still runs everything.

  • DEVELOPMENT.md and CLAUDE.md describe the split.

Trade-off

Coverage in the main CI run drops from 95% to 86%, almost all of it in apps/benchmarks/. The Benchmarks workflow covers that code when it changes. What isn't covered: a change outside those paths that breaks a benchmark test, for example a catalog model. The docs say to run make backend-test or start the workflow by hand in that case.

Testing

  • make backend-test-fast: 557 passed, 150 deselected, in 14s (the full suite was 188s locally).
  • pytest -m benchmark: 151 passed, in 2m57s.
  • make backend-lint passes, and the workflow YAML parses with one shared path list for both triggers.
  • This PR changes conftest.py and benchmarks.yml, so the Benchmarks workflow should run on it. That run is the check that the new workflow works on GitHub.

The backend CI job took about 6 minutes, 327s of it in pytest. Most of that was
benchmark tests: each one that needs a scored submission spends about 3.3s
running the real scorer inline in fixture setup, and the scorer parity test
takes 17s. Locally the full suite is 188s; without those tests it is 14s.

- conftest.py marks benchmark tests `benchmark`: every test in a
  test_benchmark* or test_mcp_benchmarks file, and any test using
  benchmark_case, case_files or run_files. New tests are marked without anyone
  remembering to.
- One end-to-end test (upload, score, waiting for review) is also marked
  `benchmark_smoke`. CI runs `-m "not benchmark or benchmark_smoke"` and no
  longer installs tesseract, which only the parity test needs.
- A new Benchmarks workflow runs the full set, with tesseract, when a PR or a
  push to main touches apps/benchmarks/, the scorer submodule, the benchmark
  tests and fixtures, or conftest.py. It can also be started by hand. It is
  separate from CI so it never holds up a deploy.
- `make backend-test-fast` runs what CI runs. DEVELOPMENT.md and CLAUDE.md
  describe the split, including the gap: a change elsewhere that breaks a
  benchmark test is not caught.

Coverage in the main CI run drops from 95% to 86%, almost all of it in
apps/benchmarks/, which the Benchmarks workflow covers when that code changes.
@mykolamelnykml
mykolamelnykml merged commit 65494d0 into main Oct 5, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant