GitLab coverage badge with pytest
4 min read

GitLab coverage badge with pytest

GitLab coverage badge with pytest

I recently added a coverage badge to my GitLab repo, but it took a little while and I hit a few snags along the way.

In the end it was a very simple thing to achieve, but the GitLab docs are a little confusing on the matter, so I thought a quick post on how to achieve this was in order, and hopefully it will save a few people some time.

First off, if you land on the GitLab page Test Coverage Visualisation, ignore it. This info isn't relevant for just displaying a badge. It's purely for saving coverage info so you can eg. show what lines are missing tests on the diff reports.

Not that this isn't a useful thing, but if all you're trying to do right now is add a coverage badge to your project or README, then this isn't relevant.

You don't need any artefacts to add a coverage badge!

Add the tests to .gitlab-ci.yml

First, you need to actually run the tests and coverage report in your pipeline.

For pytest, ensure you have both pytest, pytest-cov, and coverage installed. I personally have coverage[toml] installed so that I can put the config for this in pyproject.toml and avoid yet another config file in my project root!

I also tend to use pipenv for my projects, so my Pipfile looks like this:

[dev-packages]
django-debug-toolbar = "*"
pytest-django = "*"
pytest-cov = "*"
coverage = {extras = ["toml"], version = "*"}

(As you can see, for this particular project, I'm testing a Django application).

All that is needed for the CI/CD config is then:

stages:
  - static
  - test
  - deploy
  
...

test:
  stage: test
  before_script:
    - pip install pipenv
    - pipenv install --system --dev
    - pytest --version
  script:
    - pytest src --cov=src -vvv

This will show you the coverage information when the tests run.

Note: My directory structure is like this:

root_dir
|- .gitlab-ci.yml
|- pyproject.toml
|- ...
|- src   *<= Main project folder*
   |- project_files

Hence the pytest src in my script setup for the CI. If your code is all in root, or in some other directory, you will need to change this reference to src to something suitable for your project.

if you run that pytest src --cov=src -vvv command manually from project root, the result will end with something like this:

src/user/tests/test_views.py                  7      0      0      0   100%
src/user/tokens.py                            5      1      0      0    80%
src/user/urls.py                              4      0      0      0   100%
src/user/views.py                            52     21      2      0    57%
---------------------------------------------------------------------------
TOTAL                                      1150    291    148     13    69%

(No, I haven't finished adding all my tests yet ... I need to get better at a more TDD approach :D )

Configure GitLab

This is essentially all we need to do in our project. The rest is GitLab configuration.

First, we need to tell it how to extract the coverage percentage from your report. This can be done under Settings > CI/CD > General Pipelines. Scroll down a little until you find the field Test Coverage Parsing. Then enter this regex:

^TOTAL.+?(\d+\%)$

And save the changes.

Et voilĂ , GitLab now knows what your coverage percentage is. You can actually see this if you create a merge request - it should look something like this (once the pipeline finishes running):
merge-coverage

So now all we need to do is add the badge itself. There are 2 ways you can do this.

1. Add badge into a text file

GitLab provides links for adding the badge into markdown, html, and AsciiDoc. These links can be copied pasted from just beneath the Test Coverage Parsing setting. For example, the markdown text to paste is:

[![coverage report](https://gitlab.com/<project path>/badges/main/coverage.svg)](https://gitlab.com/<project path>/-/commits/main)

(Replacing <project path> with your own values of course)

2. Add badge to project

This option will add your badge to the project itself, so that it will display under the project description. These can be added under Settings > General > Badges.

To add a Pipeline Status badge for example, use the following settings:
Link: https://gitlab.com/%{project_path}/-/commits/%{default_branch}
Badge Image URL: https://gitlab.com/%{project_path}/badges/%{default_branch}/pipeline.svg

This will just work as the pipeline status is generated automatically from the latest pipeline by Gitlab.

For the coverage badge, using the settings you've just configured, use the following:
Link: https://gitlab.com/%{project_path}/-/commits/%{default_branch}
Badge Image URL: https://gitlab.com/%{project_path}/badges/%{default_branch}/coverage.svg

gitlab_badges

Displaying the coverage badge on branches

At the time of writing, it's not possible to get the coverage badges displaying on branches other than your main branch. It does look as though GitLab plan on implementing this though.

If you're reading this much later, check up on the status of Gitlab Issue Issue #27093 - Add ability to see code coverage badge on any branch to see if it has been implemented yet.

Enjoying these posts? Subscribe for more