Chapter 24Lesson 05~215 minutes

Checkpoint Lab — Test Reports, Coverage, JUnit, Code Quality, Browser Performance, Accessibility, and Pipeline Feedback

Produce two structured reports from a disposable test suite, prove their source and raw semantics, repair one malformed or misleading report, and assemble an evidence packet suitable for review.

CheckpointJUnitCoverage reportEvidence packetCleanup

Learning objectives

Checkpoint objectives

  • Produce one JUnit report and one Cobertura coverage report from a disposable test suite.
  • Verify report schema, checksums, source SHA, pipeline/job identity, and expected GitLab feedback independently.
  • Predict state changes before running the pipeline and compare them with observed state.
  • Inject one malformed or misleading report condition, preserve first-failure evidence, and repair the smallest safe scope.
  • Document report access, retention, tool assumptions, and the bridge from quality feedback to Chapter 25 security scanning.

1. Checkpoint scenario

Use the disposable glci-ch24-feedback-lab project. The pipeline runs a deterministic standard-library test harness, emits JUnit XML and Cobertura XML, extracts a coverage percentage, and retains raw evidence. You then create one deliberate failure: either malformed JUnit XML or a misleading coverage regex. Diagnose it without hiding the original job/report.

Safety boundary: only synthetic code and report data are permitted. No production credentials, customer test logs, real browser targets, cloud infrastructure, or external deployments are involved.

2. Assumptions and preflight

Item Mandatory path
GitLab tier Free-compatible JUnit, coverage percentage, coverage visualization, and Code Quality report import.
Runner Any runner that can execute an approved Python image; no privileged Docker required.
Tools Python standard library only for mandatory report generation.
Source/data Synthetic app.py and deterministic tests.
Paid/admin features Browser Performance widget is optional/simulated; no admin or cloud requirement.
set -eu
git status --short
git rev-parse HEAD
printf 'source=%s ref=%s sha=%s pipeline=%s\n' \
  "$CI_PIPELINE_SOURCE" "$CI_COMMIT_REF_NAME" "$CI_COMMIT_SHA" "$CI_PIPELINE_ID"

3. Predict before execution

Prediction Independent verification
The test job will create exactly two XML reports plus tool output/checksums. Artifact browser + SHA256SUMS inventory.
GitLab will parse three passing JUnit test cases. Pipeline Tests tab / MR test summary and raw JUnit XML.
Coverage percentage and line annotations come from different configuration channels. Job log regex result versus raw Cobertura + MR diff annotations.
A malformed JUnit file should affect report parsing, not magically rewrite the original tool exit code. Preserved job trace/status + local XML validation + missing/changed UI report.

4. Exact checkpoint pipeline

stages: [test, verify]

test_and_report:
  stage: test
  image: python:3.12-alpine
  script:
    - python tools/run_checks.py | tee reports/tool-output.txt
    - sha256sum reports/junit.xml reports/cobertura.xml reports/tool-output.txt | tee reports/SHA256SUMS
    - printf 'source=%s\nref=%s\nsha=%s\npipeline=%s\njob=%s\n' "$CI_PIPELINE_SOURCE" "$CI_COMMIT_REF_NAME" "$CI_COMMIT_SHA" "$CI_PIPELINE_ID" "$CI_JOB_ID" > reports/source.env
  coverage: '/TOTAL .* ([0-9]+(?:\.[0-9]+)?)%$/'
  artifacts:
    when: always
    expire_in: 7 days
    paths:
      - reports/
    reports:
      junit: reports/junit.xml
      coverage_report:
        coverage_format: cobertura
        path: reports/cobertura.xml

verify_raw_reports:
  stage: verify
  image: python:3.12-alpine
  needs:
    - job: test_and_report
      artifacts: true
  script:
    - sha256sum -c reports/SHA256SUMS
    - python -c 'import xml.etree.ElementTree as ET; ET.parse("reports/junit.xml"); ET.parse("reports/cobertura.xml")'
    - grep -F "sha=${CI_COMMIT_SHA}" reports/source.env
    - grep -F "pipeline=${CI_PIPELINE_ID}" reports/source.env

The verify_raw_reports job proves raw-file integrity independently of GitLab's report widgets. A production pipeline could use a stronger provenance/evidence manifest; the key concept is that parser presentation and raw verification are distinct checks.

5. Expected observations

Observation Expected result Meaning
test_and_report status Passed when all assertions pass. Tool exit status is truthful.
JUnit 3 cases, 0 failures. GitLab parsed the JUnit file.
Coverage percentage 100.0% matched from tool output. Regex extraction channel works.
Coverage report Cobertura accepted; changed-line annotations may appear after processing in an MR. Structured visualization channel works.
Raw verification Checksums and XML parsing succeed. Stored parser inputs equal what the producer job generated.

6. Inject one controlled failure

Option A — malformed JUnit

On a disposable branch, after report generation but before artifact upload, append a single invalid fragment such as <broken> without a closing tag to reports/junit.xml. Record the new checksum. Keep the test tool exit result unchanged. Expect local XML validation to fail and GitLab's JUnit feedback to be missing/invalid. Preserve the original pipeline/job/report before correcting the generator step.

Option B — misleading coverage regex

Add an earlier synthetic line TOTAL warmup 1 covered 10.0% and intentionally loosen the regex so it matches the wrong percentage. Preserve the job output and extracted value. Repair the regex to match the intended final line, not the report contents.

Choose only one option. The purpose is to locate the failure layer, not to create a collection of broken states.

7. Required diagnostic sequence

  1. Record pipeline/job IDs and first-failure screenshots/text evidence.
  2. Confirm CI_PIPELINE_SOURCE, ref, CI_COMMIT_SHA, and compiled report paths.
  3. Confirm tool exit code and exact script line that changed the report/output.
  4. Checksum and locally validate the raw report.
  5. Inspect GitLab Tests/coverage feedback without assuming it is the source of truth.
  6. Apply only the causal correction.
  7. Rerun the smallest safe scope and compare new evidence with the preserved first failure.

8. Required evidence packet

Evidence Required contents
source.env Pipeline source/ref/SHA, pipeline ID, producer job ID.
tool-output.txt Coverage line and non-secret execution output.
junit.xml Exact JUnit parser input.
cobertura.xml Exact coverage-visualization parser input.
SHA256SUMS Checksums for raw evidence.
Tool/runner note GitLab offering/version, Runner version/executor, execution image identity, Python version.
Feedback note Observed Tests/coverage UI result and any processing delay/tier limitation.
Failure note First failed pipeline/job ID, symptom, root-cause layer, smallest correction.
Governance note Blocking/advisory meaning, artifact access, seven-day retention.

9. Verification checklist

  • Report files correspond to the recorded source SHA and producer job.
  • JUnit and Cobertura parse locally.
  • Checksums verify in the downstream verification job.
  • JUnit result and job status are interpreted separately.
  • Coverage percentage and coverage visualization are interpreted separately.
  • No report contains credentials or production data.
  • The intentional failure has preserved first-failure evidence.
  • The correction changes only the causal layer.
  • Artifact retention/access and tier assumptions are documented.

10. Cleanup / rollback

Delete the disposable branch/project when the exercise is complete, or keep it until the seven-day artifact expiry for review. No external resources exist. If you change project artifact-access or retention settings for experimentation, restore the original values and record that rollback.

Knowledge check

What proves that the JUnit widget corresponds to the checkpoint source revision?

If JUnit parsing fails but the test command exited zero, is the test necessarily bad?

Why does the checkpoint verify XML in a second job?

A coverage percentage is 100%. What additional question should a reviewer ask?

What should be preserved before fixing the intentional failure?

11. What Chapter 24 adds to the production operating model

You can now treat quality feedback as a traceable evidence pipeline: exact source and configuration → tool/version and exit semantics → structured report → GitLab parser/UI → explicit gate/advisory policy → retained raw evidence. This prevents green jobs, dashboards, or percentages from becoming unexamined proxies for correctness.

Chapter 25 extends the same model to security scanners. Scanner findings introduce additional questions about scanner scope, template/version, false positives, policy gates, exceptions, and remediation evidence.

Next chapter

SAST, Dependency Scanning, Secret Detection, Container Scanning, DAST, IaC Scanning, and Security Gates

Apply the report-evidence discipline to security findings while keeping scanner scope, tier/template identity, gating semantics, and remediation workflow explicit.

Version and compatibility note

GitLab and GitLab Runner evolve continuously. Treat version-sensitive YAML, runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations as assumptions to verify against the current official GitLab documentation before production use. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for any reproducible lab or incident record.

Official references and version notes

Documentation verification date: 2026-09-12. JUnit/unit-test reports, coverage percentage extraction, Cobertura/JaCoCo coverage visualization, Code Quality report import, and Accessibility reports are available on Free/Premium/Ultimate. Browser Performance reports are Premium/Ultimate. Code Quality's built-in CodeClimate-based template was deprecated in GitLab 17.3 and is planned for removal in GitLab 19.0; current guidance is to integrate a supported tool's report directly. The checkpoint remains fully Free-compatible. Browser Performance is taught as an optional Premium/Ultimate extension, while accessibility/report-import concepts remain available without requiring paid infrastructure.

Current assumptions used in this chapter: Version-sensitive YAML, Runner/executor behavior, APIs, security features, policy controls, tiers, and deprecations must be verified against the exact GitLab, GitLab Runner, tool, and external-system versions used in production. Preserve the exact project/ref/SHA, compiled configuration, pipeline/job IDs, runner/tool versions, and external target evidence used for reproducible work.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.