doc/ci/testing/code_coverage/_index.md
{{< details >}}
{{< /details >}}
Configure code coverage to track and visualize how much of your source code is covered by tests. You can:
coverage keyword.artifacts:reports:coverage_report keyword.Use the coverage keyword to monitor your test coverage and enforce coverage requirements in merge requests.
With coverage reporting, you can:
To configure coverage reporting:
Add the coverage keyword to your pipeline configuration:
test-unit:
script:
- coverage run unit/
coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
test-integration:
script:
- coverage run integration/
coverage: '/TOTAL.+ ([0-9]{1,3}%)/'
Configure the regular expression (regex) to match your test output format. See coverage regex patterns for common patterns.
To aggregate coverage from multiple jobs, add the coverage keyword to each job you want to include.
Optional. Add a coverage check approval rule.
The following sample regex patterns were designed to parse coverage output from common test coverage tools.
Test the regex patterns carefully. Tool output formats can change over time, and these patterns might no longer work as expected.
<!-- vale gitlab_base.Spelling = NO --> <!-- Verify regex patterns carefully, especially patterns containing the pipe (`|`) character. To use `|` in the text of a table cell (not as cell delimiters), you must escape it with a backslash (`\|`). Verify all tables render as expected both in GitLab and on `docs.gitlab.com`. See: <https://docs.gitlab.com/user/markdown/#tables> -->{{< tabs >}}
{{< tab title="Python and Ruby" >}}
| Tool | Language | Command | Regex pattern |
|---|---|---|---|
| pytest-cov | Python | pytest --cov | /TOTAL.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/ |
| Simplecov-html | Ruby | rspec spec | /Line\sCoverage:\s\d+\.\d+%/ |
{{< /tab >}}
{{< tab title="C/C++ and Rust" >}}
| Tool | Language | Command | Regex pattern |
|---|---|---|---|
| gcovr | C/C++ | gcovr | /^TOTAL.*\s+(\d+\%)$/ |
| tarpaulin | Rust | cargo tarpaulin | /^\d+.\d+% coverage/ |
{{< /tab >}}
{{< tab title="Java and JVM" >}}
| Tool | Language | Command | Regex pattern |
|---|---|---|---|
| JaCoCo | Java/Kotlin | ./gradlew test jacocoTestReport | /Total.*?([0-9]{1,3})%/ |
| Scoverage | Scala | sbt coverage test coverageReport | /(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/ |
{{< /tab >}}
{{< tab title="Node.js" >}}
<!-- markdownlint-disable MD056 -->| Tool | Command | Regex pattern |
|---|---|---|
| tap | tap --coverage-report=text-summary | /^Statements\s*:\s*([^%]+)/ |
| nyc | nyc npm test | `/All files[^|]*\ |
| jest | jest --ci --coverage | `/All files[^|]*\ |
| node:test | node --experimental-test-coverage --test | `/all files[^|]*\ |
{{< /tab >}}
{{< tab title="PHP" >}}
| Tool | Command | Regex pattern |
|---|---|---|
| pest | pest --coverage --colors=never | /Statement coverage[A-Za-z\.*]\s*:\s*([^%]+)/ |
| phpunit | phpunit --coverage-text --colors=never | /^\s*Lines:\s*\d+.\d+\%/ |
{{< /tab >}}
{{< tab title="Go" >}}
| Tool | Command | Regex pattern |
|---|---|---|
| go test (single) | go test -cover | /coverage: \d+.\d+% of statements/ |
| go test (project) | go test -coverprofile=cover.profile && go tool cover -func cover.profile | /total:\s+\(statements\)\s+\d+.\d+%/ |
{{< /tab >}}
{{< tab title=".NET and PowerShell" >}}
<!-- markdownlint-disable MD056 -->| Tool | Language | Command | Regex pattern |
|---|---|---|---|
| OpenCover | .NET | None | /(Visited Points).*\((.*)\)/ |
| dotnet test (MSBuild) | .NET | dotnet test | `/Total\s*\ |
| Pester | PowerShell | None | /Covered (\d{1,3}(\.|,)?\d{0,2}%)/ |
{{< /tab >}}
{{< tab title="Elixir" >}}
| Tool | Command | Regex pattern |
|---|---|---|
| excoveralls | None | /\[TOTAL\]\s+(\d+\.\d+)%/ |
| mix | mix test --cover | /\d+.\d+\%\s+|\s+Total/ |
{{< /tab >}}
{{< /tabs >}}
<!-- vale gitlab_base.Spelling = YES -->Use the artifacts:reports:coverage_report
keyword to view which specific lines of code are covered by tests in merge requests.
You can generate coverage reports in these formats:
Coverage visualization uses artifacts reports to:
Coverage files are parsed in a background job, so there might be a delay between pipeline completion and the visualization appearing in the merge request.
By default, coverage visualization data expires one week after creation.
To configure coverage visualization:
Configure your test tool to generate a coverage report.
Add the artifacts:reports:coverage_report configuration to your pipeline:
test:
script:
- run tests with coverage
artifacts:
reports:
coverage_report:
coverage_format: cobertura # or jacoco
path: coverage/coverage.xml
For language-specific configuration details see:
Coverage reports for child pipelines appear in merge request diff annotations. However, parent pipelines cannot access these coverage reports for use in their own jobs.
Support for parent pipelines to fetch coverage reports for child pipelines is proposed in issue 285100.
{{< details >}}
{{< /details >}}
You can require specific users or a group to approve merge requests that reduce the project's test coverage.
Prerequisites:
To add a Coverage-Check approval rule:
Coverage-Check approval rule, select Enable.Coverage-Check as the Rule name.[!note] The
Coverage-Checkapproval rule requires approval when the merge base pipeline contains no coverage data, even if the merge request improves overall coverage.
After a pipeline runs successfully, you can view code coverage results in:
Merge request widget: See the coverage percentage and changes compared to the target branch.
Merge request diff: Review which lines are covered by tests. Available with Cobertura and JaCoCo reports.
Pipeline jobs: Monitor coverage results for individual jobs.
You can track the evolution of code coverage for your project or group over time.
To view the code coverage history for a project:
{{< details >}}
{{< /details >}}
To view the code coverage history for all projects in a group:
Share your project's code coverage status using pipeline badges.
To add a coverage badge to your project, see test coverage report badges.
Some test coverage tools output with ANSI color codes that aren't parsed correctly by the regular expression. This causes coverage parsing to fail.
Some coverage tools do not provide an option to disable color codes in the output. If so, pipe the output of the coverage tool through a one-line script that strips the color codes.
For example:
lein cloverage | perl -pe 's/\e\[?.*?[\@-~]//g'