name: code-coverage-skill description: >- Processus itératif d'amélioration de la couverture de code par création de tests unitaires manquants sur le backend Api/Mail. Lance une analyse SonarQube (via le skill sonar-skill), identifie les classes sous 98% de couverture, génère les tests manquants, puis relance l'analyse. Itère jusqu'à 98% de couverture globale ou 5 itérations max. Utiliser pour : améliorer la couverture de code, créer des tests unitaires manquants, atteindre un objectif de couverture, ou exécuter un processus itératif de test. INVOKES : skill sonar-skill, dotnet CLI, tests unitaires, API SonarQube. allowed-tools: Read, Write, Edit, Glob, Grep, Bash
Code Coverage Improvement Skill
Ce skill implémente un processus itératif pour améliorer la couverture de code du projet backend Api/Mail/HealthPlatform.Api.Mail.sln (chemin relatif à la racine du repo) en créant les tests unitaires manquants jusqu'à atteindre un objectif de 98% de couverture globale ou un maximum de 5 itérations.
Objectif
- Couverture cible : 98% globale
- Seuil par classe : 98% minimum
- Itérations max : 5
- Classes traitées par itération : entre 1 et 10
Prérequis
- Le skill
sonar-skilldoit être disponible et fonctionnel - SonarQube doit être en cours d'exécution sur http://localhost:9001
- Le token SonarQube et le projet doivent être configurés
Processus itératif
Vue d'ensemble
┌─────────────────────────────────────────────┐
│ BOUCLE PRINCIPALE │
│ (max 5 itérations ou couverture >= 98%) │
├─────────────────────────────────────────────┤
│ 1. Lancer analyse SonarQube (sonar-skill) │
│ 2. Récupérer KPI (couverture globale) │
│ 3. Si couverture >= 98% → STOP ✓ │
│ 4. Extraire classes < 98% de couverture │
│ 5. Sélectionner 1-10 classes à traiter │
│ 6. Pour chaque classe : │
│ a. Lire le code source │
│ b. Identifier le projet de test associé │
│ c. Lire les tests existants │
│ d. Créer/compléter les tests manquants │
│ e. Vérifier que les tests passent │
│ 7. Retour à l'étape 1 │
└─────────────────────────────────────────────┘
Étape 1 : Lancer l'analyse SonarQube
Utiliser le skill sonar-skill pour lancer une analyse complète. Suivre la procédure documentée dans ce skill :
- Préparer l'environnement (se placer dans
Api/Mail, relatif à la racine du repo) dotnet sonarscanner beginavec les exclusions**/devops/**,**/load-tests/**,**/AppHost/**- Build de la solution
HealthPlatform.Api.Mail.sln - Exécuter les 5 projets de test (
mss.mail.*.tests) avec couverture OpenCover dotnet sonarscanner end
Étape 2 : Récupérer la couverture globale
Attendre la fin du traitement asynchrone côté serveur (poll sur ce/activity)
plutôt qu'un délai fixe, puis lire la métrique de couverture :
# Attendre que la dernière tâche d'analyse soit terminée (max 3 min)
$deadline = (Get-Date).AddMinutes(3)
do {
Start-Sleep -Seconds 5
$ce = Invoke-RestMethod -Uri "http://localhost:9001/api/ce/activity?component=healthplatform-api-mail&onlyCurrents=true&ps=1" `
-Headers @{Authorization="Bearer $env:SONAR_TOKEN"}
$status = if ($ce.tasks.Count -gt 0) { $ce.tasks[0].status } else { "PENDING" }
} while ($status -in @("PENDING","IN_PROGRESS") -and (Get-Date) -lt $deadline)
$metrics = "coverage"
$result = Invoke-RestMethod -Uri "http://localhost:9001/api/measures/component?component=healthplatform-api-mail&metricKeys=$metrics" `
-Headers @{Authorization="Bearer $env:SONAR_TOKEN"}
$globalCoverage = [double]$result.component.measures[0].value
Write-Host "Couverture globale : $globalCoverage%"
Étape 3 : Condition d'arrêt
if ($globalCoverage -ge 98) {
Write-Host "✓ Objectif atteint : $globalCoverage% >= 98%"
# STOP - Ne pas continuer les itérations
}
Étape 4 : Extraire les classes sous 98%
$result = Invoke-RestMethod -Uri "http://localhost:9001/api/measures/component_tree?component=healthplatform-api-mail&metricKeys=coverage,uncovered_lines,lines_to_cover&strategy=leaves&ps=500&metricSort=coverage&asc=true&qualifiers=FIL&s=metric" `
-Headers @{Authorization="Bearer $env:SONAR_TOKEN"}
# Filtrer les fichiers C# source (pas les tests) avec couverture < 98%
$classesBelowTarget = $result.components | Where-Object {
$_.path -like "src/*" -and
$_.path -like "*.cs" -and
$_.measures.Count -gt 0
} | ForEach-Object {
$cov = ($_.measures | Where-Object { $_.metric -eq "coverage" }).value
$uncovered = ($_.measures | Where-Object { $_.metric -eq "uncovered_lines" }).value
$total = ($_.measures | Where-Object { $_.metric -eq "lines_to_cover" }).value
if ($cov -ne $null -and [double]$cov -lt 98) {
[PSCustomObject]@{
Path = $_.path
Coverage = [double]$cov
UncoveredLines = [int]$uncovered
TotalLines = [int]$total
}
}
} | Sort-Object Coverage
# Afficher les classes à traiter
$classesBelowTarget | Format-Table -AutoSize
Write-Host "Total classes < 98% : $($classesBelowTarget.Count)"
Étape 5 : Sélectionner les classes à traiter (1-10)
Stratégie de sélection : Prioriser les classes avec le plus grand nombre de lignes non couvertes (impact maximal sur la couverture globale), en évitant les classes trop complexes à tester (dépendances HTTP externes, etc.).
Règles de sélection :
- Sélectionner entre 1 et 10 classes par itération
- Prioriser les classes avec un fort ratio
uncovered_lines / total_linesET un nombre raisonnable de lignes à couvrir - Éviter les classes qui nécessitent des mocks HTTP complexes si des classes plus simples sont disponibles
- Préférer les classes du Domain et Application (plus faciles à tester) avant Infrastructure et Api
Ordre de priorité des couches :
src/Domain/— Modèles, logique métier pure (testé parmss.mail.domain.tests)src/Application/— Services applicatifs, handlers (testé parmss.mail.application.tests)src/Infrastructure/— Infrastructure (testé parmss.mail.infrastructure.tests)src/Api/— Contrôleurs, middleware (testé parmss.mail.api.testsetmss.mail.integration.tests)
Étape 6 : Créer les tests manquants
Pour chaque classe sélectionnée :
6a. Identifier le projet de test correspondant
Base (relative à la racine du repo) : Api/Mail/tests
| Projet source | Projet de test associé |
|---|---|
src/Domain |
tests/mss.mail.domain.tests |
src/Application |
tests/mss.mail.application.tests |
src/Infrastructure |
tests/mss.mail.infrastructure.tests |
src/Api |
tests/mss.mail.api.tests (unit) / tests/mss.mail.integration.tests (intégration) |
6b. Lire le code source et les tests existants
- Lire le fichier source pour comprendre la classe, ses méthodes, ses dépendances
- Vérifier s'il existe déjà un fichier de test pour cette classe
- Si oui, lire les tests existants pour identifier les cas manquants
- Si non, créer un nouveau fichier de test
6c. Conventions de test du projet
- Framework : xUnit (
[Fact],[Theory]) - Mocking : Moq (
Mock<T>,MockBehavior.Strict) - Assertions : FluentAssertions (
.Should().Be(),.Should().NotBeNull(), etc.) - Nommage :
{MethodName}Should{ExpectedBehavior}(ex:GetTokensShouldReturnTokensDto) — jamais de_dans les noms de méthode - Structure : Arrange / Act / Assert
- VerifyNoOtherCalls : Toujours appeler
VerifyNoOtherCalls()à la fin des tests avec mocks stricts - Namespace : Reprendre la structure du projet de test (ex:
namespace mss.mail.application.tests.Services)
6d. Ce qu'il faut tester
- Cas nominaux : Appels avec paramètres valides → résultat attendu
- Cas limites : null, empty, valeurs extrêmes
- Cas d'erreur : exceptions, codes HTTP d'erreur
- Branches conditionnelles : if/else, switch, patterns optionnels
- Vérification des appels mock : Verify + VerifyNoOtherCalls
6e. Valider les tests
Après création/modification des tests, les exécuter pour s'assurer qu'ils passent :
dotnet test tests/{ProjetDeTest}/{ProjetDeTest}.csproj --configuration Release --filter "{NomDuTest}" --logger "console;verbosity=minimal"
Étape 7 : Retour à l'étape 1
Une fois les tests créés et validés pour les 1-10 classes de l'itération :
- Incrémenter le compteur d'itération
- Vérifier si max itérations atteint (5)
- Si non, retourner à l'étape 1 (analyse SonarQube complète)
Suivi des itérations
Maintenir un tableau de suivi à chaque itération :
| Itération | Couverture avant | Classes traitées | Tests ajoutés | Couverture après |
|-----------|-----------------|------------------|--------------|-----------------|
| 1 | xx.x% | ClassA, ClassB | +12 | xx.x% |
| 2 | xx.x% | ClassC, ClassD | +8 | xx.x% |
| ... | ... | ... | ... | ... |
Règles importantes
- Ne jamais modifier le code source pour améliorer la couverture — uniquement créer/modifier des tests
- Ne jamais créer de tests triviaux juste pour la couverture (pas de tests vides ou sans assertions)
- Toujours vérifier que les tests passent avant de passer à la classe suivante
- Respecter les conventions existantes du projet (Moq strict, FluentAssertions, VerifyNoOtherCalls)
- Maximum 10 classes par itération pour éviter les sessions trop longues
- Minimum 1 classe par itération — toujours progresser
- Arrêt obligatoire à 98% de couverture globale ou après 5 itérations
- Afficher le rapport KPI SonarQube (comme défini dans sonar-skill) à chaque fin d'itération
Exemple de déroulement
Itération 1:
→ Analyse SonarQube : couverture = 62.3%
→ 23 classes < 98%
→ Traitement de 5 classes (Domain)
→ +15 tests créés, tous passent
Itération 2:
→ Analyse SonarQube : couverture = 75.5%
→ 18 classes < 98%
→ Traitement de 8 classes (Application + Infrastructure)
→ +20 tests créés, tous passent
Itération 3:
→ Analyse SonarQube : couverture = 88.2%
→ 12 classes < 98%
→ Traitement de 10 classes
→ +25 tests créés, tous passent
Itération 4:
→ Analyse SonarQube : couverture = 98.1%
→ ✓ Objectif atteint ! STOP