
Un pipeline vert rassure, mais ne dit pas tout. Sans rapports qualité visibles dans la MR, les reviewers ne savent pas quels tests échouent, ni si la couverture monte ou baisse. Ce lab vous apprend à rendre les résultats lisibles directement dans GitLab pour améliorer la décision de merge.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Générer un rapport JUnit depuis pytest
- Publier ce rapport comme artifact reconnu par GitLab
- Extraire une couverture avec
coverage: - Lire ces informations dans les widgets de Merge Request
Quel lab commencer ?
Section intitulée « Quel lab commencer ? »Ce lab suit le Lab 09. Si votre pipeline publie déjà correctement les images, vous pouvez démarrer ici avec starter/lab-10.
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Dans un flux d'équipe, la MR est le point de vérité pour décider un merge. Si les infos qualité sont cachées dans des logs longs, elles sont peu consultées. En affichant les résultats au bon endroit, vous rendez la qualité visible et actionnable.
Ce lab répond à des besoins réels :
- repérer immédiatement un test cassé dans une MR
- suivre l'évolution de la couverture
- éviter les merges "à l'aveugle"
Prérequis
Section intitulée « Prérequis »- Lab 09 — Publier dans le registry terminé
- Avoir lu Rapports qualité
Point de départ
Section intitulée « Point de départ »-
Basculez sur la branche du lab
Fenêtre de terminal cd pipeline-craftgit checkout starter/lab-10 -
Ouvrez le job
pytestdans.gitlab-ci.ymlVous allez y ajouter la production de rapport et l'extraction de couverture.
Le problème
Section intitulée « Le problème »Sans configuration explicite, GitLab ne sait pas interpréter vos résultats de test. Vous devez lui fournir :
- un fichier JUnit via
artifacts.reports.junit - une expression
coverage:pour extraire le pourcentage
L'exercice
Section intitulée « L'exercice »Étape 1 — À vous de générer le rapport JUnit
Section intitulée « Étape 1 — À vous de générer le rapport JUnit »-
Modifiez le job pytest pour générer un rapport JUnit et une couverture exploitable.
-
Ajoutez un artifact JUnit conservé même en cas d'échec.
-
Vérifiez que GitLab peut afficher le rapport dans l'interface MR.
👉 Vérifier votre solution (Étape 1)
1️⃣ Job pytest avec rapport JUnit et couverture
Section intitulée « 1️⃣ Job pytest avec rapport JUnit et couverture »pytest: stage: test image: python:3.12-slim cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - pytest -v --junitxml=report.xml --cov=app --cov-report=term-missing coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' artifacts: when: always paths: - report.xml reports: junit: report.xml expire_in: 7 daysPoints clés :
--junitxml=report.xml: génère le XML attendu par GitLabreports.junit: report.xml: indique à GitLab où lire le rapportwhen: always: upload l'artifact même si les tests échouent (crucial pour le diagnostic)--cov=app: active la couverture sur le moduleapp
Étape 2 — À vous d'extraire la couverture
Section intitulée « Étape 2 — À vous d'extraire la couverture »-
Ajoutez une regex
coverage:sur le jobpytest. -
Vérifiez localement que la regex correspond bien à la ligne
TOTAL ... XX%. -
Ajustez la regex si besoin.
👉 Vérifier votre solution (Étape 2)
1️⃣ Regex de couverture
Section intitulée « 1️⃣ Regex de couverture »pytest: coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/'Cette regex matche la ligne produite par pytest-cov :
TOTAL 45 3 93%GitLab extrait 93% et l'affiche comme badge de couverture dans l'interface.
Tester la regex localement avant de pousser :
pytest -v --cov=app --cov-report=term-missing | grep TOTALVérifiez que la sortie contient bien TOTAL suivi d'un pourcentage en fin de ligne.
Étape 3 — À vous de vérifier dans la MR
Section intitulée « Étape 3 — À vous de vérifier dans la MR »-
Poussez vos modifications
Fenêtre de terminal git add .gitlab-ci.ymlgit commit -m "ci: publish junit and coverage"git push origin starter/lab-10 -
Ouvrez une Merge Request
-
Vérifiez l'onglet tests et la couverture affichée
L'objectif est de lire la qualité sans ouvrir les logs complets.
👉 Vérifier votre solution (Étape 3)
1️⃣ Lire les résultats dans la Merge Request
Section intitulée « 1️⃣ Lire les résultats dans la Merge Request »Après un pipeline sur MR, allez dans l'onglet Overview de la MR.
Vous devriez voir :
- Un widget Test summary indiquant les tests passés / échoués
- Un badge Coverage avec le pourcentage extrait
En cas d'échec de test, GitLab affiche le test échoué directement dans la MR — sans ouvrir les logs complets.
Cliquez sur View details dans le widget pour voir les tests un par un avec leur stacktrace.
Le fichier complet
Section intitulée « Le fichier complet »📄 Voir le fichier .gitlab-ci.yml complet
stages: - lint - test - build - deploy
workflow: rules: - if: $CI_PIPELINE_SOURCE == "push" - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH - if: $CI_COMMIT_TAG - if: $CI_PIPELINE_SOURCE == "schedule" - if: $CI_PIPELINE_SOURCE == "trigger" - if: $CI_PIPELINE_SOURCE == "api"
variables: PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
ruff-lint: stage: lint image: python:3.12-slim cache: key: files: - requirements-dev.txt paths: - .pip-cache/ policy: pull before_script: - pip install ruff script: - ruff check app/ tests/
pytest: stage: test image: python:3.12-slim cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - echo "Pipeline source: $CI_PIPELINE_SOURCE" - pytest -v --junitxml=report.xml --cov=app --cov-report=term-missing coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' artifacts: when: always paths: - report.xml reports: junit: report.xml expire_in: 7 days
nightly-regression: stage: test image: python:3.12-slim cache: key: files: - requirements-dev.txt paths: - .pip-cache/ before_script: - pip install -r requirements-dev.txt script: - echo "Nightly run on source=$CI_PIPELINE_SOURCE" - pytest -v rules: - if: $CI_PIPELINE_SOURCE == "schedule"
docker-build: stage: build image: docker:27 services: - docker:27-dind variables: DOCKER_TLS_CERTDIR: "/certs" script: - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA . - docker build -t $CI_REGISTRY_IMAGE:latest . - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA - docker push $CI_REGISTRY_IMAGE:latest
deploy-staging: stage: deploy image: alpine:3.20 script: - echo "Deploying $CI_COMMIT_SHORT_SHA to staging..." - ./scripts/deploy-demo.sh staging rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
deploy-production: stage: deploy image: alpine:3.20 script: - echo "Deploying $CI_COMMIT_SHORT_SHA to production..." - ./scripts/deploy-demo.sh production rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH when: manualVérification
Section intitulée « Vérification »-
report.xmlest généré et publié - GitLab affiche les tests dans la MR
- Le pourcentage de couverture est extrait
- Les reviewers peuvent lire les résultats sans parcourir les logs
Pièges fréquents
Section intitulée « Pièges fréquents »La couverture peut ne pas apparaître si la regex ne matche pas la sortie réelle. Vérifiez toujours la ligne exacte produite par pytest-cov.
Le rapport JUnit peut être vide si le chemin est incorrect ou si la commande pytest échoue avant génération. Dans ce cas, when: always aide au diagnostic car l'artifact est tout de même uploadé.
À retenir
Section intitulée « À retenir »- Les rapports qualité doivent être visibles dans la MR, pas cachés dans les logs
- JUnit + coverage améliore la revue et la confiance de merge
- Une bonne regex coverage est essentielle
- Les artifacts rendent le diagnostic reproductible