Every now and then it seems like a good idea to re-read the documentation of tools you've been using for years. In most cases you just update to the latest version and everything works fine, but you may not be using the latest features.
So here are some things I already knew, and some things I newly discovered when I re-read GitLab's documentation after stumbling over this tweet:
TLDR
You may see all of the below in action in this demo merge request.
Unit test reports
The first thing I found is that GitLab has support for the JUnit XML file format and PHPUnit is able to write a JUnit XML file report. By configuring PHPUnit to create a JUnit XML and by declaring this an artefact in .gitlab-ci.yml
you can have a nice unit test overview in the pipeline itself and the merge request.
Add the JUnit logging to your phpunit.xml
file:
<phpunit>
<!-- ... -->
<logging>
<junit outputFile="junit.xml" />
</logging>
<!-- ... -->
</phpunuit>
And tell GitLab-CI via the .gitlab-ci.yml
about this report:
Unit Tests:
stage: test
script:
- ./vendor/bin/phpunit
artifacts:
reports:
junit: junit.xml
What you get is a nice overview of the tests run, the time it took to run every single one in the pipeline and in the merge request overview page.
You may find more hints about this feature in the unit test reports section of the official GitLab docs.
Test code coverage
GitLab can show you the code coverage in percent you have with your tests at various places:
- as a badge via a predefined URL
- in a merge request, also indicating if merging this code would increase or decrease code coverage
- and as a nice graph over time in the Analytics > Repository overview per project and on a group level
Add a simple coverage report to phpunit.xml
:
<phpunit>
<!-- ... -->
<coverage>
<report>
<text outputFile="php://stdout"
showUncoveredFiles="false"
showOnlySummary="true" />
</report>
</coverage>
</phpunuit>
And tell GitLab-CI via the .gitlab-ci.yml
about this report (add the coverage
key):
Unit Tests:
stage: test
script:
- XDEBUG_MODE=coverage ./vendor/bin/phpunit
coverage: '/^\s*Lines:\s*\d+.\d+\%./'
This assumes you are using Xdebug and have it already installed in the image your are using to run the tests in GitLab CI. Find the documentation about this feature here.
Test code coverage visualization
This one was an absolut blast for me. While you are gathering code coverage to have a line coverage number you can see everywhere in GitLab, you can also create a line coverage report as Cobertura XML file format with PHPUnit that GitLab can read and show you covered and uncovered lines directly in the merge requests diff view.
Add a the cobertura coverage report to phpunit.xml
:
<phpunit>
<!-- ... -->
<coverage>
<!-- ... -->
<report>
<!-- ... -->
<cobertura outputFile="cobertura.xml" />
</report>
</coverage>
<!-- ... -->
</phpunuit>
And tell GitLab-CI via the .gitlab-ci.yml
about this report (add the coverage_report
artifacts key):
Unit Tests:
stage: test
script:
- XDEBUG_MODE=coverage ./vendor/bin/phpunit
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: cobertura.xml
Read more about this awesome feature in the test coverage visualization documentation alongside some screenshots.
Code style violations
PHP CS Fixer is able to generate a GitLab formatted report which GitLab can use to show you any new violations in the code or even if code style violations have been tackled.
Run PHP CS Fixer with the --format=gitlab
argument and tell GitLab CI via the .gitlab-ci.yml
where the report is to be found:
Coding guidelines:
stage: static analysis
script:
- ./vendor/bin/php-cs-fixer fix -v --dry-run --format=gitlab --using-cache=no src/ > gl-cs-fixer.json || exit 0
artifacts:
reports:
codequality: gl-cs-fixer.json
I hope this small overview helps you get more out of GitLab and GitLab CI when working with PHP projects.
Top comments (1)
Thanks for sharing!
I gave it a try and was running into an issue with the codequality report. I had the job marked to only run for Merge Requests which caused it not to work as a baseline report was missing. It seems the job needs to run on your master/main branch to have it properly working.