GitLab Pipelines · Workshop Lektion 5 / Testberichte

Testberichte schön darstellen

GitLab liest JUnit- und Coverage-Reports und zeigt sie direkt im Merge Request.

Warum das zählt
Ein grüner oder roter Job sagt wenig. Wer im Merge Request auf einen Blick sieht, welche Tests neu fehlschlagen und welche Zeilen ungetestet sind, reviewt schneller und sicherer. Genau diese Aufbereitung macht GitLab automatisch – wenn du die Reports richtig deklarierst.

Kurzer Rückruf

Welches Keyword macht eine Datei nach dem Job herunterladbar?

Die Idee: spezielle Artifacts, die GitLab versteht

In Lektion 3 hast du artifacts: paths: gesehen – das sind beliebige Dateien zum Download. Daneben gibt es artifacts: reports: – das sind typisierte Reports in einem Format, das GitLab kennt. GitLab parst sie und baut daraus UI-Elemente:

Schritt 1 · JUnit-Bericht aus pytest

pytest schreibt mit einem Flag ein JUnit-XML. Das deklarierst du als reports: junit:

pytest:
  stage: test
  script:
    - pip install -r requirements.txt pytest pytest-cov
    - pytest --junitxml=report.xml --cov=app --cov-report=xml
  artifacts:
    when: always          # auch bei roten Tests hochladen!
    reports:
      junit: report.xml

Im Merge Request erscheint dann ein Test summary-Panel. GitLab vergleicht Quell- und Zielzweig und zeigt gezielt: neu fehlgeschlagen, neu behoben, weiterhin rot. Im Tab Tests der Pipeline siehst du jede Testsuite einzeln, mit Laufzeit.

Ohne when: always kein Report bei roten Tests Schlagen Tests fehl, ist der Job rot – und Artifacts werden standardmässig nicht hochgeladen. Dann fehlt ausgerechnet der Bericht, der zeigt, was fehlschlug. Bei Test-Reports darum fast immer when: always.

Schritt 2 · Coverage sichtbar machen

Zwei Dinge, die zusammenspielen – die Prozentzahl und die Annotationen im Diff:

pytest:
  stage: test
  script:
    - pytest --junitxml=report.xml --cov=app --cov-report=xml --cov-report=term
  coverage: '/TOTAL.*?(\d+%)/'     # liest die % aus dem Job-Log
  artifacts:
    when: always
    reports:
      junit: report.xml
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
Dein Win Aus zwei Zeilen YAML wird im Merge Request ein komplettes Test-&-Coverage-Dashboard – ohne externes Tool.

Besonderheiten & Stolperfallen

Annotationen nur auf geänderten Zeilen Die Coverage-Visualisierung markiert nur Zeilen, die der MR verändert. Unveränderte Dateien bleiben unmarkiert, auch wenn Coverage-Daten existieren. Das ist Absicht – Review-Fokus auf das Neue.
Vergleich braucht den Zielzweig Das „neu fehlgeschlagen / neu behoben" entsteht durch Vergleich mit dem Report des Zielzweigs. Lief auf main noch nie eine Pipeline mit JUnit-Report, kann GitLab nicht vergleichen – dann siehst du nur den absoluten Stand.
junit: akzeptiert Dateien/Globs, keine Ordner Du kannst report.xml, ein Muster wie tests/**/*.xml oder eine Liste angeben – aber nicht einfach einen Verzeichnisnamen.
Auch Code Quality & mehr Dasselbe Prinzip gilt für weitere Report-Typen: codequality, sast, dependency_scanning, dotenv … Alle erscheinen als aufbereitete MR-Widgets. JUnit und Coverage sind nur die zwei häufigsten.

Übung für Teilnehmende

Übung 1 · Fehler finden

Szenario: Tests schlagen fehl, aber im MR erscheint kein Test-Summary. Der Job hat reports: junit: report.xml. Was fehlt vermutlich?

Lösung anzeigen

artifacts: when: always. Da der Job rot ist, wird der Report ohne diese Zeile nicht hochgeladen – GitLab hat nichts zum Anzeigen.

Übung 2 · Selbst schreiben

Aufgabe: Ergänze einen mypy-Job so, dass seine Ergebnisse als JUnit im Tests-Tab erscheinen. (mypy kann mit --junit-xml schreiben.)

Lösung anzeigen
mypy:
  stage: test
  script:
    - pip install mypy && mypy app --junit-xml mypy.xml
  artifacts:
    when: always
    reports:
      junit: mypy.xml

Mehrere Jobs dürfen JUnit-Reports liefern – sie werden im Tests-Tab zusammengeführt.

Übung 3 · Verstehen

Frage: Worin unterscheiden sich artifacts: paths: [coverage.xml] und artifacts: reports: coverage_report: mit derselben Datei?

Lösung anzeigen

paths macht die Datei nur herunterladbar. reports: coverage_report lässt GitLab sie parsen und als Diff-Annotationen darstellen. Gleiche Datei, völlig anderer Effekt: speichern vs. verstehen.

Kurz prüfen (aus dem Kopf)

Was bewirkt artifacts: reports: junit?

Wozu dient das Keyword coverage mit Regex?

Primärquelle zum Lesen GitLab Docs – Unit test reports und Code coverage. Beide zeigen genau, wie Report → UI-Element wird.
Frag deinen Teacher. Willst du Code-Quality- oder SAST-Reports auch sehen? Sag Bescheid, ich zeig dir die Syntax.
← Lektion 4 Lektion 6 · rules & workflow →