> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qlty.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Selective Coverage

Selective coverage lets you upload coverage from a run that intentionally executed only a subset of your test suite — for example, only the tests affected by a pull request's changes. Marking these uploads with the `--selection` flag tells Qlty the report is a partial view of your codebase, so Qlty computes [diff coverage](/coverage/metrics) from it while excluding it from total coverage.

## Background

On large codebases, running the full test suite on every pull request can be too slow or too expensive. Many teams adopt **selective testing** (also called test selection or test impact analysis): each PR build runs only the tests relevant to the code that changed.

Selective testing creates a problem for coverage reporting. A selected run only exercises a fraction of the codebase, so its coverage report looks like a massive coverage drop compared to full-suite reports. Without extra information, Qlty would:

* Report a misleading total coverage percentage for the PR, failing the Total Coverage commit status
* Risk polluting project dashboards and future comparisons with partial data

The `--selection` flag solves this. A selected report is trusted for the lines it covers — which is exactly what diff coverage needs — and is never treated as a measurement of your project's total coverage.

## How Selective Coverage Behaves

When you publish coverage with `--selection`:

* **Diff coverage works normally.** Changed lines in the pull request are evaluated against the selected report, and the Diff Coverage commit status and PR comments are posted as usual.
* **Total coverage is not computed.** The Total Coverage commit status is posted as passing with the message "Not computable for select coverage" rather than reporting a misleading percentage.
* **Project metrics are unaffected.** Selected reports never contribute to total coverage metrics, component coverage, coverage trends, or the file explorer.
* **Comparisons stay accurate.** A selected report is never used as the comparison base for another pull request, even in stacked-PR workflows.
* **Reports are labeled.** When all uploads for a commit are selected, the coverage report detail page in Qlty Cloud shows the report as "Selected."

## Publishing Selective Coverage

<Info>
  Selective coverage requires [Qlty CLI](/cli/quickstart) v0.633.0, GitHub Action `qltysh/qlty-action` v2.3.0, or CircleCI orb `qltysh/qlty-orb` 0.1.2 — or newer. Workflows pinned to `qlty-action/coverage@v2` or `qlty-orb@0.1` pick these up automatically; exact-version pins need a bump.
</Info>

Add the `--selection` flag to `qlty coverage publish` in the builds that run a selected subset of tests:

<CodeGroup>
  ```yaml GitHub Action lines theme={"system"}
  - uses: qltysh/qlty-action/coverage@v2
    with:
      token: ${{ secrets.QLTY_COVERAGE_TOKEN }}
      files: coverage/lcov.info
      selected: true
  ```

  ```yaml CircleCI Orb lines theme={"system"}
  version: 2.1
  orbs:
    qlty-orb: qltysh/qlty-orb@0.1
  jobs:
    build:
      steps:
        - checkout

        - qlty-orb/coverage_publish:
            files: coverage/lcov.info
            selected: true
  ```

  ```bash Qlty CLI lines theme={"system"}
  qlty coverage publish --selection coverage/lcov.info
  ```
</CodeGroup>

Publish full-suite runs without the flag, exactly as before. A typical setup:

* **Pull requests** run selected tests and publish with `--selection`
* **The default branch** (and/or a nightly build) runs the full suite and publishes without `--selection`, keeping total coverage, dashboards, and comparison baselines accurate

## Selected and Full Coverage Together

Selected and full uploads for the same commit and [tag](/coverage/tags) are assembled as **separate reports**: parts counting and completion signals are tracked independently for each, which is why the `--selection` flag must accompany every command for a selected report, including `qlty coverage complete`.

The two reports still work together when a commit has both. Total coverage comes from the full report only, while diff coverage evaluates changed lines against the combined coverage of both reports — a line counts as covered if any upload covers it. In Qlty Cloud, the coverage reports page shows one entry per commit and tag, and its detail page is labeled "Selected" only when every upload for that commit and tag was selected.

Upload order does not matter. If the selected report arrives first, the Total Coverage status reads "Not computable for select coverage" until the full report is processed, then updates to the actual percentage. If the full report arrives first, a later selected upload leaves the computed total in place.

You can also separate them by tag — for example, a full `unit` suite alongside a selected `integration` subset on the same PR:

<CodeGroup>
  ```bash Qlty CLI lines theme={"system"}
  # Full unit test run — totals computed for this tag
  qlty coverage publish --tag=unit unit.lcov

  # Selected integration subset — diff coverage only
  qlty coverage publish --tag=integration --selection integration.lcov
  ```
</CodeGroup>

Each tag receives its own commit statuses, so the `unit` tag reports total coverage while the `integration` tag reports "Not computable for select coverage."

## Selective Coverage with Server-Side Merging

Selective coverage composes with both [server-side merging](/coverage/merging) strategies. Because selected and unselected uploads assemble into separate reports, the selection flag is part of the report's identity — every command for the same report must agree on it.

### With `coverage complete`

Pass `--selection` to **both** `publish` and `complete`. A plain `qlty coverage complete` will not find a report whose parts were published with `--selection` (and vice versa):

<CodeGroup>
  ```yaml GitHub Action lines theme={"system"}
  - uses: qltysh/qlty-action/coverage@v2
    with:
      command: publish
      token: ${{ secrets.QLTY_COVERAGE_TOKEN }}
      files: part1.lcov
      incomplete: true
      selected: true

  - uses: qltysh/qlty-action/coverage@v2
    with:
      command: complete
      token: ${{ secrets.QLTY_COVERAGE_TOKEN }}
      selected: true
  ```

  ```yaml CircleCI Orb lines theme={"system"}
  - qlty-orb/coverage_publish:
      files: part1.lcov
      incomplete: true
      selected: true

  - qlty-orb/coverage_complete:
      selected: true
  ```

  ```bash Qlty CLI lines theme={"system"}
  qlty coverage publish --selection --incomplete part1.lcov
  qlty coverage publish --selection --incomplete part2.lcov
  qlty coverage complete --selection
  ```
</CodeGroup>

### With `total-parts-count`

Pass `--selection` on every part. Selected and unselected parts are counted independently, so a build can upload a full report and a selected report in parallel, each with its own parts count:

<CodeGroup>
  ```bash Qlty CLI lines theme={"system"}
  qlty coverage publish --selection --total-parts-count=2 part1.lcov
  qlty coverage publish --selection --total-parts-count=2 part2.lcov
  ```
</CodeGroup>

## Selective Coverage vs. Carry Forward Tags

Both features address selective testing, at different granularities:

* Use [carry forward tags](/coverage/carry-forward-tags) when entire suites (tags) are skipped for some commits — Qlty reuses each tag's most recent report so combined coverage stays complete.
* Use selective coverage when a run executes a partial, changing subset of tests *within* a suite — the report is never a complete picture for its tag, so it should only feed diff coverage.

Carry forward requires that a tag report the same set of tests each time it runs; selected runs break that assumption, which is exactly why they need the `--selection` flag instead.

## Best Practices

* **Keep a full-coverage source of truth.** Publish full-suite (unselected) coverage on your default branch so total coverage metrics, trends, and PR comparison baselines remain meaningful.
* **Use selective coverage on pull requests only.** Publishing a selected report to your default branch means no new total coverage data for that branch until the next full run.
* **Gate PRs with Diff Coverage.** With selective testing, the Diff Coverage commit status is your primary quality gate; the Total Coverage status will pass with "Not computable for select coverage." If you prefer, you can disable the Total Coverage status entirely under Project Settings → Code Review.

## Troubleshooting

### `coverage complete` reports "Coverage report not found"

If parts were published with `--selection`, the completion signal must also include it: `qlty coverage complete --selection`. Selected and unselected uploads assemble into separate reports, and each must be completed on its own.

### Total coverage status shows an unexpected drop

Check that every build publishing a partial test run passes `--selection`. A selected run published without the flag is treated as a full report and will be compared against full-suite baselines.

### Diff coverage is missing changed lines

Selective testing determines which tests run, and therefore which lines the coverage report can mark as covered. If changed lines show as uncovered, verify your selective testing setup actually ran the tests that exercise them.

## See Also

* [Coverage Merging](/coverage/merging) - Combine multiple coverage reports
* [Coverage Tags](/coverage/tags) - Track different types of tests separately
* [Carry Forward Tags](/coverage/carry-forward-tags) - Reuse coverage when suites are skipped
* [Commit Statuses](/coverage/commit-statuses) - Configure coverage gates on pull requests
