Skip to content

Commit 0cac9af

Browse files
authored
Document how to use coverage with test sharding (#23219)
1 parent 4d01975 commit 0cac9af

2 files changed

Lines changed: 74 additions & 0 deletions

File tree

docs/docs/python/goals/test.mdx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,76 @@ branch = true
578578

579579
When generating HTML, XML, and JSON reports, you can automatically open the reports through the option `--test-open-coverage`.
580580

581+
### Coverage with test sharding
582+
583+
When using the `--shard` flag to split tests across CI runners, each shard only exercises a fraction of your test targets. The per-shard coverage report will be artificially low. To get accurate coverage you need to combine the binary `.coverage` files from all shards.
584+
585+
#### Configuration
586+
587+
Add `"raw"` to your coverage reports so Pants writes the `.coverage` binary, and set `relative_files = true` so that `coverage combine` can match paths across different sandbox directories:
588+
589+
```toml title="pants.ci.toml"
590+
[coverage-py]
591+
report = ["raw", "xml", "console"]
592+
output_dir = "coverage-report"
593+
```
594+
595+
```ini title=".coveragerc"
596+
[run]
597+
relative_files = true
598+
branch = true
599+
```
600+
601+
:::caution Don't set `fail_under` in `[coverage-py]` when sharding
602+
Each shard only runs a fraction of your targets, so per-shard coverage is intentionally incomplete. Setting `fail_under` in `pants.toml` or `pants.ci.toml` will cause every shard to fail. Enforce the threshold after combining all shards instead.
603+
:::
604+
605+
#### Merging coverage reports
606+
607+
After all shards complete, collect their `.coverage` binaries, combine them with `coverage combine`, and generate the final report. The following example uses GitHub Actions, but the same approach applies to any CI system:
608+
609+
```yaml title=".github/workflows/ci.yml"
610+
# In each shard job: upload the coverage output
611+
- name: Upload coverage
612+
uses: actions/upload-artifact@v4
613+
with:
614+
name: coverage-shard-${{ matrix.shard }}
615+
include-hidden-files: true # .coverage is a dotfile
616+
path: coverage-report/
617+
618+
# Post-shard job: combine and enforce threshold
619+
coverage-report:
620+
needs: [test]
621+
runs-on: ubuntu-latest
622+
steps:
623+
- uses: actions/checkout@v4
624+
625+
- name: Download all shard coverage
626+
uses: actions/download-artifact@v4
627+
with:
628+
pattern: coverage-shard-*
629+
path: all-coverage/
630+
merge-multiple: false
631+
632+
- name: Combine and report
633+
run: |
634+
pip install coverage
635+
636+
idx=0
637+
for f in $(find all-coverage/ -name ".coverage" -not -name ".coverage.*"); do
638+
cp "$f" ".coverage.shard${idx}"
639+
idx=$((idx + 1))
640+
done
641+
642+
coverage combine --rcfile=.coveragerc .coverage.shard*
643+
coverage xml --rcfile=.coveragerc -o coverage-report/coverage.xml
644+
coverage report --rcfile=.coveragerc --fail-under=80
645+
```
646+
647+
:::note `global_report` and sharding
648+
With `[coverage-py] global_report = true`, per-shard reports show 0% for untouched files. Consider applying this setting only in the post-merge step rather than in `pants.ci.toml`.
649+
:::
650+
581651
## JUnit XML results
582652

583653
Pytest can generate [JUnit XML result files](https://docs.pytest.org/en/6.2.x/usage.html#creating-junitxml-format-files). This allows you to hook up your results, for example, to dashboards.

docs/docs/using-pants/advanced-target-selection.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,10 @@ For other goals, you can leverage shell piping to partition the input targets in
206206
pants list :: | awk 'NR % 5 == 0' | xargs pants package
207207
```
208208

209+
:::tip Coverage and sharding
210+
When using `--shard` with test coverage enabled, each shard only exercises a fraction of your targets, producing artificially low coverage numbers. You need to combine the coverage data from all shards in a post-shard CI step to get accurate results. To learn how to do this for Python see [Coverage with test sharding](../python/goals/test.mdx#coverage-with-test-sharding) for the full configuration and CI workflow.
211+
:::
212+
209213
## Using CLI aliases
210214

211215
If setting tags on individual targets is not feasible, there are a few other options available to refer to multiple targets.

0 commit comments

Comments
 (0)