GitLab liest JUnit- und Coverage-Reports und zeigt sie direkt im Merge Request.
Welches Keyword macht eine Datei nach dem Job herunterladbar?
Artifacts geben Dateien weiter und machen sie in der UI verfügbar – die Basis für Reports.
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:
reports: junit: → der Tests-Tab der Pipeline + das Test-Summary-Widget im MRreports: coverage_report: → Zeilen-Annotationen direkt im Diff des MRcoverage: → die Coverage-Prozentzahl als Badgepytest 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.
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.
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
coverage: '/…(\d+%)/' – ein Regex, der die Zahl aus dem Job-Log fischt.
Sie landet als Badge und in der MR-Übersicht. (--cov-report=term sorgt dafür,
dass die TOTAL …%-Zeile überhaupt im Log steht.)coverage_report: cobertura – die coverage.xml (Cobertura-Format) wird geparst und
geänderte Zeilen im Diff werden grün/rot markiert: getestet vs. nicht getestet.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.
codequality, sast,
dependency_scanning, dotenv … Alle erscheinen als aufbereitete MR-Widgets.
JUnit und Coverage sind nur die zwei häufigsten.
Szenario: Tests schlagen fehl, aber im MR erscheint kein Test-Summary.
Der Job hat reports: junit: report.xml. Was fehlt vermutlich?
artifacts: when: always. Da der Job rot ist, wird der Report ohne diese Zeile
nicht hochgeladen – GitLab hat nichts zum Anzeigen.
Aufgabe: Ergänze einen mypy-Job so, dass seine Ergebnisse als JUnit im
Tests-Tab erscheinen. (mypy kann mit --junit-xml schreiben.)
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.
Frage: Worin unterscheiden sich artifacts: paths: [coverage.xml] und
artifacts: reports: coverage_report: mit derselben Datei?
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.
Was bewirkt artifacts: reports: junit?
JUnit-Reports speisen den Tests-Tab und das MR-Widget mit neu/behoben/weiterhin-rot.
Wozu dient das Keyword coverage mit Regex?
Der Regex extrahiert die % aus dem Log fürs Badge. Die Diff-Annotationen kommen aus dem coverage_report (Cobertura).