You must add coverage keyword to your .gitlab-ci.yml See: https://docs.gitlab.com/ee/ci/testing/code_coverage/index.html

You can calculate coverage from the output

...
script:
    - awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", instructions, " instructions covered"; print 100*covered/instructions, "% covered" }' target/site/jacoco/jacoco.csv
  coverage: '/\d+\.\d+.%.covered/'
...

Example

clean-test-jacoco:
  image: maven:latest
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS clean verify
    - awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", instructions, " instructions covered"; print 100*covered/instructions, "% covered" }' target/site/jacoco/jacoco.csv
  coverage: '/\d+\.\d+.%.covered/'
  artifacts:
    paths:
      - target/site/jacoco/jacoco.xml
    reports:  
      coverage_report:
        coverage_format: jacoco
        path: target/site/jacoco/jacoco.xml

Also you can create a badge

!coverage
Answer from jschnasse on Stack Overflow
Top answer
1 of 2
3

You must add coverage keyword to your .gitlab-ci.yml See: https://docs.gitlab.com/ee/ci/testing/code_coverage/index.html

You can calculate coverage from the output

...
script:
    - awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", instructions, " instructions covered"; print 100*covered/instructions, "% covered" }' target/site/jacoco/jacoco.csv
  coverage: '/\d+\.\d+.%.covered/'
...

Example

clean-test-jacoco:
  image: maven:latest
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS clean verify
    - awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", instructions, " instructions covered"; print 100*covered/instructions, "% covered" }' target/site/jacoco/jacoco.csv
  coverage: '/\d+\.\d+.%.covered/'
  artifacts:
    paths:
      - target/site/jacoco/jacoco.xml
    reports:  
      coverage_report:
        coverage_format: jacoco
        path: target/site/jacoco/jacoco.xml

Also you can create a badge

!coverage
2 of 2
2

You should see them in the Tests tab on the Pipelines :

https://gitlab.com/{group}/{project}/-/pipelines/{pipeline_id}/test_report

Example :

You also have access to the report on the Merge Request if you have one open :

To see the coverage you need to configure the coverage keyword in the job :

coverage:
  script:
    - mvn clean install surefire-report:report
  image: maven:3.9.9-sapmachine-23
  stage: coverage
  coverage: /Total.*?([0-9]{1,3})%/
  artifacts:
    [...]

This will tell to Gitlab the regex to use to get the coverage based on your coverage tool, here Jacoco. Based on the documentation :

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 widget showing code coverage percentage

  • Merge request diff: Review which lines are covered by tests. Available with Cobertura and JaCoCo reports. Pipeline jobs: Monitor coverage results for individual jobs.

🌐
GitLab
gitlab.com › gitlab.org › gitlab foss › repository
doc/ci/testing/test_coverage_visualization/jacoco.md · f85a8fe60b6efd4c6bc272946db0bb304e5f0814 · GitLab.org / GitLab FOSS · GitLab
In this example, the mvn command generates the JaCoCo coverage report. The path points to the generated report. If the job generates multiple reports, use a wildcard in the artifact path · JaCoCo reports provide relative file paths but coverage ...
🌐
DevOpsSchool.com
devopsschool.com › blog › gitlab-code-coverage-in-java-with-gitlab-complete-guide
Gitlab – Code Coverage in Java with GitLab – Complete Guide
Clone the Repository: git clone https://gitlab.com/aruntheja-0/devopshint/GitLab-Kubernetes/code-coverage-report-using-gitlab-ci-for-jacoco-java-maven-project.git cd code-coverage-report-using-gitlab-ci-for-jacoco-java-maven-project
🌐
GitLab
gitlab.lexilogos.com › help › help
Jacoco · Code coverage · Testing · Ci · Help · GitLab
In this example, lines 83-86 show red bars for uncovered code, line 88 shows a green bar for covered code, and lines 87, 89-90 have no coverage data. To configure your pipeline to generate the coverage reports, add a job to your .gitlab-ci.yml file.
🌐
DEV Community
dev.to › barg › crack-the-code-seamless-coverage-reports-with-jacoco-and-s3-in-gitlab-ci-4ij2
Seamless Coverage Reports with JaCoCo and S3 in GitLab CI - DEV Community
May 13, 2024 - In this step, we're utilizing an image equipped with a script capable of converting a JaCoCo XML report to cobertura.xml. After the script is run and cobertura.xml report is generated we can use it to create a visualization of the coverage report in GitLab's UI. If you'd like to explore more about this functionality, you can access the GitLab documentation through the following link: ... If we add the coverage report to the GitLab's Merge request, it only provides a visual representation where covered code lines are highlighted in green and uncovered ones in red.
🌐
YouTube
youtube.com › devops hint
Java Code Coverage(JaCoCo) Report using GitLab CI for Java Maven project | JaCoCo with GitLab CI - YouTube
In this Video we are going to cover Java Code Coverage(JaCoCo) Report using GitLab CI for Java Maven project | JaCoCo with GitLab CI#jacocowithgitlab #javaco...
Published: August 29, 2023
Views: 1K
Top answer
1 of 2
7

In order to get ./gradlew test to output a summary of test coverage, I needed to add gradle-jacoco-log to my project.

plugins {
  id 'org.barfuin.gradle.jacocolog' version '2.0.0'
}

test {
  finalizedBy jacocoTestReport
}

jacocoTestReport {
  dependsOn test
}

Which gives me the following console output:

> Task :jacocoLogTestCoverage
Test Coverage:
    - Class Coverage: 100%
    - Method Coverage: 83.6%
    - Branch Coverage: 75%
    - Line Coverage: 85.5%
    - Instruction Coverage: 83.1%
    - Complexity Coverage: 82.5%

I can then choose to report Instruction Coverage to GitLab by adding the following to .gitlab-ci.yml:

test:
  stage: test
  script: gradle check
  coverage: '/    - Instruction Coverage: ([0-9.]+)%/'
2 of 2
0

GitLab Community Edition 15.7.6

parse_jacoco.sh

#!/bin/bash

# Check if the JaCoCo XML file path is provided
if [ $# -eq 0 ]; then
    echo "Please provide the JaCoCo XML report file path"
    exit 1
fi

JACOCO_XML=$1

# Check if the file exists
if [ ! -f "$JACOCO_XML" ]; then
    echo "File not found: $JACOCO_XML"
    exit 1
fi

# Ensure xmllint is installed
if ! command -v xmllint &> /dev/null; then
    echo "xmllint is not installed. Please install libxml2-utils"
    exit 1
fi

# Define a function to calculate coverage percentage
calculate_coverage() {
    local covered=$1
    local missed=$2
    local total=$((covered + missed))
    if [ $total -eq 0 ]; then
        echo "0.0"
    else
        echo "scale=1; $covered * 100 / $total" | bc
    fi
}

echo "Coverage Data:"

# Initialize total instruction coverage counters
total_instruction_covered=0
total_instruction_missed=0

# Get coverage for various types
for type in INSTRUCTION BRANCH LINE COMPLEXITY METHOD CLASS; do
    covered=$(xmllint --xpath "sum(/report/counter[@type='$type']/@covered)" $JACOCO_XML)
    missed=$(xmllint --xpath "sum(/report/counter[@type='$type']/@missed)" $JACOCO_XML)
    total=$((covered + missed))
    coverage=$(calculate_coverage $covered $missed)
    echo "${type} Coverage: ${covered} covered, ${missed} missed, ${total} total (${coverage}%)"

    # Accumulate INSTRUCTION coverage as the total coverage
    if [ "$type" = "INSTRUCTION" ]; then
        total_instruction_covered=$covered
        total_instruction_missed=$missed
    fi
done

# Calculate and output total coverage (echo here for GitLab usage)
total_coverage=$(calculate_coverage $total_instruction_covered $total_instruction_missed)
echo "Total Coverage: ${total_coverage}%"

gitlab config

stages:
  - test
  - visualize

test-job:
  stage: test
  image: maven:3.3-jdk-8
  script:
    - mvn verify
  artifacts:
    when: always
    reports:
      junit:
        - target/surefire-reports/TEST-*.xml
        - target/failsafe-reports/TEST-*.xml
    paths:
      - target/site/jacoco/jacoco.xml
  tags:
    - docker-runner

coverage-job:
  stage: visualize
  image: alpine:latest
  before_script:
    - apk add --no-cache libxml2-utils
  script:
    - ./parse_jacoco.sh target/site/jacoco/jacoco.xml
  coverage: '/Total Coverage: (\d+\.\d+)%/'
  needs: ["test-job"]
  tags:
    - docker-runner

Find elsewhere
🌐
GitLab
gitlab.com › gitlab kubernetes › code coverage report using gitlab ci for jacoco java maven project
GitLab Kubernetes / code coverage report using gitlab ci for jacoco java maven project · GitLab
code coverage report using gitlab ci for jacoco java maven project · Project information · README · Created on · August 29, 2023 · Loading
🌐
Medium
medium.com › slickteam › manage-tests-and-coverage-in-gitlab-ci-4ccf0ddae34a
Manage tests and coverage in Gitlab-CI | by Ronan Barbot | Slickteam | Medium
May 11, 2021 - When you begin to have a lot of tests on your project, sometimes you want to know the coverage of these tests, to check how the code is covered and if some part are not enough tested. We use JaCoCo on our Java projects to measure test coverage, and we configured our CI to get the global coverage result in the UI. First, you must get the results from your tests report. Since we have 2 stages for testing, we want to have the global results with unit and integration test coverage merged. In the gitlab-ci.yml file, we have set JaCoCo report folders as artifacts for the 2 stages, and declare the stage unit_test as a dependency of IT_test.
🌐
OpenMSCG
software.rcc.uchicago.edu › help
Test coverage visualization · Merge requests · Project · User · Help · GitLab
The following gitlab-ci.yml example for Java or Kotlin uses Gradle to build the project and Jacoco coverage-tooling to generate the coverage artifact. You can check the Docker image configuration and scripts if you want to build your own image. GitLab expects the artifact in the Cobertura format, so you have to execute a few scripts before uploading it. The test-jdk11 job tests the code and generates an XML artifact.
🌐
GitHub
github.com › diffblue › gitlab › blob › master › doc › ci › testing › test_coverage_visualization.md
gitlab/doc/ci/testing/test_coverage_visualization.md at master · diffblue/gitlab
The following .gitlab-ci.yml example for Java or Kotlin uses Maven to build the project and JaCoCo coverage-tooling to generate the coverage artifact. You can check the Docker image configuration and scripts if you want to build your own image. GitLab expects the artifact in the Cobertura format, so you have to execute a few scripts before uploading it. The test-jdk11 job tests the code and generates an XML artifact.
Author: diffblue
🌐
GitLab
docs.gitlab.com › gitlab docs › use gitlab › use ci/cd to build your application › testing › code coverage › coverage visualization › cobertura
Cobertura coverage visualization | GitLab Docs
The following .gitlab-ci.yml example uses Mocha and nyc to generate the coverage artifact: test: script: - npm install - npx nyc --reporter cobertura mocha artifacts: reports: coverage_report: coverage_format: cobertura path: coverage/cobertura-coverage.xml · GitLab 17.6 and later supports JaCoCo format natively.
🌐
Akobor
akobor.me › posts › how-to-gitlab-test-coverage-with-jacoco-and-gradle
How to: GitLab test coverage with JaCoCo and Gradle
June 11, 2020 - # ... variables: JACOCO_CSV_LOCATION: '$CI_PROJECT_DIR/build/jacocoCsv' # ... stages: - test # ... test: stage: test script: # Any task that runs your tests - ./gradlew check - awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", instructions, " instructions covered"; print 100*covered/instructions, "% covered" }' $JACOCO_CSV_LOCATION
Top answer
1 of 9
47

It seems you forgot to add the calls to cat in your .gitlab-ci.yml file.

You should have something like that:

script:
    - mvn $MAVEN_CLI_OPTS test
    - cat target/site/jacoco/index.html

That being said, I don't think this is the best way of doing this, as you need to pollute your output with raw HTML in order to retreive the desired coverage value.

I would recommend using the method described in this pull request instead: https://github.com/jacoco/jacoco/pull/488

  • Keep the jacoco parts in your build.xml
  • Use this awk instruction to print the correct code coverage total:

    awk -F"," '{ instructions += $4 + $5; covered += $5 } END { print covered, "/", 
    instructions, "instructions covered"; print 100*covered/instructions, "% 
    covered" }' target/site/jacoco/jacoco.csv
    
  • Replace the Gitlab CI regexp with what the instruction returns: \d+.\d+ \% covered

Edit:

As of Gitlab 8.17, you can define the regexp directly inside the .gitlab-ci.yml file, as stated in the documentation.

It may seem superfluous, but if this regexp is now part of your repository history, you can change it alongside the other tools used to compute it.

2 of 9
19

GitLab employee here.

If your administrator has GitLab pages set up, you can see the URL that your artifact deployed to by going (on your project) to Settings -> Pages.

There you should see:

Congratulations! Your pages are served under: https://your-namespace.example.com/your-project

Click on that link and you should be good to go! Also we are expanding support for HTML artifacts. This issue and it’s related issues talk about existing and upcoming features that may expand on what you’ve built here.

🌐
GitLab
gitlab.com › gitlab.org › #227345
Support JaCoCo coverage reports for coverage visualization (#227345) · Issues · GitLab.org / GitLab · GitLab
July 8, 2020 - ### Intended users * [Delaney (Development Team Lead)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead) * [Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sasha-software-developer) * [Devon (DevOps Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#devon-devops-engineer) ### User experience goal Use the nice code coverage visualization feature without having to use outdated tool chains that lack support for modern language versions. ### Proposal It would be helpful, if there was a `artifacts:reports:jacoco` setting, for gathering coverage information from JaCoCo reports. ### Further details Cobertura is currently not well supported. For example cobertura or the cobertura-maven-plugin lacks proper Java8+ support.
🌐
GitLab
transfer.hft-stuttgart.de › help
Test coverage visualization · Testing · Ci · Help · GitLab
# Please define it first, or chose an existing stage like `deploy`. stage: visualize image: registry.gitlab.com/haynes/jacoco2cobertura:1.0.7 script: # convert report from jacoco to cobertura, using relative project path - python /opt/cover2cover.py build/jacoco/jacoco.xml $CI_PROJECT_DIR/src/main/java/ > build/cobertura.xml needs: ["test-jdk11"] artifacts: reports: coverage_report: coverage_format: cobertura path: build/cobertura.xml · The following .gitlab-ci.yml example for Python uses pytest-cov to collect test coverage data and coverage.py to convert the report to use full relative paths. The information isn't displayed without the conversion. This example assumes that the code for your package is in src/ and your tests are in tests.py:
🌐
Jfsanchez
notes.jfsanchez.net › 2022 › 07 › 15 › gitlab-coverage-from-jacoco-reports
GitLab coverage from JaCoCo reports – Notes
July 15, 2022 - stages: - test test:unit: stage: test image: openjdk:17-alpine script: | ./gradlew check # Print test coverage to console echo "coverage: $(cat build/reports/jacoco/test/html/index.html | grep -Eo 'Total[^%]*%' | grep -Eo '([0-9]{1,3})%')" coverage: "/coverage: ([0-9]{1,3}%)/" artifacts: reports: junit: - build/test-results/test/TEST-*.xml coverage_report: coverage_format: cobertura path: build/reports/cobertura/cobertura.xml · With this pipeline configuration, we should be able to collect the application test coverage and visualize this information inside the file diff view of our Merge Requests (MRs).