Files
upstream-mirror 64898b2c79
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
2026-09-15 15:05:30 +05:00

3.8 KiB

name: fix-backend-coverage description: Fix backend test coverage gaps. Use when CI output or test-backend --coverage reports missing lines, like "ERROR: path/to/file.py no longer has complete backend test coverage". argument-hint: "[test_module_or_file]"

Fix Backend Coverage

Fix backend test coverage gaps for Zulip's enforced 100% coverage files.

Use this skill when:

  • CI output contains "no longer has complete backend test coverage"
  • You need to verify coverage after modifying code in an enforced file
  • A file in not_yet_fully_covered has reached 100% and should be promoted to enforced, or coverage should be added to reach 100%

Workflow

1. Run coverage on the specific test module

IMPORTANT: Never run the full test suite with --coverage — it takes a very long time. Always target the specific test module that covers the file with missing coverage.

./tools/test-backend --skip-provision-check --coverage --no-cov-cleanup \
    --no-html-report zerver.tests.test_specific_module

If invoked with an argument, use it: $ARGUMENTS

If the CI output names the source file but not the test module, use git grep to find which test file imports or tests the relevant code.

2. Analyze missing lines

./.claude/skills/fix-backend-coverage/analyze-coverage <source_file_with_missing_coverage>

With no arguments, checks all enforced files for missing coverage (useful after a targeted test run to see what's still missing).

The script loads var/.coverage and reports:

  • Classification: ENFORCED (must be 100%) vs EXEMPT
  • Statement/excluded/missing counts and coverage percentage
  • Each missing line with 1 line of source context above and below

3. Fix each uncovered line using the right technique

Read the source at each missing line and classify it:

Line type Fix
Dead code (unreachable branch) Simplify/remove the dead branch
Error-only test path (assert, fail) Add # nocoverage comment
Missing test coverage Write a test that exercises the line
Newly 100% covered file Remove from not_yet_fully_covered in tools/test-backend

# nocoverage should only be used for lines that execute only when a test fails or for truly unreachable defensive code. Never use it to skip writing tests for reachable production code.

4. Verify

Re-run coverage on the same targeted test module and re-analyze:

./tools/test-backend --skip-provision-check --coverage --no-cov-cleanup \
    --no-html-report zerver.tests.test_specific_module
./.claude/skills/fix-backend-coverage/analyze-coverage <source_file>

Confirm 0 missing lines, then lint:

./tools/lint --skip-provision-check --fix --only=ruff,ruff-format <changed_files>

Coverage system reference

Config

  • Coverage config: tools/coveragerc
  • Coverage data: var/.coverage
  • Exclusion patterns in coveragerc: # nocoverage, if False:, raise NotImplementedError, raise AssertionError, if TYPE_CHECKING:, @abstractmethod, @skip, and ... (ellipsis)

Enforcement model

  • tools/test-backend defines two lists:
    • enforce_fully_covered: all .py files matching source_files globs minus those in not_yet_fully_covered
    • not_yet_fully_covered: files exempt from the 100% requirement
  • When a file in not_yet_fully_covered reaches 100%, it should be removed from the list to promote it to enforced status
  • Enforcement only runs in CI with full suite + --coverage; locally you check with targeted runs + analyze-coverage