Objectif : À la fin de ce chapitre, tu sauras intégrer les tests dans un pipeline CI/CD, configurer SonarQube pour l’analyse de qualité, et mettre en place des quality gates qui bloquent le déploiement si la qualité n’est pas au rendez-vous.
Durée estimée : 35 minutes | Niveau : Intermédiaire
Introduction
Tu sais écrire des tests unitaires et d’intégration. Mais si personne ne les lance, ils servent à rien. Le vrai pouvoir des tests, c’est quand ils tournent automatiquement à chaque commit, à chaque PR, à chaque déploiement.
Dans ce chapitre, on va brancher les tests dans des pipelines CI/CD et mettre en place des quality gates — des barrières automatiques qui empêchent du code de mauvaise qualité d’atteindre la production.
Pourquoi tester dans le pipeline ?
La réponse est simple : les humains oublient. Même les meilleurs développeurs oublient de lancer les tests avant de push. Un pipeline CI/CD, lui, n’oublie jamais.
Les bénéfices concrets :
- Détection immédiate des régressions
- Feedback rapide — tu sais en 2 minutes si ton code casse quelque chose
- Confiance — si le pipeline est vert, le code est déployable
- Documentation vivante — les tests montrent ce que le code est censé faire
Tests dans GitHub Actions
Voici un pipeline complet qui lance les tests à chaque push et PR :
name: Tests & Quality
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16
env:
POSTGRES_DB: test_db
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install dependencies
run: |
pip install -r requirements.txt
pip install -r requirements-test.txt
- name: Run linting
run: |
ruff check .
ruff format --check .
- name: Run tests with coverage
env:
DATABASE_URL: postgresql://test:test@localhost:5432/test_db
run: |
pytest --cov=app --cov-report=xml --cov-report=html --junitxml=test-results.xml -v
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: htmlcov/
- name: Check coverage threshold
run: |
coverage report --fail-under=80
Ce qu’on fait ici :
- Service PostgreSQL pour les tests d’intégration
- Linting avec Ruff (formatage + style)
- Tests avec pytest + coverage
- Seuil de couverture à 80% — le pipeline échoue si c’est en dessous
Tests dans GitLab CI
L’équivalent en GitLab :
stages:
- lint
- test
- quality
lint:
stage: lint
image: python:3.12-slim
script:
- pip install ruff
- ruff check .
- ruff format --check .
test:
stage: test
image: python:3.12-slim
services:
- postgres:16
variables:
POSTGRES_DB: test_db
POSTGRES_USER: test
POSTGRES_PASSWORD: test
DATABASE_URL: postgresql://test:test@postgres:5432/test_db
script:
- pip install -r requirements.txt -r requirements-test.txt
- pytest --cov=app --cov-report=xml --cov-report=term --junitxml=report.xml -v
artifacts:
reports:
junit: report.xml
coverage_report:
coverage_format: cobertura
path: coverage.xml
coverage: '/TOTAL.*\s+(\d+%)/'
GitLab CI a un avantage : les rapports de couverture sont intégrés nativement dans les merge requests. Tu vois directement quel pourcentage de code est couvert.
SonarQube — Analyse de qualité
SonarQube va plus loin que la couverture. Il analyse :
- Bugs potentiels
- Vulnérabilités de sécurité
- Code smells (dette technique)
- Duplication de code
- Couverture de tests
Installation avec Docker
# docker-compose.yml
services:
sonarqube:
image: sonarqube:lts-community
ports:
- "9000:9000"
environment:
SONAR_ES_BOOTSTRAP_CHECKS_DISABLE: "true"
volumes:
- sonar_data:/opt/sonarqube/data
- sonar_logs:/opt/sonarqube/logs
volumes:
sonar_data:
sonar_logs:
Intégration dans le pipeline
sonarqube:
stage: quality
image: sonarsource/sonar-scanner-cli:latest
variables:
SONAR_HOST_URL: "https://sonar.devopslab.ch"
SONAR_TOKEN: $SONAR_TOKEN
script:
- sonar-scanner
-Dsonar.projectKey=mon-projet
-Dsonar.sources=app/
-Dsonar.tests=tests/
-Dsonar.python.coverage.reportPaths=coverage.xml
-Dsonar.python.xunit.reportPath=report.xml
allow_failure: false
Configuration du projet (sonar-project.properties)
sonar.projectKey=mon-projet
sonar.projectName=Mon Projet DevOps
sonar.sources=app/
sonar.tests=tests/
sonar.language=py
sonar.python.coverage.reportPaths=coverage.xml
# Quality Gate personnalisé
sonar.qualitygate.wait=true
Quality Gates
Un quality gate est un ensemble de conditions que le code doit remplir pour être considéré comme “déployable”. Si une condition échoue, le pipeline est bloqué.
Conditions typiques
Coverage ≥ 80% (couverture de tests)
Duplications ≤ 3% (code dupliqué)
Bugs = 0 (aucun bug détecté)
Vulnerabilities = 0 (aucune vulnérabilité)
Code Smells ≤ 10 (dette technique limitée)
Quality Gate dans GitHub Actions
- name: Quality Gate
run: |
# Check coverage
COV=$(coverage report | grep TOTAL | awk '{print $NF}' | tr -d '%')
if [ "$COV" -lt 80 ]; then
echo "Coverage $COV% is below 80% threshold"
exit 1
fi
# Check for security issues
pip install safety
safety check --json || true
# Check complexity
pip install radon
radon cc app/ -a -nc
Coverage reports dans les PR
Le but ultime : quand quelqu’un ouvre une PR, le pipeline affiche automatiquement :
- Le pourcentage de couverture actuel
- La diff de couverture (est-ce que la PR améliore ou dégrade la couverture ?)
- Les fichiers non couverts
Avec Codecov (gratuit pour l’open source)
- name: Upload to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
fail_ci_if_error: true
Avec SonarQube
SonarQube crée automatiquement un commentaire dans la PR avec un résumé : bugs trouvés, couverture, duplications, quality gate pass/fail.
Stratégies de test par environnement
graph LR Local["Local (dev)
Unit tests, linting"] --> PR["PR/MR
Unit + integration
+ coverage"] PR --> Staging["Staging
E2E + performance
+ security"] Staging --> Prod["Production
Smoke tests
+ synthetics"] style Local fill:#1e3a5f,stroke:#3b82f6,color:#f1f5f9 style PR fill:#1a2332,stroke:#3b82f6,color:#f1f5f9 style Staging fill:#1a2332,stroke:#f59e0b,color:#f1f5f9 style Prod fill:#1a2332,stroke:#dc2626,color:#f1f5f9
L’idée : plus tu te rapproches de la prod, plus les tests sont lourds mais aussi plus ils sont critiques.
Tests de performance dans le pipeline
performance:
stage: test
image: grafana/k6:latest
script:
- k6 run --out json=results.json tests/performance/load_test.js
artifacts:
paths:
- results.json
Avec k6, tu peux définir des seuils :
// tests/performance/load_test.js
export const options = {
thresholds: {
http_req_duration: ['p(95)<500'], // 95% des requêtes < 500ms
http_req_failed: ['rate<0.01'], // Moins de 1% d'erreurs
},
stages: [
{ duration: '30s', target: 20 },
{ duration: '1m', target: 50 },
{ duration: '30s', target: 0 },
],
};
À toi de jouer
Trois exercices pour ancrer ce que tu viens de lire.
Exercice 1 — Pipeline GitHub Actions avec tests
Crée un workflow GitHub Actions qui : installe les dépendances Python, lance les tests unitaires avec pytest, génère un rapport de coverage en XML, et poste le résumé de coverage en commentaire sur la PR (avec pytest-cov et une action de reporting).
Exercice 2 — Quality Gate avec SonarQube Déploie SonarQube avec Docker Compose. Configure un projet, définis un Quality Gate custom (coverage > 80%, aucun bug critique, dette technique < 2h). Intègre l’analyse dans ton pipeline CI et fais échouer le build si le Quality Gate n’est pas passé.
Exercice 3 — Stratégie de tests par environnement Conçois une matrice de tests pour 3 environnements : en PR (tests unitaires + lint, < 3 min), en staging (tests d’intégration + performance basique, < 15 min), en pre-prod (tests e2e + load test, < 1h). Écris les fichiers de workflow correspondants et configure les triggers appropriés (on push, on merge, scheduled).
Résumé
- Les tests dans le pipeline garantissent que chaque commit est vérifié automatiquement
- SonarQube analyse la qualité au-delà de la simple couverture (bugs, vulnérabilités, dette technique)
- Les quality gates bloquent le déploiement si les critères ne sont pas remplis
- La couverture de code doit être visible dans les PR (Codecov, SonarQube)
- Adapte les types de tests à l’environnement (unit en local, E2E en staging, smoke en prod)
La suite
Tu as maintenant toutes les bases pour écrire des tests et les intégrer dans tes pipelines. La prochaine étape ? Applique tout ça sur un vrai projet — crée une API FastAPI, écris les tests, configure SonarQube, et mets en place un pipeline complet. C’est le meilleur moyen d’ancrer ces compétences.
🖥️ Pratique sur ton propre serveur
Pour suivre Tests & Qualité en conditions réelles, tu as besoin d'un VPS. DigitalOcean offre 200$ de crédit gratuit pour démarrer.
Contenu réservé aux abonnés
Ce chapitre fait partie de la formation complète. Abonne-toi pour débloquer tous les contenus.
Débloquer pour 29 CHF/moisLe chapitre 1 de chaque formation est gratuit.
Série pas encore débloquée
Termine la série prérequise d'abord pour accéder à ce contenu.
Aller à la série prérequiseSur cette page
Articles liés
Déploiement avancé et orchestration
Stratégies de déploiement rolling et canary, intégration CI/CD avec GitHub Actions, et AWX / Ansible Automation Platform.
Ansible dans un pipeline CI/CD
Dynamic inventory multi-cloud, callbacks et custom modules, et optimisation des performances Ansible avec Mitogen et stratégies parallèles.
GitHub Actions et automatisation
Découvre GitHub Actions pour le CI/CD, la CLI gh pour travailler depuis le terminal, et les bonnes pratiques de collaboration en équipe.