GUIDE COMPLET

Guide de l'utilisateur

De votre premier fichier de trace jusqu'au contrôle de conformité aux normes de sécurité — tout ce que sait faire Fucini Coverage Studio, et comment l'utiliser précisément.

Télécharger le VSIX

1. Introduction

Fucini Coverage Studio transforme les fichiers de trace de couverture que votre build produit déjà en une couverture de premier ordre dans l'éditeur — dans VS Code et dans Visual Studio. Il lit vingt-cinq formats, les normalise en un modèle canonique Fucini unique, fusionne plusieurs exécutions de façon déterministe et affiche le tout dans l'éditeur lui-même — gouttières, CodeLens, survol et une vue Covered Files — de sorte qu'il n'y a pas de visualiseur séparé pour lequel quitter votre éditeur. Les deux éditions partagent un seul lecteur : le même rapport donne les mêmes chiffres, au chiffre près, dans les deux. Ce guide est écrit du point de vue de VS Code ; là où Visual Studio diffère, un encadré In Visual Studio dit comment.

Il a été conçu en tenant compte des démarches de sécurité fonctionnelle : couverture MC/DC, couverture des régions et des instanciations C++, un score composite pondéré selon la criticité, et un verdict COMPLIANT / NON-COMPLIANT configurable, aligné sur les approches IEC 61508, ISO 26262 et DO-178C.

Fucini Coverage Studio in VS Code: a file opened from the Coverage view, uncovered lines and half-taken branches in the editor, the MC/DC hover, the heatmap, the status-bar card and the annotated sourceScreenshot pending — add assets/img/marketplace-demo.gif (see SCREENSHOTS.md).

2. Installation et prérequis

  • VS Code ≥ 1.88 — la version minimale prise en charge par cette extension — ou Visual Studio 2022 ou 2026, Community, Professional ou Enterprise (voir l'encadré ci-dessous).
  • Un fichier de trace de couverture que votre projet produit déjà (voir §4).

Installez l'extension depuis le Marketplace, ou depuis un fichier .vsix via Extensions → ⋯ → Install from VSIX…. L'extension s'active au démarrage et ajoute une icône Coverage à la barre d'activité.

Dans Visual Studio. Le même produit est livré comme une seconde extension, Fucini Coverage Studio pour Visual Studio, pour Visual Studio 2022 et 2026 — Community, Professional et Enterprise. Il n'utilise pas la couverture de code propre à Visual Studio : dans Visual Studio 2022, c'est une fonction Enterprise, donc sur Community et Professional c'est la seule couverture que l'IDE affichera. Installez le .vsix en l'ouvrant — le VSIX Installer demande quel Visual Studio — ou via Extensions → Manage Extensions ; l'extension se charge à l'ouverture d'une solution ou d'un dossier. La fenêtre Coverage a besoin du Microsoft Edge WebView2 Runtime, que Windows 11 et Visual Studio 2026 apportent déjà ; les marques dans l'éditeur fonctionnent sans.

3. Démarrage rapide

Vous voulez voir comment ça fonctionne avant de connecter votre propre projet ? Téléchargez le projet de démonstration (~6 Ko — un petit projet C avec un lcov.info déjà prêt) :

  1. Décompressez-le où vous voulez, puis ouvrez coverage-studio-demo.code-workspace dans VS Code (File → Open Workspace from File…).
  2. Installez Fucini Coverage Studio si ce n'est pas déjà fait (voir §2 ci-dessus).
  3. Le fichier .vscode/settings.json propre au workspace pointe déjà vers le coverage/lcov.info fourni, donc les gouttières et la vue Covered Files apparaissent dès l'activation de l'extension — aucune étape Load Coverage n'est nécessaire.
  4. Vous voulez régénérer vous-même le fichier de trace (par ex. avec un autre compilateur) ? Exécutez scripts/gen-coverage.sh (ou .ps1 sous Windows) — consultez le README.md propre au workspace pour connaître les compilateurs disponibles.

Dans Visual Studio. Ouvrez une solution, ou un dossier (File → Open → Folder, c'est ainsi qu'on ouvre un projet CMake) — la démo ci-dessus s'ouvre comme un dossier, et son .vscode/settings.json y est lu aussi. Un rapport à l'endroit que les réglages nomment est chargé de lui-même et le volet Fucini Coverage de la fenêtre Output dit quels fichiers ; sinon Tools → Coverage Studio → Load Coverage File…, une fois — c'est mémorisé. Ouvrez un fichier source et choisissez Show Coverage in Editor : rouge est une ligne jamais exécutée, ambre une décision prise dans un seul sens, et Ctrl+Shift+U, N va à la prochaine ligne non couverte. View → Other Windows → Coverage est l'arbre avec les chiffres de chaque fichier et un score sur l'ensemble, que la barre d'état affiche pour l'exécution et pour le fichier où vous êtes. Tools → Coverage Studio → Getting Started ouvre ces étapes comme une page avec un bouton pour chacune ; la première fois, elle s'ouvre d'elle-même.

  1. Générez un fichier de trace de couverture avec votre flux de test habituel.
  2. Palette de commandes (Ctrl+Shift+P) → Fucini Coverage: Load Coverage. Avec watch.enabled activé (valeur par défaut), un fichier correspondant se charge automatiquement.
  3. Ouvrez un fichier source couvert : la barre d'état affiche son pourcentage, la vue Coverage se remplit, survoler une ligne montre son nombre de passages, et l'exécution apparaît dans le panneau Test Coverage natif. Des barres sur les lignes non couvertes, une carte de chaleur des passages et des compteurs ×N en ligne sont à un réglage près (editorGutter.mode, hitCounts.inline).
Covered (green) and uncovered (red) gutters in the editorScreenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).

4. Générer des fichiers de trace

Les formats suivants sont détectés automatiquement au chargement :

Des recettes complètes prêtes à copier-coller pour chaque compilateur — notamment Swift, Rust, Go, Python, .NET, PHP et plus encore — sur la page Recettes de couverture: Swift · Clang · GCC · Rust · Go · Python · Java/Kotlin · JS/TS · .NET · PHP · Ruby.

C / C++ — LLVM (llvm-cov)

clang --coverage -fprofile-instr-generate -fcoverage-mapping test.c -o test
LLVM_PROFILE_FILE=test.profraw ./test
llvm-profdata merge -sparse test.profraw -o test.profdata
llvm-cov export ./test -instr-profile=test.profdata --format=json > coverage.json

Le JSON llvm-cov est l'entrée la plus riche — outre les lignes, branches et fonctions, il transporte les régions, le MC/DC et les instanciations de templates C++.

C / C++ — GCC (gcov → lcov)

gcc --coverage calc.c calc_test.c -o test && ./test
lcov --capture --directory . --output-file lcov.info
# or gcovr --cobertura coverage.xml
# or skip the conversion entirely: gcovr --json coverage.json

JavaScript / TypeScript — Istanbul / nyc

nyc --reporter=json mocha        # emits coverage/coverage-final.json

Java — JaCoCo

mvn test        # emits target/site/jacoco/jacoco.xml

Ruby — SimpleCov

# .resultset.json (built-in) or coverage.json via the simplecov-json gem

Go

go test ./... -coverprofile=coverage.out    # read directly, no conversion

Python — coverage.py

coverage run --branch -m pytest && coverage json    # emits coverage.json

PHP — PHPUnit (Clover)

XDEBUG_MODE=coverage phpunit --coverage-clover clover.xml

.NET / C# — Coverlet (OpenCover)

dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
FormatFichier typiqueMétriques supplémentaires
LCOVlcov.infolignes, branches, fonctions
llvm-cov JSONcoverage.json+ régions, MC/DC, instanciations
Cobertura XMLcoverage.xmllignes, branches
JaCoCo XMLjacoco.xmllignes, branches, fonctions
Istanbul / nyccoverage-final.jsoninstructions, branches, fonctions
SimpleCov.resultset.jsonlignes
Clover XMLclover.xmllignes, branches, fonctions
OpenCover XMLcoverage.opencover.xmllignes, branches, fonctions
coverage.py JSONcoverage.jsonlignes, branches
gcov / gcovr JSONcoverage.jsonlignes, branches, fonctions
Go coverage profilecoverage.outlignes
SonarQube genericcoverage.xmllignes, branches
GNATcoverage XML (Ada)*.xmllignes, branches, MC/DC
BullseyeCoverage XMLcoverage.xmllignes, condition/décision
Visual Studio*.coveragexmllignes, branches
Coveralls JSONcoveralls.jsonlignes, branches
Xcode xccov JSONcoverage.jsonfonctions et totaux par fichier — aucune donnée par ligne
gcov plain text*.gcovlignes, branches, appels de fonction
VectorCASTcoverage.xmllignes, branches, paires MC/DC, fonctions, appels de fonction
Testwell CTC++*.txtlignes, condition/décision
Lauterbach TRACE32*.xmlinstructions, décisions, conditions, MC/DC, fonctions, appels, code objet
EMMA XML (Java)coverage.xmllignes
UCIS / Aldec UCDB*.xmlinstructions, branches de décision
NCover XMLCoverage.xmllignes, fonctions
dotCover DetailedXMLdotCover.xmllignes, fonctions
PIT (mutation)mutations.xmlscore de mutation — aucune couverture
Stryker (mutation)mutation-report.jsonscore de mutation — aucune couverture

Un projet C++ natif, mesuré depuis Visual Studio

Dans Visual Studio. La couverture d’un projet C++ propre à Visual Studio était réservée à Enterprise, et le plugin gratuit OpenCppCoverage qui comblait le manque a été retiré. Tools → Coverage Studio → Run Native Project with Coverage prend le projet de démarrage — un .vcxproj —, demande à MSBuild où il se compile et avec quel jeu d’outils, et le mesure de l’une de deux façons. Sur le jeu d’outils ClangCL, avec llvm-profdata et llvm-cov de LLVM sur la machine (le composant C++ Clang tools for Windows de Visual Studio les apporte), il recompile le projet dans coverage\native\ avec -fprofile-instr-generate -fcoverage-mapping, via un fichier props que MSBuild est chargé d’importer en premier — rien ne change dans le projet —, exécute le programme avec LLVM_PROFILE_FILE défini, fusionne le profil et exporte coverage\native\lcov.info, exact à la région près. Sur tout autre jeu d’outils, avec OpenCppCoverage installé, il compile le projet tel quel — une build Debug a les PDB — et l’exécute sous OpenCppCoverage, qui écrit coverage\native\opencppcoverage.xml. Chaque commande va dans le volet Fucini Coverage, et le rapport est chargé et mémorisé comme celui d’une exécution de tests. Un projet qui ne peut pas être mesuré se voit dire pourquoi et quoi installer. MSBuild 17.8 (Visual Studio 2022 17.8) ou plus récent, pour la question qu’il lui pose.

Visual Studio: Run Native Project with Coverage on a C++ project — the instrumented build, the run, and the gutter filling inScreenshot pending — add assets/img/vs-native-run.gif (see SCREENSHOTS.md).
Dans Visual Studio : Run Native Project with Coverage sur un projet C++ — la compilation, l’exécution, et l’éditeur qui se remplit.

5. Chargement et détection

Par défaut, l'extension analyse depuis la racine de l'espace de travail. Affinez ce comportement avec deux paramètres :

{
  "fuciniCoverage.coverageFile.defaultLocation": "${workspaceFolder}/build",
  "fuciniCoverage.coverageFile.paths": [
    "coverage.json",
    "reports/*.info",
    "${env:CI_ARTIFACTS}/lcov.info",
    "https://ci.example.com/artifacts/latest/coverage.xml"
  ]
}
  • Chaque entrée de paths est relative à defaultLocation (ou à la racine de l'espace de travail si non défini).
  • Une entrée contenant * est recherchée récursivement ; un simple nom de fichier ne correspond que directement dans le dossier de base.
  • Lorsque paths est vide, l'extension recherche d'abord coverage.json, puis lcov.info, et charge celui qu'elle trouve en premier.
  • Pick Coverage File utilise les fichiers que vous choisissez à la place de ces chemins — chaque choix s’ajoute à l’ensemble et tous sont fusionnés — jusqu’à ce que vous les déchargiez ou modifiiez ces paramètres.
  • Variables — chaque réglage de chemin développe ${workspaceFolder}, ${workspaceFolderBasename}, ${userHome}, ${env:NAME}, ${command:id} et ${config:section.key}. Une variable que l'extension ne connaît pas est laissée telle quelle, si bien qu'une faute de frappe apparaît dans le journal de détection comme le chemin recherché, au lieu de disparaître. ${command:id} exécute d’abord cette commande — uniquement dans un espace de travail approuvé, cinq secondes au plus —, si bien que ${command:cmake.buildDirectory} suit le kit CMake sélectionné.
  • Entrées URL — une entrée http(s):// est récupérée dans le stockage de l'extension à chaque chargement et chargée depuis là ; la vue Coverage nomme l'URL. Chaque récupération est conditionnelle (ETag / Last-Modified), si bien qu'un artefact inchangé ne télécharge rien, et quand une récupération échoue, la dernière copie téléchargée est chargée à la place, avec la raison dans la sortie. remote.headers ajoute des en-têtes Name: value avec les variables développées, remote.refreshMinutes relance la récupération à intervalle régulier, et un fragment #lcov.info nomme le format quand l'URL elle-même ne se termine pas par un nom de fichier.
  • Motifs d'exclusion — fuciniCoverage.ignore écarte des fichiers entiers (vendorisés, générés, tiers) de l'exécution à son chargement, si bien que chaque vue, chaque garde-fou et chaque export compte sans eux ; le résultat du chargement dit combien ont été laissés de côté et la sortie les nomme. Les motifs sont comparés au chemin relatif à l'espace de travail et au chemin absolu, et un motif sans / correspond à un nom de dossier ou de fichier à n'importe quelle profondeur, comme .gitignore.
  • Espaces de travail multi-racines — chaque dossier est détecté selon ses propres termes : defaultLocation, paths, pathRemap, ignore, watch.* et remote.* sont lus par dossier, si bien que le .vscode/settings.json propre à un dossier ou son entrée dans le .code-workspace s'applique, et ${workspaceFolder} dans une entrée désigne le dossier de cette entrée. Les fichiers de trace de chaque dossier fusionnent en une seule exécution, la vue Coverage regroupe les fichiers par dossier, et un dossier ajouté à l'espace de travail ou retiré de celui-ci recharge la couverture de lui-même.
  • Rechargement après une tâche — watch.reloadAfterTasks nomme des tâches (un label de tasks.json, ou source: name tel que la liste Run Task l'affiche) dont la fin recharge la couverture, que watch.enabled soit activé ou non — pour les builds que l'observateur ne peut pas suivre. Une entrée absolue de paths hors de l'espace de travail est interrogée elle aussi, si bien qu'un fichier qui y apparaît est chargé.
  • Une progression que l'on peut annuler — un chargement de dix fichiers de trace ou plus, ou de 8 Mo ou plus, s'exécute sous une notification de progression munie d'un bouton Annuler qui nomme le fichier en cours de lecture et la phase ; un chargement plus petit ne fait que faire tourner la barre d'état. Annuler laisse l'exécution précédente chargée et le dit.

Depuis 1.2026.6, une entrée absolue peut elle aussi contenir un joker : ${workspaceFolder}/build/coverage-merged/*.lcov.info charge chaque fichier de ce genre dans ce dossier, et ** vaut pour n’importe quelle profondeur. Les dossiers avant le premier joker sont là où elle cherche, et ils sont surveillés, si bien qu’un rapport qu’un build y écrit se charge de lui-même. L’édition Visual Studio lit une telle entrée de la même façon, et depuis 1.2026.5 un joker relatif y est lui aussi recherché à n’importe quelle profondeur, comme il l’a toujours été ici.

Lorsqu’aucun paths n’est configuré, le premier des noms de rapport bien connus trouvé sous le dossier de base est chargé. D’abord les quatre qui ont toujours été recherchés — coverage.json, lcov.info, coverage.out, clover.xml — puis, depuis 0.2026.83, jacoco.xml, coverage.xml, cobertura.xml, coverage.cobertura.xml, coverage.opencover.xml et coverage-final.json, et enfin les emplacements où écrivent les configurations par défaut : coverage/ (nyc, Jest, vitest, PHPUnit, SimpleCov), target/site/jacoco/jacoco.xml (Maven), build/reports/jacoco/test/jacocoTestReport.xml (Gradle) et TestResults/*/coverage.cobertura.xml (dotnet test). Ainsi, un projet Java ou .NET affiche sa couverture dès la première ouverture, comme un projet lcov l’a toujours fait.

Depuis 1.2026.3, une solution .NET a besoin d'encore moins : le dossier TestResults/<run>/ de chaque projet de test fait partie des emplacements connus, et pas seulement celui du dossier de l'espace de travail, et le <user>_<machine>_<date>.cobertura.xml du collecteur de Microsoft est trouvé à côté du coverage.cobertura.xml de Coverlet — une solution dont les tests ont été lancés dans le Test Explorer de Visual Studio montre donc sa couverture dès la première ouverture, chaque dossier d'exécution est chargé, et la fusion garde pour chaque fichier le dernier mot de l'exécution la plus récente. Et fuciniCoverage.ignore.generated, activé par défaut, laisse les fichiers de designer et les fichiers générés — *.Designer.cs, *.g.cs, *.generated.cs, *.razor.g.cs, AssemblyInfo, les usings globaux, Migrations/ et obj/ — hors de chaque total, page et export avant que ignore ne s'applique, si bien qu'une table générée que personne ne teste ne coûte pas son seuil à la solution.

Dans Visual Studio : la couverture après chaque exécution de tests. Lancez vos tests comme d'habitude. Tools → Coverage Studio → Collect Coverage in Test Explorer… place un .runsettings avec le collecteur Cobertura de Microsoft à côté de la solution. Visual Studio le reprend quand Tools → Options → Test → Auto detect runsettings files est activé ; sinon, sélectionnez-le une fois sous Test → Configure Run Settings. Dès lors, chaque exécution écrit un rapport sous le projet de test, et la surveillance de la solution le charge à l'instant où il apparaît, fusionné avec tout ce que les réglages nomment — depuis le Test Explorer, un terminal ou un script, indifféremment. Rien ne s'accroche au Test Explorer, si bien que Visual Studio 2026 et Microsoft.Testing.Platform fonctionnent tels quels. Run Tests with Coverage est la commande de VS Code : elle reconnaît dotnet test, vitest, jest, pytest, go, cargo, maven, gradle, phpunit et ctest, lance les tests avec la couverture activée dans la fenêtre Output et charge ce qu'ils ont écrit ; un projet de test sans coverlet.collector est lancé avec le collecteur livré par le SDK de test, et testRun.skipWhenTestsFail garde la dernière bonne couverture à l'écran quand une exécution se termine au rouge.

Un artefact CI derrière un jeton, revérifié tous les quarts d’heure — le jeton reste dans l’environnement, jamais dans settings.json :

{
  "fuciniCoverage.coverageFile.paths": [
    "https://ci.example.com/api/builds/latest/artifacts/coverage#lcov.info"
  ],
  "fuciniCoverage.remote.headers": ["Authorization: Bearer ${env:CI_TOKEN}"],
  "fuciniCoverage.remote.refreshMinutes": 15
}
A tracefile loaded from a URL: the Coverage view names the address it came fromScreenshot pending — add assets/img/remote-tracefile.png (see SCREENSHOTS.md).

Un rechargement est silencieux à dessein — une boîte de dialogue après chaque build est une question qui n’a qu’une réponse. Ce qui n’est pas silencieux, c’est l’icône Coverage : tant que la vue n’est pas devant vous, elle porte le nombre de tracefiles relus, et son infobulle les nomme. Ouvrez la vue et le compte disparaît.

A build rewrites two reports while the Explorer is open: the Coverage icon in the activity bar gains a count, its tooltip names what reloaded, and opening the view clears itScreenshot pending — add assets/img/coverage-badge.gif (see SCREENSHOTS.md).

Des fichiers qui ne doivent jamais compter, quoi qu’en dise le fichier de trace :

{
  "fuciniCoverage.ignore": ["vendor/**", "**/*.generated.ts", "build/**"]
}

Un rechargement à la fin de la tâche de test, pour un build que l’observateur de fichiers ne peut pas suivre — une exécution qui remplace un arbre de sortie lié symboliquement, un rapport sur un partage réseau, une étape de couverture qui post-traite son fichier :

{
  "fuciniCoverage.watch.reloadAfterTasks": ["npm: test", "coverage-report"]
}

6. Fusion des exécutions

Chaque entrée paths existante est chargée et fusionnée en une seule exécution. La fusion est déterministe — le résultat ne dépend pas de l’ordre de chargement — et un fichier mesuré par plus d’un tracefile prend ses chiffres de celui dont la mtime sur disque est la plus récente : la réexécution propre d’un module remplace ce qu’une exécution plus large et plus ancienne en disait, au lieu de s’y ajouter. La vue Couverture montre ce que cela a fait : chaque ligne de fichier nomme le tracefile dont viennent ses chiffres, le badge est entouré là où ces chiffres ont supplanté un rapport plus ancien, chaque ligne de tracefile au-dessus de l’arbre compte combien de ses fichiers ont été supplantés ou en ont supplanté d’autres, et un clic sur une ligne de tracefile met ses fichiers en évidence dans l’arbre jusqu’au clic suivant (coverageView.mergedMarks désactive le contour et la mise en évidence).

Four reports merged onto one source file: llvm-cov brings lines, functions, regions, branches, MC/DC and instantiations, two TRACE32 exports bring function calls and object code, and a mutation report brings the mutation scoreScreenshot pending — add assets/img/four-reports-one-file.svg (see SCREENSHOTS.md).

Une exécution fusionnée peut porter davantage que les six métriques classiques, chacune issue du rapport qui la mesure : appels de fonction, code objet et score de mutation, à côté des lignes, fonctions, régions, branches, MC/DC et instanciations. La vue Coverage affiche une colonne pour chaque métrique que l’exécution porte — et aucune pour celles qu’elle ne porte pas — classées par le poids de chaque métrique dans votre score, la plus lourde d’abord, quelle que soit la largeur — ce qui ne tient pas défile latéralement au lieu de disparaître. Faites glisser la vue dans le panneau inférieur et elle devient un tableau. Les cartes de la barre d’état, le rapport HTML et les exports CSV et Markdown suivent la même règle : ce qu’un rapport porte est affiché, ce qu’il ne porte pas est omis plutôt qu’imprimé comme un zéro.

The Coverage view in a real window: eight tracefiles from five languages above a tree with MC/DC, Conditions, Branches, Regions and the weighted score in columns beside every file, and a covered C# file open next to itScreenshot pending — add assets/img/coverage-view-editor.png (see SCREENSHOTS.md).
The Coverage view as a wide panel: C, C++, JavaScript, Python and .NET merged into one tree, with MC/DC, branches, regions, functions, lines, instantiations, mutation score, Max CRAP and the weighted score in columns beside every file, and an em dash where a metric does not applyScreenshot pending — add assets/img/coverage-view-columns.png (see SCREENSHOTS.md).
The Coverage view over a workspace of eleven projects: every tracefile listed, the tree collapsed to one row per project with its percentage and bar, scrolled through, expanded, and a file opened from itScreenshot pending — add assets/img/workspace-overview.gif (see SCREENSHOTS.md).
Visual Studio: the Coverage window over a folder of eleven projects — collapsed to one row per project with its bar, then expanded, then a file opened from itScreenshot pending — add assets/img/vs-workspace-overview.gif (see SCREENSHOTS.md).
Dans Visual Studio : la fenêtre Coverage sur un dossier de onze projets — repliée à une ligne par projet avec sa barre, puis dépliée, puis un fichier ouvert depuis elle.

De quel rapport vient un fichier

Quand plusieurs rapports chargés mesurent le même fichier, le plus récent l’emporte sans partage — ce qui est juste quand la nouvelle exécution d’un module remplace ce qu’une exécution plus ancienne et plus large avait dit. C’est faux quand les rapports mesurent le même code à dessein : l’éditeur bascule alors de l’un à l’autre à chaque build, et chacun ne raconte qu’une partie de l’histoire. coverageFile.sources dit quoi faire à la place, fichier par fichier. Trois situations l’appellent :

  • Un rapport est le meilleur. Le coverage.json de llvm-cov porte le MC/DC, un gcov.info de GCC issu du même build seulement les lignes et les branches : choisissez coverage.json, et gardez l’autre pour les quelques fichiers que seul GCC compile.
  • Plusieurs suites de tests d’un même build. Les tests unitaires, les tests d’intégration et le hardware-in-the-loop écrivent chacun un rapport ; chacun à lui seul laisse de côté des lignes que les autres ont exécutées. Combiner, union : une ligne est couverte là où n’importe quel rapport l’a exécutée, et les compteurs s’additionnent.
  • Une base de code, deux compilateurs. Les mêmes sources compilées par clang et par GCC empruntent des chemins différents dans le code propre à chaque chaîne d’outils — un intrinsèque ici, un repli portable là — et chaque rapport dit que l’autre moitié n’a jamais tourné. Combiner, agree : une ligne n’est couverte que là où chaque rapport qui la mesure l’a exécutée, et les lignes sur lesquelles ils divergent sont marquées en bleu sarcelle. C’est la question que pose une vérification croisée entre compilateurs : qu’est-ce que chaque build que je livre a réellement exercé ?

Vous écrivez rarement les règles à la main. Faites un clic droit sur un fichier dans la vue Couverture et choisissez Choose Coverage Source... (ou lancez Choose Coverage Source for This File... sur le fichier ouvert) : la liste présente chaque rapport qui mesure le fichier, chacun avec ses propres lignes, branches et MC/DC, puis Combine them — agree et Combine them — union ; choisissez-en un et indiquez s’il vaut pour le fichier, son dossier ou un motif. Clear Coverage Source for This File... retire la règle. Dans les réglages, chaque règle est un glob sur les fichiers, un glob sur le rapport (un motif sans / correspond au nom de fichier du rapport, {a,b} en désigne plusieurs) et, pour combiner, "combine": "agree" ou "union". La première règle dont les fichiers correspondent et dont le rapport mesure le fichier décide ; un fichier qu’un seul rapport mesure ne lui est jamais retiré. Les branches, le MC/DC et les régions d’un fichier combiné viennent du rapport qui en contient le plus. coverageFile.mergeStrategy: "order" tranche les fichiers dont aucune règle ne parle selon l’ordre de coverageFile.paths plutôt que selon les dates.

{
  "fuciniCoverage.coverageFile.paths": ["clang.json", "gcc/bits.gcov.json.gz"],
  "fuciniCoverage.coverageFile.sources": [
    { "files": "src/**", "report": "{clang.json,bits.gcov.json.gz}", "combine": "agree" }
  ]
}

Ce que vous voyez : la ligne du fichier dans la vue Couverture nomme le rapport dont viennent ses chiffres, ou, en cas de combinaison, chaque rapport et le mode, avec ≠ n pour les lignes en litige. La gouttière et l’Annotated Source marquent ces lignes en bleu sarcelle et indiquent quel rapport les a exécutées et combien de fois. La carte de survol de la barre d’état nomme la source du fichier ouvert et, pour toute l’exécution, les règles en vigueur et la façon dont les autres fichiers ont été tranchés. Le samples/c-cross-check de la démo est le cas des deux compilateurs, prêt à ouvrir. Visual Studio fait tout cela aussi : Choose Coverage Source... sur une ligne de la vue Couverture, et Choose et Clear Coverage Source for This File... sous Tools > Coverage Studio.

Choisir et combiner des sources fait partie des offres payantes. Sur Community, le rapport le plus récent l’emporte pour chaque fichier, comme sans règle, et une règle présente dans les réglages est signalée comme inutilisée plutôt qu’ignorée en silence.

Choose Coverage Source on bits.c: clang.json with lines, branches and MC/DC, bits.gcov.json.gz with lines and branches, and the two ways to combine them
Dans VS Code : Choose Coverage Source... sur bits.c depuis la vue Couverture — le rapport clang, le rapport GCC, ou les deux combinés.
Animation in VS Code: bits.c combined by agree with four teal lines, Choose Coverage Source opened from the Coverage view, and the file reloaded combined by union
Dans VS Code : de agree à union en deux clics — les lignes en litige restent en bleu sarcelle, les chiffres changent.
Animation in Visual Studio: bits.c combined by agree, the Coverage window's row menu, Choose Coverage Source and its two dialogs, and the file reloaded combined by union
Dans Visual Studio : la même chose depuis le menu d’une ligne de la vue Couverture — les rapports, puis la portée de la règle, puis le fichier rechargé.
bits.c with the clang and GCC reports combined by agree: the Coverage view row names both reports with four disputed lines, and the builtin and the portable loop are marked in teal
Dans VS Code : bits.c, clang et GCC combinés par agree — la ligne indique ≠ 4, et les quatre lignes qu’un seul build a exécutées sont en bleu sarcelle.
bits.c with the clang and GCC reports combined by union: every line covered, the four disputed lines still teal, and the status bar naming the union
Le même fichier combiné par union : toute ligne exécutée par l’un ou l’autre build est couverte, si bien que bits.c atteint 100% de ses lignes — et les lignes sur lesquelles les builds divergent restent en bleu sarcelle.
The Annotated Source of bits.c, combined by agree: the source line under the title names both reports, and each teal row says how often each report ran it
L’Annotated Source nomme la combinaison sous le titre, et chaque ligne en bleu sarcelle, combien de fois chaque rapport l’a exécutée.
The status bar's hover card for bits.c, ending with the coverage source: both reports, combined by agree, disagreeing on four lines
La carte de survol du fichier dans la barre d’état indique d’où viennent ses chiffres ; celle de l’exécution compte les fichiers que chaque règle a tranchés.
Visual Studio: Choose Coverage Source on bits.c from the Coverage window's row menu — the clang report, the GCC report and the two ways to combine them; behind it the row's agree badge with four disputed lines and the teal lines in the margin
Dans Visual Studio : Choose Coverage Source... depuis une ligne de la vue Couverture — les mêmes rapports et les deux mêmes façons de les combiner ; la barre d’état nomme la combinaison.

7. Remappage des chemins

L'intégration continue enregistre souvent des chemins absolus de la machine de build qui n'existent pas sur votre poste. Réécrivez-les avec des règles ordonnées :

{
  "fuciniCoverage.pathRemap": [
    { "from": "/builds/ci/project", "to": "${workspaceFolder}" },
    { "from": "\\\\", "to": "/" }
  ]
}

Les règles s'appliquent dans l'ordre ; la première correspondance l'emporte par préfixe. Utilisez ceci pour résorber les différences de séparateurs Windows/Unix ou faire correspondre un chemin de conteneur à votre copie de travail.

Vous avez rarement à écrire la règle vous-même. Le « ça s’est chargé mais rien ne s’allume » le plus courant est un fichier de trace dont les chemins viennent d’un conteneur ou d’une copie de travail CI (/build/src/a.c, /home/runner/work/repo/repo/src/a.c, C:\agent\_work\1\s\src\a.c) alors que l’espace de travail contient src/a.c. Quand un chargement laisse des fichiers sans correspondance, l’extension cherche leurs noms dans l’espace de travail, infère la règle de préfixe qui en explique le plus grand nombre, la consigne sous [FUCINI_REMAP_002], et le résultat du chargement propose Apply Suggested Remap — un clic ajoute la règle à fuciniCoverage.pathRemap et recharge. Suggest Path Remap Rule lance la même analyse à la demande depuis la palette. Rien n’est écrit sans le clic.

Un to peut utiliser ${workspaceRoot}, qui désigne le dossier de l’espace de travail où se trouve le fichier de trace ; dans un espace de travail multi-racines, il essaie d’abord ce dossier, puis chaque autre dossier qui s’avère contenir le fichier. Les règles elles-mêmes sont lues par dossier, si bien que chaque racine d’un espace de travail multi-racines peut porter les siennes.

8. Couverture dans l'éditeur

  • Marges et règle — par défaut, la gouttière propre à l'éditeur n'affiche que des constats : barres MC/DC, triangles « depuis la dernière exécution », points des lignes modifiées. editorGutter.mode ajoute des barres sur les seules lignes non couvertes ou une carte de chaleur des passages (ci-dessous) ; la vue colorée d'un fichier entier est l'Annotated Source.
  • CodeLens de fonction — % de couverture au-dessus de chaque fonction ; cliquez pour accéder à sa première ligne non couverte. Bascule avec codeLens.enabled.
  • Survol des branches et du MC/DC — survolez une ligne de décision pour voir les compteurs pris/non pris par branche et un tableau de vecteurs par condition. Activez une marge colorée avec mcdcGutter.enabled.
  • Avertissements de code mort — les fonctions avec des lignes mesurables et une couverture nulle sont signalées dans le panneau Problems (deadCode.enabled).
  • Next / Previous Uncovered — naviguez entre les lacunes.
  • Barre d'état — un élément $(dashboard) NN% pour toute l'exécution et un élément par fichier, tous deux colorés selon le score composite ; survolez pour un tableau complet des métriques.
  • Badges de l'Explorateur — badges de couverture par fichier et par dossier, avec le détail par métrique au survol. Désactivées par défaut : activez-les avec explorerBadges.enabled.
  • Depuis la dernière exécution — un triangle rouge sur chaque ligne exécutée lors de l'exécution précédente et pas dans celle-ci, un vert pour l'inverse, avec la règle d'aperçu et les nombres de passages au survol.
  • Tampons modifiés — chaque marque, survol et CodeLens suit le texte pendant l'édition et se retire d'une ligne réécrite, où un point gris dit pourquoi.
  • Compteurs de passages en ligne — hitCounts.inline écrit ×12 après chaque ligne où commence une instruction, ×0 compris : le nombre qui a toujours été au survol, sans survoler. Toggle Inline Hit Counts l'active ou le désactive ; le menu de la barre d'état le propose comme Afficher ou Masquer, selon le cas.
  • Entrées Problems par ligne — problems.perLine place un diagnostic Information, avec un soulignement ondulé dans l'éditeur, sur chaque bloc contigu de lignes jamais exécutées d'un document ouvert (une fonction morte de quarante lignes est une entrée, pas quarante) et, en uncoveredAndPartial, sur chaque ligne dont l'une des branches n'a jamais été prise. Les entrées suivent leurs lignes pendant l'édition et disparaissent à la fermeture du document ; l'entrée par fichier derrière problems.enabled est inchangée.
  • Teinte de ligne — lineHighlight place une teinte translucide derrière les lignes elles-mêmes, pour ce que la gouttière marque (uncovered, ou heatmap pour les lignes exécutées également). Un réglage à part, pour que la gouttière puisse rester nette pendant que les manques sont teintés, ou l’inverse.
  • Règle d’aperçu — overviewRuler décide de la bande dans la barre de défilement indépendamment de la gouttière : follow (avec les barres, comme avant), uncovered (toujours, la gouttière peut donc être désactivée pendant que la barre de défilement cartographie encore les manques) ou off.
  • Quel fichier de trace a couvert une ligne — avec plusieurs rapports fusionnés, l’info-bulle du nombre d’exécutions se termine par Couvert par : et chaque rapport ayant couvert cette ligne, nom de suite du TN: de lcov compris ; un clic sur une ligne de fichier de trace dans la vue Coverage éclaire les lignes qu’il a apportées dans chaque éditeur ouvert.
Function CodeLens and MC/DC hover tooltipScreenshot pending — add assets/img/codelens-hover.png (see SCREENSHOTS.md).
A function CodeLens on a C# method: 37.14% covered, 13 of 35 lines, branches 10 of 22, complexity 22, CRAP 142.2 — with the uncovered branches of the method marked underneathScreenshot pending — add assets/img/codelens-crap.png (see SCREENSHOTS.md).
Alt+N jumps from one uncovered line to the next, Alt+P goes backScreenshot pending — add assets/img/jump-between-gaps.gif (see SCREENSHOTS.md).
Explorer badges: a coverage percentage on every measured file and folder of all five demo projects, beside a covered C# file with its gutters, hit counts and CodeLensScreenshot pending — add assets/img/explorer-badges.png (see SCREENSHOTS.md).

Modes de gouttière de l’éditeur

editorGutter.mode décide de ce que la gouttière propre à l’éditeur montre de la couverture, en plus des constats qu’elle affiche toujours. off (la valeur par défaut) se limite à ceux-ci. uncovered place une barre sur chaque ligne qui n’a jamais été exécutée et une barre ambre sur chaque ligne dont l’une des branches n’a jamais été prise, et rien sur les lignes couvertes, si bien qu’un mur de vert ne cache pas les trois lignes rouges. coverage ajoute une barre verte sur chaque ligne couverte, si bien que tout le fichier se lit en rouge, ambre et vert aux couleurs de l’échelle de couleurs. heatmap ajoute à la place une teinte chaude sur chaque ligne exécutée, d’autant plus vive qu’elle a tourné souvent — elle montre combien de fois une ligne a tourné, pas si elle est couverte, si bien qu’un fichier à 100 % y va du jaune au brun, jamais au vert. Choose Editor Gutter Mode... en choisit un depuis la palette ou le menu de la barre d’état ; le bouton de mode à droite de la barre d’état, ou Alt+G, passe au suivant d’une seule pression (statusBar.showModeToggle masque le bouton). Les deux écrivent le réglage. L’exemple active ensemble les barres des lignes non couvertes et les compteurs en ligne :

{
  "fuciniCoverage.editorGutter.mode": "uncovered",
  "fuciniCoverage.hitCounts.inline": true
}
Uncovered mode: a red bar and wash on lines that never ran, amber on a line with a branch arm never taken, and the execution count written after each lineScreenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).
The coverage mode in VS Code: green bars on lines that ran in full, amber where a branch arm never did, red where nothing ran; the status bar names lcov.info as the report and the mode button reads Coverage
Dans VS Code : le mode coverage — vert là où une ligne a entièrement tourné, ambre là où une branche n’a jamais été prise, rouge là où rien n’a tourné. L’élément de barre d’état du fichier nomme le rapport dont viennent ses chiffres ; le bouton de mode à côté indique Coverage.
Alt+G pressed four times: heatmap, off, uncovered and back to coverage
Dans VS Code : Alt+G quatre fois — heatmap, off, uncovered, puis retour à coverage.
Visual Studio: Gutter: Coverage on Quote.cs, green, amber and red bars beside the hit counts
Dans Visual Studio : Gutter: Coverage (Red, Amber, Green) sur Quote.cs.

La carte de chaleur est relative au fichier. La teinte d’une ligne compare son compteur à celui de la ligne la plus chaude du même fichier, sur une échelle logarithmique, en cinq paliers — ainsi, un corps de boucle exécuté mille fois et une fonction exécutée deux fois sont tous deux visibles, au lieu que l’un noie l’autre, et un fichier où tout s’est exécuté exactement une fois est uniformément chaud plutôt qu’uniformément pâle. Avec un thème sombre, le dégradé va de l’olive terne à l’orange vif ; avec un thème clair, du jaune pâle au brun : dans les deux cas, plus de couleur signifie plus d’exécutions, et le rouge reste réservé aux lignes qui ne se sont jamais exécutées. lineHighlight: "heatmap" place les mêmes teintes en lavis derrière le code, et hitCounts.inline écrit le compteur exact après la ligne.

{
  "fuciniCoverage.editorGutter.mode": "heatmap",
  "fuciniCoverage.lineHighlight": "heatmap",
  "fuciniCoverage.hitCounts.inline": true
}
The heatmap on a dark theme: functions that ran once in dim olive, the decision that ran five times in vivid orange, lines that never ran in redScreenshot pending — add assets/img/heatmap-dark.png (see SCREENSHOTS.md).
The same file on a light theme: pale yellow for lines that ran once, brown for the hottestScreenshot pending — add assets/img/heatmap-light.png (see SCREENSHOTS.md).
Switching from uncovered mode to the heatmap, on a dark and then on a light themeScreenshot pending — add assets/img/heatmap.gif (see SCREENSHOTS.md).

Les couleurs sont les vôtres. colorScale.lowColor, midColor et highColor donnent le rouge, l’ambre et le vert de la gouttière, des teintes de ligne et de chaque pourcentage ; heatmap.colors et heatmap.colorsDark contiennent les cinq teintes de la carte de chaleur pour un thème clair et un thème sombre, de la ligne exécutée le moins souvent à celle exécutée le plus souvent. La page des réglages montre le résultat avant que rien ne soit enregistré : sous Colour scale, un aperçu reste visible pendant que les lignes défilent — le dégradé avec ses deux points pivots, quelques pourcentages dans leurs couleurs, et un petit éditeur clair et un petit éditeur sombre peints dans le mode coverage et dans la carte de chaleur — et il se redessine dès qu’une couleur est choisie.

{
  "fuciniCoverage.heatmap.colors": ["#e3f2fd", "#90caf9", "#42a5f5", "#1e88e5", "#0d47a1"]
}
The settings page in VS Code: two colours typed in, the pinned colour preview repainting each time
Dans VS Code : deux couleurs saisies dans la page des réglages — l’aperçu se redessine à chaque fois.
Visual Studio: the same settings page and the same colour preview
Dans Visual Studio : la même page, le même aperçu.

La partie d’une ligne qui n’a jamais été exécutée

Une ligne est couverte ou elle ne l’est pas, et la vérité se situe souvent entre les deux : return x > hi ? hi : x; a été exécutée, mais sa branche hi jamais. Lorsque lineHighlight est activé, la partie jamais exécutée d’une ligne exécutée est teintée dans l’éditeur, pour tous les formats qui portent des plages de colonnes (llvm-cov, Istanbul, Go, dotnet-coverage) — les mêmes segments que marque le source annoté. Uniquement sur les lignes exécutées : une ligne jamais exécutée est déjà marquée en entier. Un template C++ compte comme exécuté là où n’importe quelle instanciation l’a exécuté ; ce qu’a fait chaque instanciation, c’est la métrique des instanciations qui le rapporte.

An executed line whose opening brace is tinted: the if ran, the block it opens never didScreenshot pending — add assets/img/partial-line.png (see SCREENSHOTS.md).

Quels tests ont exécuté cette ligne

Certains rapports indiquent non seulement qu’une ligne a été exécutée, mais aussi quels tests l’ont exécutée : coverage.py, écrit avec coverage json --show-contexts et dynamic_context = test_function dans .coveragerc, OpenCover, collecté avec -coverbytest, et un tracefile lcov écrit en une section par test (TN:), dont les sections sont additionnées en un seul enregistrement avec un test par ligne. Survolez le début d’une ligne, là où figure le compteur d’exécutions, et les tests sont nommés — abrégés en classe et méthode, les cinq premiers par leur nom et le reste sous forme de nombre ; le CodeLens de la fonction dit combien de tests l’ont exécutée. Show Tests That Ran This Line — la Command Palette, le menu contextuel de l’éditeur, dans Visual Studio Tools → Coverage Studio ou Ctrl+Shift+U, T — les liste, les plus actifs en premier, et ouvre celui que vous choisissez là où il est écrit dans l’espace de travail. Une exécution dotnet test ne sait pas dire quel test a exécuté quoi ; activez testRun.perTest et Run Tests with Coverage liste les classes de test et les lance une à la fois, chaque rapport étiqueté de sa classe, si bien que le survol, la lentille et la commande répondent aussi pour .NET. L’information est conservée par fichier ; elle survit donc à une fusion avec un rapport qui ne sait rien des tests.

{
  "fuciniCoverage.testRun.perTest": true
}
# .coveragerc
[run]
dynamic_context = test_function

coverage run -m pytest && coverage json --show-contexts
Hovering the start of two lines of a Python file: each names the tests that ran it; an uncovered line names noneScreenshot pending — add assets/img/tests-per-line.gif (see SCREENSHOTS.md).
Show Tests That Ran This Line: the caret on a line, the list of tests that ran it busiest first, and the picked test opened where it is writtenScreenshot pending — add assets/img/tests-for-line.gif (see SCREENSHOTS.md).
Show Tests That Ran This Line : la liste, les plus actifs en premier, et le test ouvert là où il est écrit.
Visual Studio: the caret on line 62 of Quote.cs, Show Tests That Ran This Line, the dialog listing Tests.QuoteTests, and Go to Test opening QuoteTests.cs
Dans Visual Studio : Show Tests That Ran This Line sur la ligne 62 de Quote.cs — le test qui l’a exécutée, et Go to Test qui l’ouvre.

Réussite ou échec, sur les marques

Une ligne couverte a le même aspect, que son test ait réussi ou non. Là où le rapport dit quels tests ont exécuté une ligne et où le fichier de résultats du lanceur dit comment ils se sont terminés, une ligne qu’un test en échec a exécutée reçoit une barre rouge à son début et une bande dans la règle d’aperçu ; son survol nomme les tests en échec, et Show Tests That Ran This Line écrit échoué à côté de chacun. Quand un test est rouge, l’endroit où regarder est le code qu’il a traversé. Les résultats sont lus à chaque chargement dans le dossier de chaque rapport — tout .trx, et les noms qu’utilisent les outils qui écrivent du JUnit (TEST-*.xml, junit*.xml, test-results*.xml) — et depuis testResults.paths, sous forme de chemins ou de globs relatifs au dossier. Run Tests with Coverage demande à dotnet test un test-results.trx à côté du rapport, si bien qu’avec testRun.perTest activé il n’y a rien à configurer. testResults.enabled désactive cette lecture.

{
  "fuciniCoverage.testResults.paths": ["build/test-results/**/*.xml", "reports/junit.xml"]
  }
A failing test: a red bar on the lines it ran, the hover naming it under Failing tests that ran this line, and Show Tests That Ran This Line writing failed beside itScreenshot pending — add assets/img/pass-fail.gif (see SCREENSHOTS.md).
Visual Studio: a failing test — the red bar on the lines it ran, the hover naming it, and Show Tests That Ran This Line writing failed beside itScreenshot pending — add assets/img/vs-pass-fail.gif (see SCREENSHOTS.md).
Dans Visual Studio : un test rouge — la barre rouge sur les lignes qu’il a exécutées, le survol qui le nomme, et Show Tests That Ran This Line qui écrit failed à côté.

Les tests qu’une modification touche

Une exécution complète répond lentement à ce à quoi Run Tests Affected by My Changes… répond tout de suite : parmi tous les tests, lesquels sont passés par le code que je viens de modifier ? git est interrogé sur la diff de l’arbre de travail par rapport à testImpact.baseRef — HEAD par défaut, c’est-à-dire ce qui n’est pas encore commité ; origin/main pour tout ce que la branche modifie — et les tests qui ont exécuté une ligne modifiée sont listés, en premier celui qui a exécuté la plus grande part de la modification. Choisir un test l’ouvre. Là où les rapports viennent d’une exécution par test (testRun.perTest), la première entrée ne lance que ces tests, chaque classe dans son propre rapport, si bien que le rapport de toutes les autres classes reste valable et que les totaux restent ceux de la suite entière. Un test qui n’a exécuté que des lignes situées sous une insertion ou une suppression est listé lui aussi : sans cela, son rapport nommerait les mauvaises lignes.

An uncommitted edit, Run Tests Affected by My Changes…, the list with the test that ran most of the change first, and the run of only those testsScreenshot pending — add assets/img/test-impact.gif (see SCREENSHOTS.md).
Visual Studio: an edit, Run Tests Affected by My Changes…, the list with the test that ran most of the change first, and the run of only thoseScreenshot pending — add assets/img/vs-test-impact.gif (see SCREENSHOTS.md).
Dans Visual Studio : une modification, Run Tests Affected by My Changes…, la liste avec en tête le test qui a exécuté la plus grande part du changement, et l’exécution de ceux-là seulement.

Le plus petit nombre de tests qui exécutent encore chaque ligne

Show Minimal Test Set… répond à deux questions à partir des mêmes lignes par test : quels tests, en petit nombre, exécuteraient encore chaque ligne que la suite exécute — pour l’exécution rapide avant un commit — et quels tests n’exécutent aucune ligne qu’un autre n’exécute déjà. Les tests retenus viennent d’abord, chacun avec les lignes qu’il ajoute et les lignes que lui seul exécute ; puis les autres, chacun marqué comme n’ajoutant rien. Le choix est le choix glouton — le test qui exécute le plus de lignes, puis celui qui en ajoute le plus à celles-là — il est donc proche du plus petit ensemble, et le même à chaque fois. Redondant par les lignes ne veut pas dire redondant par ce qu’un test vérifie : un test qui n’ajoute aucune ligne peut malgré tout être le seul à vérifier une valeur sur ces lignes. La liste dit où regarder quand on élague une suite, jamais quoi supprimer.

Show Minimal Test Set…: the chosen tests first, then the tests that add nothingScreenshot pending — add assets/img/minimal-test-set.png (see SCREENSHOTS.md).
Visual Studio: Show Minimal Test Set… — the chosen tests, then the tests that add nothingScreenshot pending — add assets/img/vs-minimal-test-set.png (see SCREENSHOTS.md).
Dans Visual Studio : Show Minimal Test Set… — les tests retenus, puis ceux qui n’apportent rien.

Lancer ce test, avec la couverture

Placez le curseur dans un test et lancez Run This Test with Coverage — la Command Palette, le menu contextuel de l’éditeur, dans Visual Studio Tools → Coverage Studio ou Ctrl+Shift+U, R — et ce test seul s’exécute avec la couverture activée : la méthode de test où se trouve le curseur, ou la classe de test ou le bloc describe quand il est entre deux méthodes, ou le fichier quand il est au-dessus de toute classe. Ce qui est sous le curseur est lu dans le texte, si bien que cela fonctionne pour C#, VB et F# ([Fact], [Test], [TestMethod] et consorts), JavaScript et TypeScript (it, test, describe) et Python (def test_…), quel que soit le service de langage installé. La recette du dossier est restreinte à lui — dotnet test --filter "FullyQualifiedName~…", jest ou vitest <file> -t "…", un identifiant de nœud pytest — et ce qu’elle a écrit est chargé comme n’importe quelle exécution ; un lanceur qui ne peut pas être restreint le dit, et Run Tests with Coverage les lance tous.

Run This Test with Coverage: the caret in a Fact, the one dotnet test --filter run in the terminal, the gutter of the class under test filling inScreenshot pending — add assets/img/run-this-test.gif (see SCREENSHOTS.md).
Run This Test with Coverage : un test, une exécution, la classe testée allumée.
Visual Studio: the caret in the Fact AGoldCustomerGetsTenPercent, Run This Test with Coverage, the run appearing in the Tracefiles list and the lenses saying run by 1 test(s)
Dans Visual Studio : Run This Test with Coverage dans un [Fact] — l’exécution dans la liste Tracefiles, les lignes au-dessus des méthodes indiquant qu’un seul test a exécuté le code.

Go et Rust. Dans un fichier Go, le func TestXxx (ou Fuzz…, Example…) où se trouve le curseur s’exécute seul, dans son propre paquet et sous son nom exact — go test ./pkg/calc -run "^TestTotal$" — et, hors d’un test, c’est le paquet du fichier qui s’exécute. Dans un fichier Rust, la fonction #[test] s’exécute par son chemin dans la crate avec --exact ; avec le curseur dans un mod et dans aucun test, ce sont les tests de ce module qui s’exécutent ; un test d’intégration sous tests/ s’exécute dans son propre binaire (--test api). Un lanceur ne reçoit que des fichiers de son propre langage : un fichier TypeScript dans un dossier Go obtient une phrase, pas une exécution à vide.

La couverture après chaque enregistrement

Avec testRun.onSave activé, enregistrer un source lance les tests qui le couvrent, avec la couverture, un instant après l’enregistrement, et la gouttière suit. Pour une solution .NET, le projet du fichier enregistré est trouvé à travers le graphe des .csproj et seuls les projets de test qui le référencent — directement, ou à travers d’autres projets — sont lancés, un dotnet test <project> chacun ; tout autre lanceur lance sa recette entière ; un fichier qu’aucun projet ne possède et qu’aucun rapport ne mesure ne lance rien. Plusieurs enregistrements d’affilée font une seule exécution, et une exécution déjà en cours n’est pas interrompue. Le reste est comme le fait Run Tests with Coverage : le terminal, le volet Output, le rapport chargé. Désactivé par défaut — c’est une habitude à choisir, pas un réglage par défaut à découvrir.

{
  "fuciniCoverage.testRun.onSave": true
}
Coverage after every save: an edit to a C# file, Ctrl+S, the covering test project runs by itself, and the gutter changesScreenshot pending — add assets/img/coverage-on-save.gif (see SCREENSHOTS.md).
La couverture après chaque enregistrement : modifier, enregistrer, et la gouttière suit un instant plus tard.
Visual Studio: with testRun.onSave on, a comment line added to Quote.cs and saved, the tests running by themselves and the lens above Price changing
Dans Visual Studio : testRun.onSave activé — Quote.cs enregistré, les tests se lancent d’eux-mêmes, la ligne au-dessus de la méthode change.

L’application elle-même, avec la couverture

Une exécution de tests dit ce que les tests atteignent. Ce qu’une personne atteint — en parcourant les écrans avant une version, en rejouant les étapes d’un client — est aussi de la couverture, et Run App with Coverage… la collecte. L’application .NET du dossier — un Exe, un WinExe, un projet web ou worker, jamais un projet de test ; un choix là où il y en a plusieurs — est démarrée sous le dotnet-coverage de Microsoft dans une console à elle, pour qu’on puisse saisir dans une application console, et tourne jusqu’à ce que vous la fermiez. Ce que vous avez parcouru est alors chargé comme n’importe quelle exécution et, dans une session de couverture, s’ajoute à ce que les tests ont exécuté. La façon dont l’application s’est terminée ne compte pas contre l’exécution. L’outil est à installer une fois : dotnet tool install --global dotnet-coverage.

Run App with Coverage…: the console app started under dotnet-coverage, a few inputs, closed, and its coverage loadedScreenshot pending — add assets/img/run-app.gif (see SCREENSHOTS.md).
Visual Studio: Run App with Coverage… — the console app, a few inputs, closed, and its coverage loadedScreenshot pending — add assets/img/vs-run-app.gif (see SCREENSHOTS.md).
Dans Visual Studio : Run App with Coverage… — l’application console, quelques saisies, fermée, et sa couverture chargée.

Les mutants, et où ils se trouvent

Un outil de mutation — PIT pour Java, Stryker pour JavaScript, C# et Scala, Mull pour C et C++ — modifie votre code par petites touches et exécute les tests contre chaque modification. Une modification qu’aucun test ne remarque est un mutant survivant : le code a été exécuté, et rien n’a vérifié ce qu’il faisait. Le score de mutation indique combien ont été détectés ; depuis 0.2026.83, l’éditeur indique où se trouvent les autres. Une ligne qui en porte un est suivie d’une note (⚑ 2 mutants survived), le texte modifié est souligné lorsque le rapport précise de quel texte il s’agissait (c’est le cas de Stryker et de Mull), la règle d’aperçu porte une bande, et le survol montre ce qui a été modifié, combien de tests l’ont exécuté et, pour les mutants détectés, quel test les a détectés.

A surviving mutant in the editor: the note after the line, the underlined text, and the hover naming the change — ConditionalBoundary: value <= loScreenshot pending — add assets/img/mutant-hover.png (see SCREENSHOTS.md).

Survivant signifie que des tests ont exécuté le code modifié et ont tous réussi. Non testé (le no coverage du rapport) signifie qu’aucun test n’exécute ce code, de sorte que rien n’aurait pu le remarquer. Les mutants détectés sont comptés au survol et jamais marqués, et les mutants qui n’ont jamais constitué un test équitable — un mutant qui ne compilerait pas — restent hors du score. Le source annoté comporte une rangée sous chacune de ces lignes et un bouton Next Mutant (U), et les rapports HTML comportent une section Surviving Mutants qui renvoie à la ligne. Rien n’est à activer, et un projet sans rapport de mutation n’en voit rien.

Surviving mutants marked in the editor, the hover naming the change, and the annotated source jumping from one to the next with UScreenshot pending — add assets/img/mutants.gif (see SCREENSHOTS.md).

Un test s’en apercevrait-il ? Une exécution de mutation sous le curseur

L’exécution de mutation d’un projet prend une heure ; celle d’une fonction, une minute. Run Mutation Tests Here lance cette minute : la fonction où se trouve le curseur — ou les lignes sélectionnées, ou le fichier — est ce que le lanceur de mutation du dossier est chargé de muter, et son rapport est chargé à côté de la couverture à l’écran, où les mutants survivants sont marqués. Pour C#, c’est Stryker.NET (dotnet tool install --global dotnet-stryker), auquel sont donnés la plage de caractères et le projet de test qui référence le projet du fichier ; pour JavaScript et TypeScript, StrykerJS, auquel sont données les lignes ; pour Java, PIT avec Maven, auquel est donnée la classe. La façon dont le lanceur s’est terminé ne compte pas contre l’exécution : un score sous son seuil est un code de sortie, et reste un rapport. Un lanceur qui n’a rien écrit est signalé, avec ce qu’il lui faut d’installé.

Run Mutation Tests Here on one function: Stryker.NET runs that minute, and the surviving mutants are marked in the editorScreenshot pending — add assets/img/mutation-here.gif (see SCREENSHOTS.md).
Visual Studio: Run Mutation Tests Here on one function, and the surviving mutants markedScreenshot pending — add assets/img/vs-mutation-here.gif (see SCREENSHOTS.md).
Dans Visual Studio : Run Mutation Tests Here sur une seule fonction, et les mutants survivants marqués.

La vue Test Coverage propre à VS Code

Avec testCoverage.publish activé (la valeur par défaut), chaque exécution chargée va aussi dans la vue Test Coverage native de l’éditeur — le panneau de couverture du Test Explorer, les pourcentages par fichier qu’il place dans l’Explorateur, et la bascule Show Inline Coverage propre à l’éditeur — sous forme de lignes, de branches et de fonctions, les détails étant chargés à la demande, quel que soit le fichier de trace d’origine et sans aucun adaptateur de tests. Show in Test Coverage View publie l’exécution active et ouvre le panneau quoi que dise le réglage ; le menu de la barre d’état le propose derrière quickActions.showTestCoverage. Désactivé, aucune entrée Fucini Coverage n’apparaît du tout dans le Test Explorer. Quand un fichier de trace nomme ses tests (les sections TN: de lcov), chaque test apparaît sous Fucini Coverage dans le Test Explorer, et la vue peut filtrer la couverture d’un fichier par test.

VS Code's own Test Coverage view filled from the loaded reports, one bar each for statements, branches and functionsScreenshot pending — add assets/img/test-coverage-view.png (see SCREENSHOTS.md).

Lignes non couvertes dans le panneau Problems

Désactivé par défaut parce que bruyant par nature, et seulement pour les documents ouverts — une exécution de deux mille fichiers ne peut pas inonder le panneau. Indépendant de problems.enabled, qui s’en tient à une entrée par fichier :

{
  "fuciniCoverage.problems.perLine": "uncoveredAndPartial"
}
The Problems panel: one entry per file below the statement threshold, and a possible-dead-code entry for every function that never ranScreenshot pending — add assets/img/problems-panel.png (see SCREENSHOTS.md).

9. Couverture différentielle

Limitez les décorations aux lignes modifiées par rapport à une référence git de base — idéal pour vérifier exactement ce qu'une PR a couvert ou non :

{
  "fuciniCoverage.gitDiff.enabled": true,
  "fuciniCoverage.gitDiff.baseRef": "origin/main"
}
Diff coverage: only the five lines changed against the base ref are marked and judged — 5 of 5 lines, 7 of 8 branchesScreenshot pending — add assets/img/diff-coverage.png (see SCREENSHOTS.md).

Dans Visual Studio. Les deux mêmes réglages, lus dans les mêmes fichiers : l'extension lance elle-même git diff <baseRef> pour chaque fichier de l'exécution et réduit l'exécution aux lignes que votre branche a modifiées — dans la marge, dans la fenêtre Coverage et dans les seuils. Le volet Output dit ce que git a répondu quand il ne répond rien.

Un seuil sur le nouveau code

threshold.newCode est un seuil à part, à côté de ceux qui portent sur l’exécution entière : parmi les lignes modifiées par rapport à gitDiff.baseRef qui peuvent être mesurées, le pourcentage minimal qui doit avoir été exécuté. Un projet à 62 % au total peut tout de même exiger que ce qui est écrit aujourd’hui soit testé. Il est calculé à chaque chargement sur l’exécution entière, qui reste à l’écran — gitDiff.enabled est autre chose : les lignes modifiées à la place de l’exécution. Check Coverage Thresholds et les entrées de conformité du panneau Problems le déclarent en échec dans une phrase à lui : New code 72.00% < 80% (18 of 25 line(s) changed against origin/main ran). Une modification sans aucune ligne mesurable — des commentaires, un README — ne fait rien échouer.

{
  "fuciniCoverage.threshold.newCode": 80,
  "fuciniCoverage.gitDiff.baseRef": "origin/main"
  }
Check Coverage Thresholds failing New code 72.00% < 80% beside a run that passes its own gatesScreenshot pending — add assets/img/new-code-gate.png (see SCREENSHOTS.md).
Visual Studio: Check Coverage Thresholds failing the new-code gate in the Error List, beside a run that passes its own gatesScreenshot pending — add assets/img/vs-new-code-gate.png (see SCREENSHOTS.md).
Dans Visual Studio : Check Coverage Thresholds qui fait échouer le seuil du nouveau code, à côté d’une exécution qui passe ses propres seuils.

Le nouveau code par tag, par auteur, par date

Le nouveau code, ce sont par défaut les lignes que l’arbre de travail modifie par rapport à gitDiff.baseRef — une branche, un commit ou un tag : "v1.4.0", c’est tout ce qui est venu depuis cette version. Deux réglages demandent ce qu’une référence git ne peut pas dire. gitDiff.author prend une partie du nom d’un auteur, et le nouveau code est alors les lignes que git attribue à cet auteur ; gitDiff.since prend un jour, et ce sont les lignes modifiées pour la dernière fois ce jour-là ou après, quelle que soit la branche par laquelle elles sont arrivées ; les deux ensemble, les lignes de cet auteur depuis ce jour. Ils s’appuient sur git blame, un fichier à la fois — ce qu’une grande exécution ressentira à chaque chargement — et prennent la place de la diff pour la couverture de diff et pour le seuil ci-dessus. Une ligne pas encore commitée compte dans les deux cas.

{
  "fuciniCoverage.gitDiff.author": "Ada",
  "fuciniCoverage.gitDiff.since": "2026-09-01"
  }
The same gate scoped by author and date: new code by Ada since 2026-09-01Screenshot pending — add assets/img/new-code-author.png (see SCREENSHOTS.md).

Changements indirects : ce qui a bougé sans que personne y touche

Une diff dit quelles lignes ont changé ; deux exécutions disent quelles lignes ont cessé ou commencé d’être exécutées. Les lignes qui méritent un coup d’œil sont celles où les deux divergent : du code que personne n’a modifié et qui ne s’exécute plus, parce qu’un test a été supprimé, qu’une branche en amont retourne désormais plus tôt, qu’une fixture a changé. Une revue de la diff ne peut pas les voir — elles sont hors de la diff par définition. Show Indirect Coverage Changes… les liste par fichier, en premier le fichier qui a le plus perdu, et ouvre celui que vous choisissez à sa première ligne de ce genre. L’exécution est comparée à la référence CI là où baseline.report en nomme une — c’est sur elle qu’une pull request est jugée — et sinon à l’exécution qui la précède ; les lignes que l’arbre de travail modifie par rapport à gitDiff.baseRef, et tout ce qui se trouve sous un endroit où cette modification décale les lignes du fichier, sont laissés de côté.

Show Indirect Coverage Changes…: a file that lost lines nobody edited, after a test was removed between two runsScreenshot pending — add assets/img/indirect-changes.png (see SCREENSHOTS.md).
Visual Studio: Show Indirect Coverage Changes… — a file that lost lines nobody editedScreenshot pending — add assets/img/vs-indirect-changes.png (see SCREENSHOTS.md).
Dans Visual Studio : Show Indirect Coverage Changes… — un fichier qui a perdu des lignes que personne n’a modifiées, après qu’un test a été retiré entre deux exécutions.

10. Le score composite

Plutôt que de rapporter six nombres, l'extension les condense en une moyenne harmonique pondérée (WHM) unique. Pour des métriques avec des pourcentages pᵢ et des poids wᵢ :

WHM = ( Σ wᵢ ) / ( Σ wᵢ / pᵢ )

Une moyenne harmonique est dominée par son terme le plus faible, si bien qu'une métrique déficiente ne peut pas être masquée par une métrique parfaite — exactement la propriété recherchée pour un garde-fou de sécurité. Poids par défaut :

MétriquePoidsJustification
MC/DC4IEC 61508 SIL 3–4 / ISO 26262 ASIL C–D / DO-178C DAL A–B.
Branches2IEC 61508 SIL 2+ / ISO 26262 ASIL B+.
Conditions3Entre les branches et MC/DC (DO-178C, ISO 26262).
Régions1.5Chemins internes à une instruction (p. ex. court-circuit partiel).
Lignes1IEC 61508 SIL 1+ / ISO 26262 ASIL A+.
Fonctions1Contrôle du code mort.
Instanciations0.5Couverture des templates C++ ; portée la plus étroite.
Appels de fonction1Sites d’appel qui ont été exécutés (gcov, VectorCAST, Testwell CTC++, TRACE32).
Code objet0Désactivé tant que vous ne lui donnez pas de poids : il englobe la couverture des instructions.
Score de mutation0Désactivé tant que vous ne lui donnez pas de poids : ce n’est pas de la couverture.

Réglez un poids sur 0 pour exclure cette métrique du score. Les métriques absentes des données (par exemple le MC/DC dans une simple exécution lcov) sont simplement omises.

Le code objet et le score de mutation pèsent 0 tant que vous n’en décidez pas autrement (whmWeights.objectCode, whmWeights.mutation). La couverture du code objet englobe la couverture des instructions : pondérer les deux revient à compter deux fois la même preuve ; un score de mutation n’est pas du tout de la couverture — une suite de tests peut exécuter chaque ligne et ne rien détecter. Tous deux ont néanmoins leur propre colonne et leur propre seuil.

The default weights of the composite score: MC/DC 4, branches 2, regions 1.5, lines, functions and function calls 1, instantiations 0.5; object code and mutation score 0 until given a weightScreenshot pending — add assets/img/score-weights.svg (see SCREENSHOTS.md).

Couverture des conditions

a && b est une décision — deux branches — et deux conditions avec quatre issues. Une suite de tests peut emprunter les deux branches sans jamais voir b faux : la couverture des branches est complète et la couverture des conditions est de trois sur quatre. Ce niveau se situe entre la couverture des branches et MC/DC dans DO-178C et ISO 26262, et depuis 0.2026.83 c’est une métrique à part entière plutôt qu’un élément fondu dans les branches : une ligne dans les cartes de la barre d’état, une colonne dans la vue Coverage, les rapports et les exports, un poids de 3 dans le score (whmWeights.conditions) et un garde-fou (threshold.conditions ; sans garde-fou sous le profil standard, 100 sous safety).

One decision, a && b, and the same two tests: branches 2 of 2, conditions 3 of 4 because b is never seen false, MC/DC 1 of 2 because b is never shown to matterScreenshot pending — add assets/img/branch-condition-mcdc.svg (see SCREENSHOTS.md).

Lue à partir des sondes condition de BullseyeCoverage, d’un export cond de TRACE32 et de GCC 14 compilé avec -fcondition-coverage. Un rapport qui ne distingue pas les conditions des décisions n’a ni cette ligne, ni cette colonne, ni ce poids. Si vous utilisez Bullseye ou TRACE32 : les conditions comptaient jusqu’ici comme des branches ; votre pourcentage de branches change donc avec cette version, et, avec le nouveau poids, votre score composite aussi ; réglez whmWeights.conditions sur 0 pour retrouver le score tel qu’il était.

GCC 14, ligne par ligne. -fcondition-coverage fait dire à gcov quel résultat de quelle condition manque — la condition 1 jamais vraie, la condition 0 jamais vraie ni fausse — et chaque condition est marquée sur sa ligne et nommée dans le survol, à partir du JSON de gcov comme de son listing texte (condition outcomes covered 3/6). La métrique est là où sont les autres : threshold.conditions lui sert de seuil et n’est pas jugé là où une exécution n’a pas ce chiffre, Copy Coverage Summary a une colonne Conditions, badge.metric accepte conditions, et le champ de recherche accepte conditions < 80. Le chiffre de branches d’une fonction laisse de côté les résultats de ses conditions, comme ceux du fichier et de l’exécution.

GCC 14 condition coverage: the mark on the line and the hover naming the outcome never seenScreenshot pending — add assets/img/gcc-conditions.png (see SCREENSHOTS.md).

Complexité et CRAP

Certains rapports portent la complexité cyclomatique de chaque fonction : OpenCover (le format qu’écrit Coverlet), JaCoCo, Clover et Cobertura. Lorsque c’est le cas, l’extension calcule pour la fonction un score CRAP — Change Risk Anti-Patterns — à partir de cette complexité et de la couverture qu’elle a elle-même mesurée :

CRAP = complexity² × (1 − coverage)³ + complexity

Une fonction simple et entièrement testée obtient sa propre complexité et rien de plus ; une fonction complexe et à peine testée obtient un score de plusieurs centaines. Dans l’exemple C# du projet de démonstration, Price() a une complexité de 22 et environ 37 % de ses lignes couvertes, ce qui donne 142,2, tandis que Shipping() a une complexité de 12 et est entièrement couverte, ce qui donne 12. La limite d’usage est 30 : une fonction qui l’atteint ou la dépasse est listée sous Riskiest Methods dans le rapport HTML, la pire en premier.

CRAP against line coverage for two methods: Price() with complexity 22 sits at 142.2 and needs about 75% coverage to get under 30; Shipping() with complexity 12 is fully covered and scores 12Screenshot pending — add assets/img/crap-curve.svg (see SCREENSHOTS.md).

La complexité et le score figurent dans le CodeLens de la fonction et à côté de la fonction dans le source annoté. Max CRAP est le score le plus élevé parmi les fonctions d’un fichier — le pire, non une moyenne — et constitue une colonne dans la vue Coverage, le rapport HTML et les exports CSV et Markdown. C’est une information : il n’a ni seuil ni poids dans le score composite. Les rapports qui ne portent aucune complexité (lcov, gcov, Istanbul, coverage.py) n’ont pas de CRAP, et pas de colonne vide non plus.

Depuis 0.2026.83, C et C++ en disposent aussi. llvm-cov ne rapporte aucune complexité ; elle est donc comptée à partir des données de branches que le rapport contient déjà : les conditions écrites dans le fichier propre à la fonction, plus un — la définition de McCabe, et ce que comptent les outils au niveau du source pour .NET et Java. Les conditions issues d’une macro provenant d’un autre fichier — chaque assert, par exemple — ne sont pas comptées.

The Riskiest Methods section of the HTML report: Price() with complexity 22, 37.14% of its lines covered, CRAP 142.2Screenshot pending — add assets/img/riskiest-methods.png (see SCREENSHOTS.md).

Risk hotspots, et quels fichiers afficher

Sous l'arbre de la vue Coverage, Risk hotspots liste les fonctions où du code complexe rencontre peu de couverture, la pire en premier, chacune ouvrant son fichier à la fonction. Une fonction se qualifie par son score CRAP — hotspots.crapThreshold, 30 par défaut, le chiffre proposé par les auteurs de la métrique — ou par sa seule complexité cyclomatique, hotspots.complexityThreshold, désactivé par défaut ; seuls les rapports qui portent la complexité (OpenCover, Cobertura de Coverlet, JaCoCo, llvm-cov) en ont. Community voit le nombre et le pire score ; la liste classée est Pro. À côté du tri, une seconde liste déroulante dit quels fichiers l'arbre affiche — tous, les fichiers avec des lacunes, les fichiers non testés, ou les fichiers modifiés depuis la dernière exécution ; les dossiers suivent leurs fichiers et gardent leurs propres chiffres. Les deux sont aussi dans Visual Studio, dans la fenêtre Coverage.

Visual Studio: the Coverage window with the filter beside the sort and the risk hotspots under the treeScreenshot pending — add assets/img/vs-hotspots.png (see SCREENSHOTS.md).
Dans Visual Studio : la fenêtre Coverage, avec le filtre à côté du tri et les Risk hotspots sous l'arborescence.

Espaces de noms, classes et méthodes

Pour un rapport .NET qui nomme ses classes — Cobertura et le coverage.cobertura.xml de Coverlet, OpenCover — une troisième liste déroulante, Folders / Namespaces, dessine la même exécution en espaces de noms, classes et méthodes : le chiffre d’un espace de noms est la somme de ceux de ses classes, celui d’une classe la somme de ceux de ses méthodes, exactement comme celui d’un dossier est la somme de ceux de ses fichiers, avec le même tri et le même filtre. Une ligne de méthode ouvre le fichier à la méthode ; une classe déclarée dans aucun espace de noms est sous (no namespace). Le choix est écrit dans coverageView.perspective ; une exécution qui ne porte aucun nom de classe n’a pas de liste déroulante et affiche ses dossiers. Dans Visual Studio, la fenêtre Coverage a la même liste déroulante.

The Coverage view drawn as namespaces, classes and methods, the dropdown on Namespaces, a method row about to open its fileScreenshot pending — add assets/img/namespace-perspective.png (see SCREENSHOTS.md).
La même exécution par espace de noms, classe et méthode.
Visual Studio: the Coverage window with the dropdown on Namespaces, the Pricing namespace open on Customer and its methods
Dans Visual Studio : la fenêtre Coverage par espace de noms, classe et méthode.

Sous les boutons et les listes déroulantes, un champ de recherche. Un mot garde les lignes dont le nom ou le chemin le contient — chaque mot tapé doit s’y trouver ; une comparaison garde les lignes dont le chiffre la satisfait — < 80% sur le score, lines >= 90, branches = 0, functions != 100, mcdc < 50 — et invoice < 80 exige les deux. Les lignes de méthode de la perspective par espaces de noms et les risk hotspots sont cherchés avec les fichiers, si bien qu’une fonction est trouvée là où l’exécution la place. L’arbre est filtré au fil de la frappe, dans la page, sans redessin ; un dossier qui contient une correspondance s’ouvre pour elle et se referme quand le champ se vide ; Esc l’efface. Le même champ, la même grammaire, dans Visual Studio.

Typing lines < 80 into the Coverage view's search box: the tree keeps only the files under eighty percent, folders opening to show themScreenshot pending — add assets/img/tree-search.gif (see SCREENSHOTS.md).
Rechercher dans l’arbre : un nom, puis lines < 80.

L’arbre suit l’éditeur

Le fichier que vous regardez est mis en évidence dans la vue Coverage, les dossiers au-dessus de lui sont dépliés et sa ligne est amenée dans la partie visible — il n’y a plus à chercher dans l’arbre le fichier qui est déjà ouvert. Pour le reste, l’arbre garde sa position de défilement, et rien n’est redessiné. coverageView.followActiveEditor, activé par défaut, le désactive pour ceux qui préfèrent laisser l’arbre là où ils l’ont mis.

Switching editor tabs: the Coverage view's highlighted row follows, the folders above it openedScreenshot pending — add assets/img/follow-editor.gif (see SCREENSHOTS.md).
Visual Studio: switching documents, and the Coverage window's highlighted row followingScreenshot pending — add assets/img/vs-follow-editor.gif (see SCREENSHOTS.md).
Dans Visual Studio : le passage d’un document à l’autre, et la ligne en surbrillance de la fenêtre Coverage qui suit.

11. Contrôle de conformité

Le verdict COMPLIANT / NON-COMPLIANT (affiché dans la vue source annotée, le rapport HTML et les deux info-bulles de la barre d'état) est déterminé par des seuils par métrique et un mode :

The status-bar hover card: NON-COMPLIANT, 3 of 5 gates below threshold — functions and regions pass, lines and branches miss narrowly (amber), MC/DC misses outright (red)Screenshot pending — add assets/img/statusbar.png (see SCREENSHOTS.md).
ModeCOMPLIANT quand…
strict (default)chaque métrique contrôlée individuellement atteint son propre seuil — aucun compromis.
whmle score composite pondéré unique atteint threshold.weighted.
bothle contrôle pondéré ET le contrôle strict par métrique sont satisfaits.
eitherle contrôle pondéré OU le contrôle strict par métrique est satisfait (le plus permissif).

Un seuil de 0 désactive ce garde-fou, et une métrique que le rapport ne porte pas n’est jamais jugée. Ce que vaut un seuil que vous n’avez pas défini est décidé par le profil ci-dessous. Exécutez Fucini Coverage: Check Coverage Thresholds pour évaluer à la demande.

Dans Visual Studio. Tools → Coverage Studio → Check Coverage Thresholds juge l'exécution selon les mêmes clés threshold.* et le dit dans la barre d'état et le volet Output ; avec compliance.diagnostics, problems.enabled, problems.perLine ou deadCode.enabled, les constats figurent dans l'Error List à côté de ceux du compilateur — une entrée par fichier sous un seuil, une par plage non couverte, une par fonction jamais exécutée — chacune ouvrant son fichier à la ligne.

Visual Studio: Check Coverage Thresholds, with the findings in the Error List beside the compiler's ownScreenshot pending — add assets/img/vs-error-list.png (see SCREENSHOTS.md).
Dans Visual Studio : Check Coverage Thresholds, avec les constats dans l'Error List.

Profils de seuils

threshold.profile décide de ce que vaut un seuil que vous n’avez pas défini. standard, la valeur par défaut depuis 0.2026.82, correspond à ce que l’on peut exiger d’un projet ordinaire sans enjeu de sécurité. safety place chaque garde-fou à 100 — ce qu’exige un dossier de sécurité, et exactement ce qui était livré jusqu’à 0.2026.81.

Métriquestandardsafety
Lignes80100
Fonctions80100
Régions75100
Branches70100
Score composite75100
MC/DC, instanciations, appels de fonction, code objetsans garde-fou100
Conditionssans garde-fou100
Score de mutationsans garde-fousans garde-fou

Un seuil que vous avez défini l’emporte sur l’un et l’autre profil. L’exemple place le garde-fou des branches à 90 et tout le reste à 100 ; pour ne maintenir que certaines métriques à 100, restez sur standard et définissez-les vous-même. Une réserve découle du fonctionnement des paramètres : une valeur égale à la valeur par défaut livrée ne peut pas être distinguée d’une absence de valeur ; ainsi, sous safety, un seuil écrit exactement à sa valeur standard — 80 pour les lignes, par exemple — compte toujours comme 100.

{
  "fuciniCoverage.threshold.profile": "safety",
  "fuciniCoverage.threshold.branch": 90
}
The settings panel: the threshold profile above the grid of thresholds, showing the standard figuresScreenshot pending — add assets/img/threshold-profile.png (see SCREENSHOTS.md).
Switching the threshold profile to safety in the settings panel: the live preview asks for 100% everywhere; back on standard it asks for 80, 70, 80 and 75 and marks the rest as not gatedScreenshot pending — add assets/img/threshold-profiles.gif (see SCREENSHOTS.md).

Si vous comptiez sur les anciennes valeurs par défaut, vous êtes jugé avec plus d’indulgence après la mise à jour vers 0.2026.82, jusqu’à ce que vous sélectionniez safety. Une installation qui fonctionnait déjà auparavant en est informée une seule fois, avec un bouton Keep 100% (safety) qui écrit le profil dans vos paramètres utilisateur ; pour un projet partagé, inscrivez-le aussi dans les paramètres de l’espace de travail, afin que tout le monde soit jugé de la même façon. Configure Coverage Compliance & Thresholds... présente le profil au-dessus de la grille des seuils, et son aperçu en direct juge avec les garde-fous réellement en vigueur. Dans chaque carte et chaque rapport, une métrique dont le garde-fou est désactivé affiche sa valeur avec un tiret neutre au lieu d’une coche ou d’une croix.

The status-bar card under the standard profile: two of four gates below threshold, and a neutral mark on the metrics that are not gatedScreenshot pending — add assets/img/statusbar-metrics.png (see SCREENSHOTS.md).

11a. Couverture du code objet

Toutes les autres métriques ici se mesurent à la source : un outil instrumente votre code, la build instrumentée s'exécute, et les compteurs disent quelles instructions, branches ou conditions ont été exercées. La couverture du code objet mesure autre chose — quelle part du binaire construit s'est réellement exécutée, comptée en octets d'instructions, en observant le flux d'instructions plutôt qu'en instrumentant la source. Cela compte parce qu'un compilateur émet du code dont aucune ligne de votre source ne rend compte : vérifications de bornes de tableaux, tables de saut de switch, sauvegardes de registres, sondes de pile, appels aux routines d'exécution pour la division ou le flottant sur des cœurs dépourvus de l'instruction. C'est aussi la seule métrique ici qui réponde à la question cela couvre-t-il l'assembleur ? — l'assembleur écrit à la main n'est jamais instrumenté et un outil travaillant sur la source ne l'atteint pas. DO-178C dit explicitement pourquoi : au niveau A, lorsqu'un compilateur ou un éditeur de liens génère du code qui n'est pas directement traçable jusqu'aux instructions source, l'objectif 6.4.4.2b exige une vérification supplémentaire précisément de ce code généré.

Elle subsume la couverture des instructions — toute instruction machine exécutée provient d'une instruction source, donc 100% de couverture du code objet implique 100% de couverture des instructions. La réciproque est fausse, et c'est précisément cette asymétrie qui justifie la mesure. Deux conséquences en découlent. Elle n'a aucun poids dans le score composite, car moyenner deux mesures des mêmes exécutions compte deux fois la même preuve ; elle est contrôlée à la place par fuciniCoverage.threshold.objectCode — une exigence plutôt qu'un poids, comme la norme le demande. Et l'écart est le livrable : une exécution à 100% de couverture de lignes et moins de 100% de couverture du code objet a localisé exactement le code produit par le compilateur dont votre source ne rend pas compte ; la fiche de conformité dit donc 312 octets jamais exécutés, avec 100% de couverture de lignes plutôt que de l'enfouir sous « 94% ». L'inverse — un binaire entier déclaré exécuté alors que sa source ne l'était pas — est une contradiction et non un score faible : presque toujours un fichier de trace périmé d'un côté d'une fusion, ou des noms de modules qui n'ont jamais correspondu aux chemins des fichiers. C'est signalé comme un constat.

La couverture du code objet exige que le binaire s'exécute là où ses instructions peuvent être observées. Il existe trois voies, dont les coûts diffèrent énormément. Seule la troisième produit de la couverture de code objet ; les deux premières figurent ici parce qu'elles résolvent un problème voisin, souvent celui qu'il vaut réellement la peine de résoudre.

  1. Une build instrumentée, exécutée sur la cible. Les compilateurs croisés GCC acceptent -fprofile-arcs -ftest-coverage, donc l'instrumentation qui marche sur un poste de travail marche sur la cible — sauf qu'un système bare-metal n'a pas de système de fichiers où écrire les compteurs .gcda, et souvent pas d'exit() au moment duquel les écrire. Les compteurs résident de toute façon en RAM : la solution est de vider cette mémoire et de reconstruire les fichiers hors cible ; embedded-gcov de la NASA JPL (Apache-2.0) fait exactement cela, sans système de fichiers, sans système d'exploitation et sans bibliothèque C standard. Vous obtenez la couverture des instructions, des branches et des fonctions d'une build produite par votre compilateur croisé, pour votre jeu d'instructions, sur votre matériel — pas de couverture de code objet, et le binaire mesuré est instrumenté, donc plus gros et plus lent que celui que vous livrez. Chargez le résultat en LCOV, gcovr JSON, gcov JSON ou, sur une chaîne d'outils antérieure à GCC 9, en listing texte .gcov.
  2. Un simulateur de jeu d'instructions. Exécutez le vrai binaire cible dans un simulateur et déduisez la couverture des adresses exécutées : pas de matériel, pas d'instrumentation, pas de sonde, et comme il observe des instructions il peut produire une véritable couverture de code objet. La limite est la fidélité : un simulateur modélise bien le cœur et moins bien les périphériques, donc traitez les résultats système avec méfiance s'il ne modélise pas finement votre silicium.
  3. Trace sur puce et débogueur. La voie de niveau certification, et la seule réellement non intrusive : l'unité de trace du cœur transmet le flux d'instructions à un débogueur, qui le transforme en couverture. Rien n'est instrumenté, la taille du code ne change pas et le comportement temporel n'est pas affecté — c'est précisément ce qui fait du résultat une preuve portant sur le binaire réellement livré. Vérifiez le silicium avant de budgéter : dans beaucoup de familles de microcontrôleurs, la trace complète n'existe que sur une variante d'émulation ou de développement dotée d'un grand tampon de trace et d'un port de trace rapide, tandis que les pièces de série exposent une unité de trace réduite, dont le repli proposé par le fabricant est une trace logicielle qui instrumente le code et consomme du temps CPU — supprimant la propriété même pour laquelle cette voie avait été choisie.

De nombreux projets embarqués mesurent la couverture en compilant les mêmes sources pour la machine de développement et en y exécutant les tests unitaires. C'est rapide, ne nécessite aucun matériel, et c'est le bon choix par défaut pour la plupart des équipes — mais il vaut la peine d'être clair sur ce que décrit cette preuve : un compilateur différent, un optimiseur différent, un jeu d'instructions différent et un binaire différent de celui qui est livré. Pour la plupart des logiciels, c'est un compromis acceptable et bien compris. Pour un travail évalué selon l'IEC 61508, l'ISO 26262 ou la DO-178C, c'est l'objection classique hôte contre cible, et les voies ci-dessus en sont les réponses classiques — la première la referme pour la couverture source, la troisième pour le code objet.

Aujourd'hui, l'export lu pour le code objet est celui de COVerage.EXPORT.ListModule de Lauterbach TRACE32 avec metric="object" ; chargez-le comme n'importe quel autre fichier de trace. Cette métrique est notée et contrôlée uniquement sous licence payante et pendant la période d'évaluation. Une installation Community ne la note pas — mais elle est informée qu'un fichier de trace la contient, car un verdict de conformité qui omettrait silencieusement la preuve la plus forte du fichier serait pire qu'un verdict qui dit ce qu'il a omis.

12. Exclusion des lignes non-code

Lorsque excludeComments est activé (par défaut), les instructions entièrement situées sur des lignes de commentaire seul ou vides sont exclues des totaux — cela neutralise aussi une particularité connue de llvm-cov/gcov où un compteur de passage égaré atterrit sur un commentaire. Les marqueurs standard sont également respectés :

x = risky();          // LCOV_EXCL_LINE
// LCOV_EXCL_START
debug_only_block();
// LCOV_EXCL_STOP

Les directives du préprocesseur ne comptent pas non plus comme du code, en C, C++, Objective-C, CUDA et C# : une ligne qui commence par # — #define, #include, #if — et les lignes sur lesquelles une barre oblique inverse finale la prolonge. gcov impute chaque utilisation d’une macro à la ligne où elle est définie, si bien qu’un en-tête dont la seule ligne rapportée était #define CHANNEL_COUNT (33U) apparaissait couvert à 100 % parce qu’une boucle du fichier .c tournait jusqu’à cette valeur, et qu’un autre dont personne n’utilisait la constante apparaissait à 0 %. Un tel en-tête n’a désormais plus rien à mesurer et n’est pas listé.

Réglez excluded.includeInTotals sur true pour comptabiliser malgré tout les lignes exclues.

Écarter un fichier ou un dossier, depuis l’arbre

Cliquez avec le bouton droit sur un fichier ou un dossier de la vue Coverage et choisissez Exclude from Coverage — il figure aussi parmi les actions de chemin de la ligne — ou lancez Exclude This File from Coverage sur le fichier ouvert : le chemin du fichier relatif à l’espace de travail, ou le /** du dossier, va dans fuciniCoverage.ignore des réglages du dossier, une fois, et le rechargement le retire de chaque total et de chaque page ; le motif est là pour être retiré à son tour. Dans Visual Studio, le menu de la ligne et Tools → Coverage Studio ont les deux mêmes commandes, qui écrivent le même réglage dans le même fichier.

Right-click a folder row in the Coverage view, Exclude from Coverage, and the tree redraws without it while the pattern appears in settings.jsonScreenshot pending — add assets/img/exclude-from-tree.gif (see SCREENSHOTS.md).
Exclude from Coverage sur un dossier : l’arbre sans lui, le motif dans les réglages.
Visual Studio: Exclude This File from Coverage on fees.ts, the tree without fees.ts, then .vscode/settings.json with the pattern src/fees.ts under fuciniCoverage.ignore
Dans Visual Studio : Exclude This File from Coverage sur fees.ts — l’arborescence sans lui, le motif dans .vscode/settings.json.

Attributs et espaces de noms, pour .NET

Deux réglages lisent dans le source ce que le rapport ne sait pas dire. ignore.attributes — ExcludeFromCodeCoverage par défaut — exclut la classe, la méthode ou la propriété placée sous un attribut qu’il nomme, comme LCOV_EXCL_START/STOP le ferait, quel que soit l’outil qui a écrit le rapport : Coverlet honore l’attribut, OpenCover, dotCover et un lcov converti non, et désormais tous s’accordent. Les noms avec ou sans le suffixe Attribute, avec ou sans espace de noms ; ajoutez GeneratedCode, Obsolete ou les vôtres. ignore.namespaces écarte chaque fichier dont la déclaration d’espace de noms correspond à un préfixe, * comme joker — Acme.Generated, Acme.*.Migrations, *Tests — et le volet Output nomme les fichiers qu’il a retirés. Les deux sont lus dans la même passe que les marqueurs de commentaire, dans les deux éditions.

{
  "fuciniCoverage.ignore.attributes": ["ExcludeFromCodeCoverage", "GeneratedCode"],
  "fuciniCoverage.ignore.namespaces": ["Acme.Generated", "*.Migrations"]
}

Exclure depuis l’éditeur

Sélectionnez les lignes et prenez Exclude Selection from Coverage dans l’ampoule, le menu contextuel de l’éditeur ou la Command Palette — dans Visual Studio l’ampoule (Ctrl+.), le menu du clic droit de la fenêtre de code, Tools → Coverage Studio ou Ctrl+Shift+U, X — et l’exclusion est écrite là où est le code : [ExcludeFromCodeCoverage] au-dessus d’une classe, d’une méthode ou d’une propriété C#, VB ou F#, par son nom court lorsque le fichier importe déjà System.Diagnostics.CodeAnalysis et pleinement qualifié lorsqu’il ne l’importe pas, pour qu’aucun using n’ait à être ajouté ; LCOV_EXCL_LINE à la fin d’une ligne de code ; LCOV_EXCL_START et LCOV_EXCL_STOP autour de plusieurs, à l’indentation de la première — avec le signe de commentaire propre au langage, //, #, ', -- ou ;. Une seule étape d’annulation. L’ampoule le propose aussi sur une ligne que les entrées Problems marquent comme non couverte. Une ligne déjà marquée, ou un membre déjà attribué, est laissé tel quel.

A selection in a C# method, the light bulb, Exclude from coverage, and the LCOV_EXCL_START and STOP lines appearing around itScreenshot pending — add assets/img/exclude-selection.gif (see SCREENSHOTS.md).
Exclude Selection from Coverage : les marqueurs écrits autour de la sélection, avec le signe de commentaire propre au fichier.
Visual Studio: four lines of an else-if branch in Quote.cs selected, Exclude Selection from Coverage writing LCOV_EXCL_START and LCOV_EXCL_STOP around them, then ExcludeFromCodeCoverage above a method
Dans Visual Studio : Exclude Selection from Coverage — les marqueurs LCOV_EXCL autour d’une branche, puis [ExcludeFromCodeCoverage] au-dessus d’une méthode.

Les branches seules, et les marqueurs de gcovr

Un else défensif, un default: qu’aucune valeur n’atteint, la branche qu’un compilateur ajoute pour une exception : la ligne s’exécute et doit compter, et seule sa branche ne peut pas être prise. LCOV_EXCL_BR_LINE et LCOV_EXCL_BR_START … LCOV_EXCL_BR_STOP retirent du compte les branches de leurs lignes et y laissent les lignes. LCOV_EXCL_EXCEPTION_BR_LINE et sa région retirent moins encore — seulement les branches qu’une exception emprunte, là où le rapport dit lesquelles, comme le fait le JSON de gcov. Chaque marqueur est lu aussi sous les préfixes de gcovr : GCOVR_EXCL_LINE, GCOVR_EXCL_START, GCOVR_EXCL_BR_LINE, GCOV_EXCL_STOP et les autres signifient ce que signifient les LCOV_EXCL_, si bien qu’un source écrit pour gcovr se lit de la même façon ici, quel que soit l’outil qui a produit le rapport. Non lu : GCOVR_EXCL_FUNCTION — rien sur cette ligne ne dit où finit la fonction.

if (handle == NULL) return E_FAIL;   // LCOV_EXCL_BR_LINE: the allocator never fails on target
  // LCOV_EXCL_BR_START generated state table
  switch (state) { /* … */ }
  // LCOV_EXCL_BR_STOP
LCOV_EXCL_BR_LINE on a line: the line still counted, its branch gone from the countScreenshot pending — add assets/img/branch-markers.png (see SCREENSHOTS.md).

Dire pourquoi : les exclusions justifiées

Retirer du code du compte est une affirmation — « ceci ne peut pas être testé », « ceci est une aide au développement » — et sous DO-178C, ISO 26262 ou IEC 61508, une affirmation qui change le chiffre sur lequel repose un certificat doit être consignée par écrit et pouvoir être revue. Une exclusion peut donc dire pourquoi, à l’endroit où elle est écrite : le texte après LCOV_EXCL_LINE ou LCOV_EXCL_START, ou la Justification de [ExcludeFromCodeCoverage].

abort();                 // LCOV_EXCL_LINE: defensive, unreachable by construction
  // LCOV_EXCL_START debug dump, never built for the target

  [ExcludeFromCodeCoverage(Justification = "a developer aid")]
  public static void DebugDump(decimal amount) { /* … */ }

Les raisons sont lues à chaque chargement et le journal les compte. Export Coverage Report… écrit la liste — les exclusions et leurs justifications, en Markdown ou en CSV : le fichier, les lignes, la façon dont l’exclusion est écrite, et la justification ou none given. Un fichier où il ne reste rien de mesurable figure tout de même dans cette liste. Avec exclusions.requireReason activé, une exclusion qui ne donne pas de raison est un constat : un avertissement dans Problems à sa ligne, et un échec de Check Coverage Thresholds. Exclude Selection from Coverage demande alors d’abord la raison et l’écrit avec le marqueur ou comme Justification de l’attribut ; si la demande est refermée ou laissée vide, rien n’est exclu.

An exclusion without a reason flagged as a warning at its line, and the exported list with none givenScreenshot pending — add assets/img/justified-exclusions.png (see SCREENSHOTS.md).
Visual Studio: an exclusion without a reason as a warning at its line, and the exported list with none givenScreenshot pending — add assets/img/vs-justified-exclusions.png (see SCREENSHOTS.md).
Dans Visual Studio : une exclusion sans motif, en avertissement sur sa ligne, et la liste exportée avec none given.

12a. Cette couverture décrit-elle encore ce fichier ?

La couverture lue dans un fichier de trace décrit le source tel qu'il était au moment des tests, et la plupart des formats ne disent rien de la version concernée. Chaque fichier du panneau Couverture est donc dans l'un de trois états :

  • ✓ Vérifié — le fichier de couverture consigne ce que contenait chaque ligne mesurée, et cela correspond toujours au fichier.
  • Rien d'affiché — non infirmé. Rien ne contredit la couverture, rien ne la confirme. C'est l'état ordinaire.
  • ⚠ Contredit — le fichier lui-même infirme sa couverture. La ligne est estompée et l'infobulle dit ce qui a été trouvé.

Seuls deux formats peuvent mériter la coche, car seuls deux consignent quelque chose sur le source mesuré : lcov écrit avec --checksum (désactivé par défaut dans geninfo ; sa raison d'être documentée est précisément d'empêcher de combiner la couverture de deux versions d'un fichier) et GNATcoverage XML, qui embarque le texte de chaque ligne mesurée. Activer l'option lcov en vaut la peine.

L'avertissement n'a besoin d'aucun des deux et fonctionne avec tous les formats : couverture enregistrée au-delà de la fin du fichier, fonction nommée qui n'est plus là où le rapport la place, ou lignes exécutées qui sont vides dans le fichier. Les horodatages ne suffisent jamais à eux seuls — un git checkout les modifie tous sans changer un octet —, un horodatage modifié n'est donc au plus qu'une raison de regarder à nouveau. La vérification s'exécute au chargement de la couverture et de nouveau chaque fois qu'un fichier est enregistré ou change sur le disque, de sorte que la marque suit le fichier : une modification qui contredit l'exécution la pose, un checkout qui restaure la version mesurée l'efface. L'infobulle dit exactement ce qui l'a prouvé. Mettez staleWarning.enabled à false pour tout désactiver.

12b. Non mesuré et non couvert

Un fichier que l’exécution ne mentionne jamais est non mesuré : aucun test ne l’a chargé, donc aucun outil n’a écrit une ligne à son sujet. Ce n’est pas la même chose que non couvert — mesuré, avec zéro passage — et l’extension n’a jamais noté un fichier absent à 0 %. Ce qu’elle ne faisait pas, jusqu’à 0.2026.69, c’était montrer les absents tout court : un module sans le moindre test n’apparaissait jamais dans l’arbre, les totaux ni le contrôle des seuils, et un lecteur voyait « 92 % » pour un projet dont la moitié des fichiers n’avait jamais été exercée.

Désormais, avec une exécution chargée, l’élément par fichier de la barre d’état dit not measured pour un fichier source du type propre à l’exécution que l’exécution ne contient pas — « du type de l’exécution » signifiant qu’il porte l’une des extensions de fichier que l’exécution a mesurées, si bien que les en-têtes et les sources d’un projet C sont candidats et ses scripts Python ne le sont pas. Tout le reste est sur demande, via fuciniCoverage.unmeasured.mode :

  • off (par défaut) — rien d’autre ne change.
  • list — la vue Coverage reçoit en bas un groupe Unmeasured nommant chacun de ces fichiers, chaque ligne l’ouvrant ; le résultat du chargement les compte ; les badges les marquent ? dans l’Explorateur ; et fuciniCoverage.threshold.unmeasuredFiles peut faire échouer Check Coverage Thresholds quand il y en a plus qu’un nombre que vous fixez. Aucun pourcentage ne bouge.
  • count — tout ce que fait list, et chaque fichier non mesuré compte aussi contre l’exécution comme un fichier non couvert de ses propres lignes de code, si bien que la barre d’état, les seuils, les badges, l’historique, chaque export et la vue Test Coverage affichent le chiffre inférieur. Le fichier est dessiné comme non mesuré partout où il apparaît, ses barres de gouttière disent « non mesuré » plutôt que « jamais exécuté », et le contrôle de non-concordance le laisse tranquille — il n’y a aucune mesure que son contenu puisse contredire.
{
  "fuciniCoverage.unmeasured.mode": "list",
  "fuciniCoverage.threshold.unmeasuredFiles": 0
}

Les fichiers d’en-tête sont le faux positif connu en C : ils ont la famille d’extensions de l’exécution et aucun fichier de trace n’en nommera jamais un, parce qu’à lui seul il ne se compile en rien. fuciniCoverage.unmeasured.exclude écarte donc par défaut **/*.h, **/*.hpp, **/*.hh, **/*.inl et **/*.d.ts, dans la même syntaxe glob que fuciniCoverage.ignore ; ajoutez-y un portage vers une plateforme qui n’est pas construite ici, ou des stubs générés, et ils sortent de la liste, du décompte et de l’état de la barre d’état. Un fichier nommé par ignore n’est jamais dit non mesuré non plus — le laisser de côté était le but. threshold.unmeasuredFiles vaut -1 par défaut, ce qui ne contrôle rien ; 0 échoue dès qu’un fichier du type de l’exécution n’a jamais été chargé par un test, et il ne s’applique que tant que unmeasured.mode vaut list ou count.

13. Rapports HTML

  • Generate Full HTML Report — un rapport multi-pages auto-rendu, par répertoire. La sortie va dans htmlReport.outputDir, ou dans le stockage global de l'extension si non défini.
  • Open Annotated Source — une vue annotée d'un seul fichier. Pointez externalHtmlReport.dir vers un répertoire llvm-cov show --format=html préconstruit pour utiliser ces pages au lieu du moteur de rendu intégré.
  • Export Fucini JSON — le modèle normalisé complet pour votre propre outillage.
  • Export Coverage Report... — l'exécution en CSV (par fichier ou par fonction), en résumé Markdown, en fichier de trace LCOV, en XML Cobertura, en SARIF, ou en badge SVG autonome pour votre README. Également accessible depuis le bouton voisin de Generate Full HTML Report dans la vue Covered Files. Tout sauf les CSV est à perte — MC/DC, régions et instanciations n'ont pas leur place en LCOV, Cobertura ou SARIF — donc Fucini JSON et les CSV restent les formats qui portent toutes les métriques.
  • Copy Uncovered Lines — un résumé Markdown de chaque lacune, prêt à coller dans une PR.

Dans Visual Studio. Le groupe Reports de Tools → Coverage Studio : Show Annotated Source ouvre le document actif comme une page dans la zone des documents — chaque ligne dans sa couleur, les constats à côté — qui défile avec l'éditeur dans les deux sens ; Open HTML Report écrit le rapport d'une page dans htmlReport.outputDir (ou %LOCALAPPDATA%\Fucini\CoverageStudio\html-report) et ouvre le navigateur ; Generate Full HTML Report y écrit l'index par dossier et la page par fichier ; Export Coverage Report… propose les huit mêmes formats et demande où enregistrer ; Generate Coverage Badge écrit le badge là où badge.outputPath l'indique, après chaque chargement avec badge.autoUpdate. La page annotée a besoin de WebView2, comme la fenêtre Coverage ; les rapports sur disque non.

Visual Studio: Show Annotated Source — the file as a page in the document well, beside the editorScreenshot pending — add assets/img/vs-annotated-source.png (see SCREENSHOTS.md).
Dans Visual Studio : Show Annotated Source — le fichier sous forme de page dans la zone des documents, à côté de l'éditeur.
Multi-page HTML report directory indexScreenshot pending — add assets/img/report.png (see SCREENSHOTS.md).
The report, Directory Coverage Summary: one row per folder, a column for every metric the run carriesScreenshot pending — add assets/img/report-directory-summary.png (see SCREENSHOTS.md).
The report, File Coverage Summary: one row per file, with Max CRAP where the report carries complexityScreenshot pending — add assets/img/report-file-summary.png (see SCREENSHOTS.md).
The report, Coverage Gaps: every function with uncovered branches or MC/DC conditions, named as writtenScreenshot pending — add assets/img/report-coverage-gaps.png (see SCREENSHOTS.md).
The report, MC/DC Expression Detail: conditions covered per decisionScreenshot pending — add assets/img/report-mcdc-detail.png (see SCREENSHOTS.md).
Export Coverage Report: CSV per file or per function, a Markdown summary, LCOV, Cobertura XML, SARIF, or an SVG badgeScreenshot pending — add assets/img/export-picker.png (see SCREENSHOTS.md).
The report’s annotated page for src/calc.c: per-line hit counts, a fully covered function, an uncovered else branch, a 1/2 partial branch, an MC/DC expansion and a never-called functionScreenshot pending — add assets/img/annotated-source.png (see SCREENSHOTS.md).

Source annotée et source brute

Open Annotated Source remplace l'onglet actif par une vue web de couverture en couleur pour ce fichier, dans la même colonne ; Open Annotated Source to the Side fait de même mais dans un volet scindé, afin que la source et la vue annotée soient côte à côte. Pour basculer plutôt sur place — pratique sur un petit écran où un fractionnement rend chaque volet trop étroit — utilisez Toggle Annotated Source : cela permute l'onglet actif entre les deux vues, en mémorisant celle que vous consultez actuellement. Depuis la vue annotée elle-même, Show Source revient directement à l'éditeur normal pour ce fichier.

Le HTML que vous voyez réellement dépend de externalHtmlReport.dir : si ce paramètre est défini et qu'une page correspondant au fichier actif y existe déjà (llvm-cov organise les pages par fichier sous la forme <nom-repo>/<chemin-relatif>.html, donc le dossier du nom du dépôt du rapport n'a jamais besoin d'être configuré), cette page générée par la chaîne d'outils est affichée à la place du moteur de rendu intégré — ses liens/feuille de style locaux sont réécrits pour fonctionner dans la vue web, et elle contient des détails que la vue intégrée ne reproduit pas (vues d'expansion MC/DC, mise en évidence des régions, récapitulatifs par répertoire). Aucune page correspondante pour ce fichier, ou paramètre laissé vide ? Le moteur de rendu intégré est alors utilisé. L'extension ne fait que lire ce répertoire — elle n'y écrit jamais.

Un badge de couverture pour le README

Generate Coverage Badge écrit dans l’espace de travail un SVG de style shields pour l’exécution active — badge.outputPath, par défaut coverage-badge.svg, relatif au dossier de l’espace de travail ou absolu, avec les mêmes variables que tout autre réglage de chemin — et propose de l’ouvrir. C’est un simple fichier dans votre dépôt, si bien qu’un README l’intègre sans aucun service derrière, sans aller-retour vers shields.io, et cela fonctionne aussi dans un dépôt isolé du réseau :

![coverage](coverage-badge.svg)

coverage: 83%

badge.metric choisit ce que le badge affiche : lines (libellé coverage), branches, mcdc ou weighted, le même score composite que montre la barre d’état, libellé score. Une exécution sans données pour la métrique choisie reçoit un n/a gris plutôt qu’un 0 % rouge. La couleur suit vos propres paliers colorScale.* : lowColor sous lowThreshold, midColor jusqu’à highThreshold, highColor à partir de là. Avec badge.autoUpdate activé, le badge est réécrit après chaque chargement réussi, silencieusement, et le canal de sortie consigne chaque écriture sous [FUCINI_BADGE] — désactivé par défaut parce qu’il écrit dans l’espace de travail à chaque chargement. Validez le SVG avec le code et l’image sur la page du dépôt suit le chiffre de l’éditeur.

{
  "fuciniCoverage.badge.outputPath": "docs/coverage-badge.svg",
  "fuciniCoverage.badge.metric": "weighted",
  "fuciniCoverage.badge.autoUpdate": true
}

14. Historique et tendances

Activez history.enabled pour conserver les exécutions localement (en conservant history.retention d’entre elles). Vous obtenez alors une flèche de tendance (▲/▼) dans la barre d’état, le graphique de tendance dans la vue Coverage et deux commandes de comparaison : Compare with Last Run et Compare Two History Runs, chacune produisant une diff de régression/amélioration par fichier.

Dans Visual Studio. Chaque chargement est comparé au précédent : un triangle dans la marge sur chaque ligne qui a commencé ou cessé de s’exécuter (sinceLastRun.enabled), la tendance à côté du score dans la barre d’état, et Compare with Last Run pour les fichiers dont les chiffres ont bougé. Avec history.enabled, les exécutions sont conservées sous %LOCALAPPDATA%\Fucini\CoverageStudio\history, à raison de history.retention d’entre elles, si bien que la comparaison survit à un redémarrage, que le graphique de tendance a de quoi dessiner, et que Compare Two History Runs… en choisit deux quelconques.

Compare with Last Run: the run moved from 83.89% to 83.05%, calc.c lost 4.54 points, and the status bar carries the trendScreenshot pending — add assets/img/history-compare.png (see SCREENSHOTS.md).
Since last run: a red mark on the lines that ran in the previous run and not in this one, a green one on the lines that are newly coveredScreenshot pending — add assets/img/since-last-run.png (see SCREENSHOTS.md).

Le graphique de tendance

Sous la barre d’outils de la vue Coverage, avec au moins deux exécutions enregistrées, la couverture des lignes de l’historique tracée en courbe, de la plus ancienne à la plus récente, les trente dernières : un point par exécution, qui dit sa date et son chiffre au survol, et le dernier chiffre à côté, avec une flèche pour la direction depuis la première. L’échelle verticale est la plage des exécutions elles-mêmes, si bien qu’une équipe à 92–94% voit le mouvement plutôt qu’une ligne plate sous 100. Les deux éditions le dessinent à partir du même historique.

The trend chart under the Coverage view's toolbar: a line over a dozen runs, a dot per run, the last figure and an arrow upScreenshot pending — add assets/img/trend-chart.png (see SCREENSHOTS.md).
La tendance : un point par exécution enregistrée, le dernier chiffre à côté.
Visual Studio: the trend line under the Coverage window toolbar, the last figure 68.25%
Dans Visual Studio : la tendance sous la barre d’outils de la fenêtre Coverage, le dernier chiffre 68.25%.

Sessions de couverture

Une seule exécution de tests couvre rarement tout ce qu’une modification a touché : les tests unitaires ont tourné ici, la suite d’intégration là, un parcours de l’interface avec la couverture activée ailleurs. Start Coverage Session fait des chargements qui suivent une seule somme — chaque exécution s’ajoute à la précédente ligne par ligne, en union : une ligne que l’une d’elles a exécutée est couverte, et les compteurs s’additionnent — si bien que la gouttière, l’arbre et le score montrent ce qu’elles ont atteint toutes ensemble. L’exécution à l’écran, s’il y en a une, est la première de la session. Une barre au-dessus de l’arbre dit combien d’exécutions depuis quand et met fin à la session ; End Coverage Session fait de même, et le chargement suivant se tient de nouveau seul. Dans Visual Studio, une seule entrée sous Tools → Coverage Studio démarre la session et, cochée, y met fin.

A coverage session: the unit test run loads, the session starts, the integration run loads on top, and the bar says two runs while the tree's numbers riseScreenshot pending — add assets/img/coverage-session.gif (see SCREENSHOTS.md).
Une session de deux exécutions : la seconde ajoutée à la première, la barre au-dessus de l’arbre qui les compte.
Visual Studio: the unit run loaded, Start Coverage Session, the integration run added, the bar saying 2 runs and lines at 68.25%, then the session ended
Dans Visual Studio : Start Coverage Session, puis une deuxième exécution ajoutée à la première — la barre compte deux exécutions, les lignes passent de 50.79% à 68.25%.

La référence CI : où en suis-je par rapport à main ?

Compare with Last Run répond à ce qu’a fait votre dernière modification ; avant une pull request, la question est où vous en êtes par rapport à main, et la réponse est sur le serveur de build. baseline.report nomme le rapport que publie le build de la branche main, et chaque chargement lui est comparé : la carte de la barre d’état porte le delta en une ligne — vs CI baseline: 84.20% → 85.10% (+0.90%), 3 file(s) moved — et Compare with CI Baseline liste les fichiers qui ont bougé, fichier par fichier, dans les mêmes termes que Compare with Last Run. Dans Visual Studio, la commande est sous Tools → Coverage Studio et récupère ou lit le rapport quand vous le demandez. Trois façons de le nommer, dans .vscode/settings.json :

  1. Une URL servie par la CI. GitLab garde les artefacts du dernier job d’une branche à une adresse stable ; le jeton reste hors du fichier de réglages grâce à ${env:…} dans remote.headers. Jenkins : https://jenkins.example.com/job/app/job/main/lastSuccessfulBuild/artifact/coverage/lcov.info. TeamCity : https://tc.example.com/repository/download/App_Main/.lastSuccessful/coverage/lcov.info avec Authorization: Bearer ${env:TC_TOKEN}. L’URL est récupérée et mise en cache exactement comme une URL de coverageFile.paths (ETag, remote.refreshMinutes).
  2. Un fichier que le pipeline a copié sur un partage — un chemin absolu tel que \\build\drops\app\main\coverage.cobertura.xml.
  3. Un artefact téléchargé conservé sous le dossier, disons ci/main.lcov.info (mettez le dossier dans .gitignore) — un chemin relatif au dossier.
{
  "fuciniCoverage.baseline.report": "https://gitlab.example.com/api/v4/projects/42/jobs/artifacts/main/raw/coverage/lcov.info?job=test",
  "fuciniCoverage.remote.headers": ["PRIVATE-TOKEN: ${env:GITLAB_TOKEN}"]
}

Tout format que le lecteur connaît convient. Un chemin que la CI a écrit relatif à son checkout — src/Billing/Invoice.cs, comme Coverlet l’écrit sur le runner — est placé sous ce dossier avant la diff, pour qu’il rencontre le fichier que l’exécution locale a résolu ; un chemin absolu d’une autre machine ne correspond à rien, faites donc écrire des chemins relatifs au pipeline. Une référence qui ne peut être ni récupérée ni lue est une ligne dans le volet Output, jamais un chargement en échec.

Compare with CI Baseline: the status bar's card with the vs CI baseline line, then the command listing the files that moved against main, regressions firstScreenshot pending — add assets/img/ci-baseline.gif (see SCREENSHOTS.md).
La référence CI : le delta sur la carte, et les fichiers qui ont bougé par rapport à main.
Visual Studio: baseline.report set to the unit suite report, then Compare with CI Baseline showing statements 50.79% to 68.25% and branches 30.43% to 50.00%, one file changed
Dans Visual Studio : Compare with CI Baseline — instructions et branches face au rapport des tests unitaires, et le fichier qui a changé.

Un artefact est un zip, et cela se lit aussi. GitHub et GitLab remettent un artefact sous forme d’archive, quel qu’en soit le contenu. Nommez le rapport qu’elle contient après un # : le membre est trouvé par son chemin ou par la fin de celui-ci ; sans #, c’est le seul fichier de l’archive, ou son seul fichier qui ressemble à un rapport, et là où il y en a plusieurs le volet Output les nomme. Il en va de même pour un zip que vous avez téléchargé (ci/artifact.zip#lcov.info) et, dans VS Code, pour une URL dans coverageFile.paths. Le jeton va au serveur pour lequel il a été défini et pas plus loin : la redirection vers le stockage qui contient l’archive est suivie sans lui.

{
  "fuciniCoverage.baseline.report": "https://api.github.com/repos/acme/app/actions/artifacts/1234567/zip#coverage/lcov.info",
  "fuciniCoverage.remote.headers": ["Authorization: Bearer ${env:GITHUB_TOKEN}"]
  }

14a. Pour les agents IA : la couverture à l’écran

Un agent qui écrit des tests peut les lancer et lire un pourcentage. Ce qu’il ne peut pas faire seul, c’est demander ce que sait l’éditeur : quelles lignes de cette fonction n’ont jamais été exécutées, quel côté de quelle branche, quels tests atteignent une ligne, si la diff qu’il vient d’écrire est couverte. Six outils répondent exactement à cela, en des termes sur lesquels un agent peut agir, à partir de l’exécution chargée — les mêmes exclusions, le même remappage, les mêmes chiffres qu’à l’écran. Ainsi, un agent chargé de combler les lacunes d’une fonction et un relecteur qui regarde la gouttière parlent des mêmes lignes.

OutilCe à quoi il répond
coverage_summaryLes totaux de l’exécution par métrique, et les fichiers les plus éloignés d’une couverture complète. La première chose à demander.
coverage_gapsCe qui n’a jamais été exécuté dans un fichier, une fonction ou une plage de lignes : les lignes non couvertes, les branches non prises, les conditions MC/DC sans leur paire, les mutants qui ont survécu.
tests_for_lineQuels tests ont exécuté une ligne, là où le rapport le dit — une exécution par test.
patch_coverageLa couverture d’une diff — l’arbre de travail par rapport à une référence git, ou un patch fourni — et celles de ses lignes qui n’ont jamais été exécutées.
coverage_deltaCe qui a bougé depuis l’exécution précédente : les totaux, et les fichiers qui ont gagné ou perdu.
test_run_commandLa commande qui lance les tests de cet espace de travail avec la couverture activée. L’agent la lance ; l’éditeur recharge le rapport de lui-même.

L’agent propre à VS Code les a comme outils, sans rien configurer. Tous les autres agents — tout client qui parle MCP, le Model Context Protocol — y accèdent par un serveur que l’éditeur lance quand mcp.enabled est activé, dans VS Code comme dans Visual Studio. Copy MCP Server Configuration place l’entrée du client dans le presse-papiers, telle que VS Code et Visual Studio la lisent dans un mcp.json ; un client qui nomme la clé externe mcpServers prend la même entrée sous ce nom.

Copy MCP Server Configuration and its message, the token painted overScreenshot pending — add assets/img/mcp-config.png (see SCREENSHOTS.md).
Visual Studio: Copy MCP Server Configuration and its message; the token painted overScreenshot pending — add assets/img/vs-mcp-config.png (see SCREENSHOTS.md).
Dans Visual Studio : Copy MCP Server Configuration et son message ; le jeton masqué.
{
  "servers": {
    "fucini-coverage": {
      "type": "http",
      "url": "http://127.0.0.1:39217/mcp",
      "headers": { "Authorization": "Bearer …" }
    }
  }
  }
  • Il est désactivé tant que vous ne l’activez pas, et il n’écoute que sur 127.0.0.1 : rien d’extérieur à cette machine ne l’atteint.
  • Un appel doit porter votre jeton, créé une fois et conservé pour vous ; sans lui, la réponse est 401. La configuration copiée contient le jeton : gardez-la hors du dépôt.
  • Un appel envoyé par une page web — il le dit dans son Origin — est refusé, quoi qu’il porte.
  • Il lit l’exécution chargée et n’écrit rien. L’exécution des tests est nommée, pas lancée : l’agent lance la commande dans son propre terminal.

Le port est mcp.port, 39217 par défaut. Là où il est pris — une deuxième fenêtre, l’autre édition à côté de celle-ci — le port libre suivant est utilisé, et la configuration copiée nomme celui qui fonctionne. Le volet Output dit où le serveur écoute ([FUCINI_MCP]) et pourquoi il n’a pas pu ([FUCINI_MCP_001]). Ce qu’une offre n’inclut pas — les noms des tests, le détail MC/DC — les outils le comptent sans le détailler, comme le fait le survol.

15. Référence des commandes

Dans Visual Studio. Chaque commande est sous Tools → Coverage Studio, nommée comme dans le tableau sans le préfixe Fucini Coverage: ; la barre d’outils de la fenêtre Coverage et le menu du clic droit d’une ligne ont celles qui y ont leur place, et le menu du clic droit de la fenêtre de code a les trois qui agissent sur l’éditeur : Run This Test with Coverage, Show Tests That Ran This Line et Exclude Selection from Coverage. Celles avec des touches sont des accords en deux frappes après Ctrl+Shift+U : R recharge, N et P vont à la ligne non couverte suivante et précédente, B à la prochaine décision partiellement testée, T liste les tests qui ont exécuté la ligne, X exclut la sélection — pas le Alt+N de VS Code, car dans Visual Studio Alt et une lettre ouvrent un menu. Modifiez-les sous Tools → Options → Keyboard, où elles sont listées comme Coverage Studio: …. Absents de cette édition : le panneau Test Coverage est une API VS Code — l’exécution est dans la fenêtre Coverage à la place — et l’Explorateur de solutions ne peut pas afficher de badges. Seulement dans cette édition : Run Native Project with Coverage, pour un projet de démarrage C++.

Dans Visual Studio : où tout se trouve. La fenêtre Coverage est sous View → Other Windows → Coverage, et en premier sous Tools → Coverage Studio, où se trouve chaque commande de cette édition, par groupes : charger et recharger, surveiller le fichier, les deux copies et les cartes ; Run Tests with Coverage, Run Native Project with Coverage et Collect Coverage in Test Explorer… ; Next et Previous Uncovered et les décisions partiellement testées ; la coloration, les compteurs d’exécution et les modes de la gouttière ; la source de couverture d’un fichier, les tests qui ont exécuté une ligne, un test avec la couverture, les deux façons d’exclure ; Compare with Last Run, Compare Two History Runs…, Compare with CI Baseline, la session de couverture et Check Coverage Thresholds ; le groupe Reports — Show Annotated Source, Open HTML Report, Generate Full HTML Report, Export Coverage Report… et Generate Coverage Badge ; puis Getting Started, les seuils de conformité et Licence…. La barre d’outils de la fenêtre a les cinq commandes les plus utilisées : Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary et les seuils de conformité ; en dessous, la perspective, le filtre et le tri, et le champ de recherche ; en dessous encore, la tendance. Laissez le pointeur sur une ligne de l’arbre et appuyez sur son ⋯ pour le menu de la ligne — ouvrir le fichier, ouvrir son dossier, copier son chemin, absolu ou relatif, avec l’un ou l’autre type de barre oblique, l’exclure de la couverture. À droite de la barre d’état figurent le score de l’exécution et celui du fichier ouvert, avec la tendance depuis la dernière exécution ; Show Coverage Card et Show Coverage Card for This File ouvrent les cartes qui les détaillent, les mêmes que VS Code affiche quand le pointeur s’arrête sur son élément de barre d’état.

Visual Studio: Tools → Coverage Studio, open, with every command of the edition
Dans Visual Studio : Tools → Coverage Studio, avec chaque commande de cette édition.
Visual Studio: View → Other Windows, where the Coverage window is
Dans Visual Studio : View → Other Windows, où se trouve la fenêtre Coverage.
Visual Studio: the Coverage window's toolbar — Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary, compliance thresholds
Dans Visual Studio : la barre d’outils de la fenêtre Coverage — Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary et les seuils de conformité.
Visual Studio: a row's menu in the Coverage window — Open, Open Containing Folder, and the four Copy Path entries
Dans Visual Studio : le menu ⋯ d’une ligne — ouvrir le fichier, ouvrir son dossier, copier son chemin sous quatre formes.
Visual Studio: the status bar's two items, the run's score and the open file's
Dans Visual Studio : les deux éléments de la barre d’état, le score de l’exécution et celui du fichier ouvert.
Visual Studio: the run's coverage card, opened by Show Coverage Card
Dans Visual Studio : la carte de couverture de l’exécution, via Show Coverage Card.
Visual Studio: the open file's coverage card, opened by Show Coverage Card for This File
Dans Visual Studio : la carte du fichier ouvert, via Show Coverage Card for This File.
The status-bar hover cards for the run and the file, then the Coverage view toolbar: Pick Coverage File, Load Coverage, Export Coverage Report and Generate Full HTML Report, ending on the generated reportScreenshot pending — add assets/img/statusbar-and-toolbar.gif (see SCREENSHOTS.md).
Dans VS Code : les cartes au survol de la barre d’état pour l’exécution et le fichier, puis la barre d’outils de la vue Coverage, jusqu’au rapport généré.
The status-bar menu: select a coverage file, run tests with coverage, reload, open the HTML report, choose the gutter modeScreenshot pending — add assets/img/statusbar-menu.png (see SCREENSHOTS.md).
Dans VS Code : le menu de la barre d’état — choisir un fichier de couverture, lancer les tests avec couverture, recharger, ouvrir le rapport, choisir le mode de gouttière.
Show Worst-Covered Functions: every function of the run, lowest coverage first, with its CRAP score where the report carries complexityScreenshot pending — add assets/img/worst-functions.png (see SCREENSHOTS.md).
Dans VS Code : Show Worst-Covered Functions, couverture la plus faible en premier, avec le score CRAP là où le rapport porte la complexité.
CommandeRôle
Load CoverageDécouvrir et charger la couverture de l'espace de travail. Alt+Shift+R par défaut (Ctrl+Alt+R sous macOS).
Pick Coverage FileChoisir des fichiers de trace — un, plusieurs, ou un de plus à chaque fois ; les choix s'additionnent, sont fusionnés et écrits dans coverageFile.paths, si bien qu'ils se chargent ensuite tout seuls.
Show Loaded Coverage FilesLister les fichiers de trace de l'exécution active. La vue Couverture les liste aussi, chacun avec un bouton de déchargement et un bouton de choix à côté.
Toggle Tracefile WatchSurveiller le ou les fichiers de trace et recharger automatiquement.
Run Tests with CoverageReconnaître le lanceur de tests, l'exécuter avec la couverture dans une tâche de terminal, charger ce qu'il écrit et proposer d'ajouter le chemin aux paramètres.
Run This Test with CoverageLe test sous le curseur — la méthode, la classe ou le bloc describe, ou le fichier — lancé par la recette restreinte à lui, puis chargé comme n’importe quelle exécution. Aussi dans le menu contextuel de l’éditeur.
Show Tests That Ran This LineLà où le rapport dit quels tests ont exécuté quoi, liste les tests qui ont exécuté la ligne sous le curseur, les plus actifs en premier, et ouvre celui que vous choisissez là où il est écrit.
Run Tests Affected by My Changes…Lister les tests qui ont exécuté une ligne que l’arbre de travail modifie par rapport à testImpact.baseRef, ouvrir celui que vous choisissez, ou ne lancer que ceux-là quand les rapports viennent d’une exécution par test.
Show Minimal Test Set…Le plus petit nombre de tests qui exécutent encore chaque ligne que la suite exécute, puis les tests qui n’ajoutent aucune ligne à eux.
Run App with Coverage…Démarrer l’application .NET du dossier sous dotnet-coverage, et charger ce que vous avez parcouru quand elle se ferme.
Run Mutation Tests HereMuter la fonction où se trouve le curseur — ou la sélection, ou le fichier — avec Stryker.NET, StrykerJS ou PIT, et charger le rapport à côté de la couverture à l’écran.
Exclude This File from Coverage / Exclude from CoveragePlace le fichier ouvert — ou, sur une ligne de la vue Coverage, le fichier ou le /** du dossier — dans fuciniCoverage.ignore des réglages du dossier, une fois.
Exclude Selection from CoverageÉcrit l’exclusion là où est le code : [ExcludeFromCodeCoverage] au-dessus d’un membre .NET, LCOV_EXCL_LINE sur une ligne, LCOV_EXCL_START/STOP autour de plusieurs, avec le signe de commentaire propre au fichier. Aussi l’ampoule et le menu contextuel de l’éditeur.
Start Coverage Session / End Coverage SessionTant qu’une session est ouverte, chaque chargement s’ajoute au précédent en union ; une barre au-dessus de l’arbre compte les exécutions et y met fin.
Next / Previous UncoveredNaviguer entre les régions non couvertes. Alt+N / Alt+P par défaut (Ctrl+Alt+N / Ctrl+Alt+P sous macOS).
Choose Editor Gutter Mode...Rien, des barres sur les seules lignes non couvertes, des barres rouge-ambre-vert, ou une carte de chaleur des passages dans la gouttière de l’éditeur.
Cycle Editor Gutter ModeUn cran plus loin dans off, uncovered, coverage et heatmap — Alt+G, ou le bouton de mode dans la barre d’état.
Choose Coverage Source for This File...Quand plusieurs rapports chargés mesurent le fichier ouvert, choisir celui dont viennent ses chiffres, pour le fichier, son dossier ou un motif — écrit une règle coverageFile.sources.
Clear Coverage Source for This File...Retirer les règles coverageFile.sources qui s’appliquent au fichier ouvert.
Toggle Inline Hit CountsAfficher ou masquer les compteurs d’exécution ×N après chaque ligne — bascule hitCounts.inline.
Show in Test Coverage ViewPublier l’exécution active dans le panneau Test Coverage propre à VS Code (même avec testCoverage.publish désactivé) et l’ouvrir.
Suggest Path Remap RuleInférer la règle pathRemap qui ferait correspondre les fichiers sans correspondance de l’exécution active à l’espace de travail, et proposer de l’ajouter.
What Community IncludesChaque plafond et chaque fonctionnalité retenue de l'offre gratuite en une seule liste, avec la part consommée de chaque plafond.
Open HTML ReportOuvrir le rapport statique généré.
Generate Full HTML ReportGénérer le rapport multipage.
Open Annotated Source / …to the SideVue annotée de la couverture d’un fichier.
Toggle Annotated SourceBasculer entre la source et la vue annotée. Alt+A par défaut (Ctrl+Alt+A sous macOS).
Show Worst-Covered Files / Folders / FunctionsQuick Pick classé du plus faible au plus élevé.
Copy Uncovered LinesRésumé Markdown de chaque plage non couverte.
Compare Two History Runs / with Last RunDiff de régression par fichier — deux exécutions conservées par l’historique, ou l’exécution à l’écran contre celle qu’elle a remplacée.
Compare with CI BaselineL’exécution chargée contre le rapport que nomme baseline.report — celui de la branche main en CI, une URL ou un artefact téléchargé — fichier par fichier.
Show Indirect Coverage Changes…Les lignes dont la couverture a bougé sans que personne les modifie, par rapport à la référence CI ou à l’exécution précédente, par fichier.
Check Coverage ThresholdsÉvaluer les contrôles de conformité.
Export Fucini JSONExporter l’exécution courante en Fucini JSON.
Export Coverage Report...Choisissez un format — CSV, Markdown, LCOV, XML Cobertura, SARIF ou un badge SVG — et une destination.
Generate Coverage BadgeÉcrire le badge SVG de l’exécution active dans badge.outputPath, affichant badge.metric, et proposer de l’ouvrir.
Copy MCP Server ConfigurationPlacer dans le presse-papiers ce dont un client MCP a besoin pour interroger la couverture à l’écran — l’adresse du serveur et votre jeton ; quand le serveur est désactivé, proposer de l’activer.
Show Status Bar MenuOuvrir le menu d’actions rapides.
Browse for External HTML Report / Full Report Output Dir…Définir les répertoires de rapport via un sélecteur.

16. Référence des paramètres

Le tableau complet et catégorisé des paramètres — chaque option avec sa valeur par défaut — se trouve sur la page Features & Settings. Toutes les clés sont préfixées par fuciniCoverage..

À noter : fuciniCoverage.language fixe l'interface utilisateur propre à cette extension (barre d'état, notifications, infobulles, vues web) sur une langue précise, indépendamment de la langue d'affichage de VS Code — par défaut sur auto, avec des ensembles pour les 18 langues prises en charge. Cela ne change pas les entrées de la palette de commandes ni les libellés des paramètres, que VS Code résout à partir de sa propre langue d'affichage.

Dans Visual Studio. Les mêmes clés fuciniCoverage.*, lues dans jusqu'à quatre fichiers, le dernier l'emportant : les réglages utilisateur propres à VS Code si VS Code est sur la machine — lus, jamais écrits, pour que vos couleurs et seuils suivent ; %APPDATA%\Fucini\CoverageStudio\settings.json, les réglages utilisateur de cette édition ; .vscode\settings.json dans le dossier ou à côté de la solution, de sorte qu'un dépôt configuré pour VS Code l'est pour Visual Studio ; et fucini-coverage.json à la racine de la solution, pour une équipe qui préfère ne pas garder de dossier .vscode dans un dépôt .NET — l'édition VS Code le lit aussi. L'engrenage de la barre d'outils de la fenêtre Coverage ouvre une fenêtre de réglages qui écrit le fichier utilisateur ou le fichier du dossier qui existe, comme le dit son sélecteur Write changes to, et conserve les commentaires d'un fichier qu'elle modifie. fuciniCoverage.language y fonctionne de la même façon ; les menus suivent la langue propre de Visual Studio.

17. Codes d'erreur

Les diagnostics sont envoyés au canal de sortie Fucini Coverage (View → Output → Fucini Coverage), chacun avec un code FUCINI_* stable.

Dans Visual Studio. Les mêmes codes vont dans le volet Fucini Coverage de la fenêtre Output (View → Output) et sont conservés dans %LOCALAPPDATA%\Fucini\CoverageStudio\coverage-studio.log, pour la question qui arrive après la fermeture de l'IDE. Trois qui reviennent : rien n'est marqué alors que le volet dit que des fichiers ont été chargés — le mode gouttière est off, choisissez Show Coverage in Editor ; FUCINI_REMAP_001 et une barre d'information — le rapport nomme des chemins qui n'existent pas ici, et le volet propose la règle pathRemap ; la fenêtre Coverage dit avoir besoin de WebView2 — installez le Microsoft Edge WebView2 Runtime, les marques dans l'éditeur n'en ont pas besoin.

CodeSignification
FUCINI_PARSE_001Format de couverture non pris en charge ou non reconnu — aucun analyseur ne correspond au fichier.
FUCINI_PARSE_010Le fichier lcov ne contenait aucun enregistrement SF.
FUCINI_PARSE_020JSON llvm-cov invalide, data[] manquant ou aucun fichier.
FUCINI_PARSE_030Racine Cobertura <coverage> absente ou XML invalide.
FUCINI_PARSE_040Racine JaCoCo <report> absente ou aucun fichier source.
FUCINI_PARSE_050JSON Istanbul/SimpleCov invalide ou sans fichiers.
FUCINI_PARSE_060JSON SimpleCov invalide ou sans tableau files de premier niveau.
FUCINI_PARSE_070Profil Go sans en-tête mode:, ou sans bloc de couverture.
FUCINI_PARSE_080Racine Clover <coverage> ou <project> absente, ou aucun fichier dedans.
FUCINI_PARSE_090Racine OpenCover <CoverageSession> absente, ou aucun fichier dedans.
FUCINI_PARSE_100JSON coverage.py invalide ou sans objet files de premier niveau.
FUCINI_PARSE_110JSON gcov/gcovr invalide ou sans tableau files de premier niveau.
FUCINI_PARSE_120XML GNATcoverage sans élément <source>, ou un index.xml dont les xi:include n’ont jamais été résolus — chargez plutôt les fichiers *.xml par source.
FUCINI_PARSE_130Élément racine <BullseyeCoverage> absent, ou aucun élément <src> à l’intérieur.
FUCINI_PARSE_140Élément racine <CoverageDSPriv> absent, aucune table <SourceFileNames> pour résoudre les lignes, ou aucune donnée de ligne.
FUCINI_PARSE_150JSON de couverture Xcode invalide, ou tableau targets de premier niveau absent.
FUCINI_PARSE_160Élément racine <coverage> de SonarQube absent, ou aucun élément <file> à l’intérieur.
FUCINI_PARSE_170JSON Coveralls invalide, ou tableau source_files de premier niveau absent.
FUCINI_LOADUn chargement a été annulé depuis sa notification de progression ; l’exécution précédente, s’il y en a une, reste chargée.
FUCINI_REMOTE_001Une URL de coverageFile.paths n’a pas pu être récupérée, avec la raison ; la dernière copie téléchargée est chargée à la place. De simples lignes [FUCINI_REMOTE] consignent chaque téléchargement et chaque vérification sans changement (304).
FUCINI_REMOTE_002Une URL de coverageFile.paths n’a donné aucune réponse complète en 30 secondes — le plus souvent un proxy ou un VPN qui accepte la connexion puis se tait ; la dernière copie téléchargée est chargée à la place.
FUCINI_REMOTE_003Une URL de coverageFile.paths a répondu par une page HTML plutôt que par un fichier de trace — une page de connexion, très probablement. La page n’est pas mise en cache et la dernière copie téléchargée est chargée à la place ; vérifiez le jeton dans remote.headers.
FUCINI_REMAP_002Une règle pathRemap a été suggérée pour les chemins qu’un chargement a laissés sans correspondance, avec le nombre de ceux qu’elle explique — ou aucune n’a pu être inférée, ou la règle inférée figure déjà dans le réglage et ne les a pas résolus.
FUCINI_REMAP_003La règle suggérée a été ajoutée à fuciniCoverage.pathRemap par Apply Suggested Remap et la couverture est en cours de rechargement.
FUCINI_GITDIFF_001L’extension Git est indisponible ; la couverture du diff est ignorée et l’exécution complète est affichée.
FUCINI_GITDIFF_002gitDiff.baseRef commence par -, ce qu’aucune référence git ne peut faire (git le lirait comme une option) ; la couverture du diff est ignorée et l’exécution complète est affichée.
FUCINI_IGNORECombien de fichiers fuciniCoverage.ignore a laissés hors de l’exécution, et lesquels.
FUCINI_UNMEASURED_001Les fichiers du type de l’exécution qu’aucun test n’a chargés, un par ligne.
FUCINI_UNMEASURED_002Plus de 5 000 fichiers de l’espace de travail correspondaient à l’une des extensions de l’exécution ; seuls les 5 000 premiers ont été considérés pour la liste Unmeasured.
FUCINI_UNMEASURED_003En mode count, certains fichiers non mesurés sont listés mais pas comptés : le plafond de lecture (2 000 fichiers ou 50 Mo par chargement) a été atteint.
FUCINI_UNMEASURED_004Un fichier non mesuré n’a pas pu être lu ; il est listé mais pas compté.
FUCINI_TESTCOVERAGECombien de fichiers ont été publiés dans la vue Test Coverage de VS Code.
FUCINI_BADGELe badge a été écrit, avec son chemin, son libellé et sa valeur.
FUCINI_BADGE_001Le badge n’a pas pu être écrit, avec la raison.
FUCINI_WORKSPACEUn dossier a été ajouté à l’espace de travail ou retiré de celui-ci ; la couverture est détectée à nouveau.
FUCINI_VARIABLESCe qu’a répondu chaque ${command:…} des réglages de chemin, ou pourquoi il est resté tel qu’écrit : la commande a échoué, n’a rien renvoyé d’utilisable, ou l’espace de travail n’est pas approuvé.
FUCINI_WATCHCe que fait l’observateur : les chemins surveillés, un fichier configuré qui est apparu, une tâche nommée dans watch.reloadAfterTasks qui s’est terminée (avec son code de sortie) et a déclenché un rechargement, ou un chemin sous files.watcherExclude qui est interrogé à la place.

18. Confidentialité

La télémétrie est contrôlée par le paramètre telemetry.enabled de portée window. Elle est désactivée par défaut. Le récapitulatif quotidien et l'avis de suppression exigent en outre que le telemetry.telemetryLevel global de VS Code autorise la télémétrie ; le ping d'installation et quelques petits événements sont envoyés dans tous les cas, tout comme l'entrée dans le registre d'utilisation d'une installation en période d'essai ou sur le niveau gratuit Community. Sur Community, Unlock Full Features échange cette télémétrie contre toutes les fonctionnalités Pro, MC/DC comprise, pendant 30 jours, une fois par machine — désactivez-la et l'ensemble Community standard s'applique ; une licence payante n'est concernée ni dans un cas ni dans l'autre. Consultez la politique de confidentialité pour savoir ce qui est envoyé.

Deux choses méritent d'être connues, parce que vous pouvez agir dessus. La première est votre ID du registre d'utilisation : en période d'essai et sur Community, l'extension l'affiche sous Show License / Activation et au bas de What Community Includes, où sélectionner la ligne la copie et ouvre la politique de confidentialité. Le registre ne connaît votre machine que par une empreinte, et par rien d'autre : cet ID est donc le seul moyen de demander ce qu'il contient vous concernant, de le faire supprimer ou de vous y opposer — citez-le et nous retrouverons votre ligne ; sans lui, nous ne le pouvons pas. La seconde est l'enregistrement d'installation : une ligne écrite la première fois qu'une installation se signale, puis conservée au lieu d'être supprimée au bout de 90 jours, contenant l'identifiant d'installation, le jour, le lieu auquel son adresse a été rattachée, les versions et le système d'exploitation — pas l'adresse elle-même, et rien sur votre code. C'est ce qui nous permet de dire combien d'installations il y a eu au fil des ans. Les deux sont décrits en détail dans la politique de confidentialité, et les deux sont supprimés si vous le demandez.

The bottom of What Community Includes: the ways to lift the caps, and How these are counted — the row that copies your usage ledger ID and opens the privacy policy
La fin de What Community Includes : comment les plafonds sont comptés, et la ligne qui vous donne votre ID de registre d'utilisation.

19. Évaluation et activation

Fucini Coverage Studio est distribué comme préversion d'évaluation. Au premier lancement, il vous est demandé d'accepter de l'évaluer, et l'essai commence — toutes les fonctionnalités sont disponibles pendant un essai de 14 jours, décompté à partir de la première utilisation sur cette installation. Aucune date fixe après laquelle quoi que ce soit s'arrête.

À partir de la version 2.2026.2, l’essai d’une nouvelle installation commence dès que l’extension a joint une fois le serveur de licences ; d’ici là, elle fonctionne au niveau Community et le signale. Dans un conteneur de développement ou un Codespace, aucun essai ne commence — un code d’abonnement, une clé ou le pass de 7 jours y débloque l’ensemble complet.

À la fin de l'essai, rien n'est verrouillé : l'extension revient au niveau gratuit Community. Pour retrouver l'ensemble complet, activez — l'activation se connecte au serveur de licences et applique automatiquement la clé renvoyée, sans e-mail et sans clé à recopier à la main :

Show License / Activation: the trial state, and the buttons to enter a subscription code, see the plans or request a licenceScreenshot pending — add assets/img/licence-dialog.png (see SCREENSHOTS.md).
  1. Exécutez Fucini Coverage: Show License / Activation (également accessible depuis la barre d'état une fois l'essai ou la clé expiré) et cliquez sur Request License… (ou Request Renewed Key… si vous avez déjà activé).
  2. Confirmez la demande. La clé est émise automatiquement, et vos coordonnées issues d'une demande antérieure sont réutilisées plutôt que redemandées.
  3. C'est tout. La clé d'activation est générée et écrite automatiquement dans fuciniCoverage.license.key. La barre d'état passe de l'essai à une licence activée en un instant.

La voie manuelle en une image : ouvrez le panneau de licence, choisissez Enter Key, collez la clé reçue par e-mail, et la bannière bascule sur « Activated ».

Activating by hand: the licence panel, the activation dialog, Enter Key, the pasted key, and the banner turning to ActivatedScreenshot pending — add assets/img/activate-key.gif (see SCREENSHOTS.md).

Si la demande automatisée venait à échouer (pas de connexion, problème de serveur) : exécutez Fucini Coverage: Copy Activation Request Code, envoyez le code via la page de contact ou à info@fucini.consulting, puis collez la clé FCK1.… que vous recevrez en retour avec Fucini Coverage: Enter Activation Key (ou directement dans settings.json) :

{ "fuciniCoverage.license.key": "FCK1.…collez ici la clé entière…" }

Le nom du paramètre est fuciniCoverage.license.key (portée user/global). La clé est liée à votre machine et à votre utilisateur du système d'exploitation, peut comporter une date d'expiration, et peut activer ou limiter des fonctionnalités individuelles ainsi que plafonner le nombre de chargements de couverture par jour. Si le message « invalid for this machine » s'affiche, demandez une nouvelle clé depuis cette installation — une clé émise pour une autre machine ne sera jamais valide ici.

Dans Visual Studio. Il n’y a pas d’offre gratuite dans cette édition : sans abonnement, rien n’est lu. Avec un abonnement, l’offre y décide de ce dont elle décide dans VS Code — une fonctionnalité que l’offre n’inclut pas est retenue, et sa commande le dit au lieu de s’exécuter. La version la plus ancienne que le serveur de licences prend encore en charge s’y applique aussi : une build antérieure en est avertie une fois par jour, avec la date à laquelle elle cesse de fonctionner, et continue de fonctionner jusque-là. Être hors ligne n’arrête jamais une build.

L'offre gratuite Community : un quota hebdomadaire

Community ne cesse jamais d'afficher la couverture. Les gouttières, la règle d'aperçu, les survols, CodeLens, la vue Coverage, le mode watch, la couverture de diff et l'historique ne sont pas comptés du tout, et le chargement d'un tracefile par commande est seulement plafonné à 25 par jour. Ce qui est mesuré, c'est la sortie : cinq par semaine pour chacune de ces actions — ouvrir le rapport HTML, exporter, comparer deux exécutions, vérifier les seuils et afficher le source annoté en place.

La semaine est la vôtre, pas celle du calendrier : elle commence à la première utilisation et se termine sept jours plus tard. Lorsqu'un quota est épuisé, le message nomme l'action et le jour où il revient, et après ce seul message, seule la barre d'état le mentionne. Fucini Coverage: What Community Includes liste chaque quota, avec ce qui est utilisé et la date de réinitialisation, avant même que vous n'en atteigniez un.

The weekly allowance: five uses of Open HTML Report across three days, a sixth refused with the day the count resets, and the week ending seven days after the first use; gutters, hovers, CodeLens and the Coverage view are never countedScreenshot pending — add assets/img/weekly-allowance.png (see SCREENSHOTS.md).
The message at a Community limit: Checking coverage thresholds, all 5 used, the day it resets, and the buttons Subscribe, 7-Day Pass and What Community IncludesScreenshot pending — add assets/img/community-limit-prompt.png (see SCREENSHOTS.md).
What Community Includes: each allowance with how much is used and the day it resets, then the features that are not includedScreenshot pending — add assets/img/community-includes-weekly.png (see SCREENSHOTS.md).

Trois détails relèvent des offres payantes tandis que leurs constats restent gratuits : Community marque chaque ligne comportant des mutants survivants et indique combien, mais pas ce que chaque mutant a modifié ; il indique combien de tests ont exécuté une ligne, mais pas leurs noms ; et il affiche le Max CRAP d'une exécution, mais pas la liste classée Riskiest Methods.

A mutant hover in Community: 2 mutants survived and 2 more detected on the line; what each mutant changed is part of the paid plansScreenshot pending — add assets/img/mutant-hover-community.png (see SCREENSHOTS.md).

Si vous utilisiez déjà Community à l'arrivée du quota hebdomadaire (0.2026.83), vos plafonds précédents restent en vigueur pendant 30 jours ; vous en êtes informé une seule fois, avec la date. Les compteurs sont conservés sur votre machine — dans le stockage propre à VS Code et dans ~/.fucini-coverage/, de sorte qu'un nouveau profil VS Code poursuit la même semaine — et ne sont jamais envoyés nulle part.

Le pass 7 jours

Pas prêt pour un abonnement ? Un pass 7 jours, c'est tout Pro pendant une semaine, payé une seule fois : rien ne se renouvelle et il n'y a rien à résilier. Achetez-le sur la page des tarifs (le message affiché à une limite Community comporte un bouton pour cela), et le code d'activation arrive par e-mail.

The 7-day pass on the pricing page: everything in Pro for one week, paid once, with the Get a 7-day pass buttonScreenshot pending — add assets/img/pricing-week-pass.png (see SCREENSHOTS.md).
  1. Exécutez Fucini Coverage: Enter Subscription Code — la commande existe aussi bien dans l'édition Community que dans Pro.
  2. Choisissez Pro et collez le code FCB1-… reçu par e-mail.
  3. C'est tout. La clé est émise et appliquée pour vous, et fonctionne hors ligne. La semaine court à partir du paiement : activez donc dès l'achat. Une fois la semaine écoulée, l'extension revient d'elle-même à Community et continue d'afficher la couverture.
Enter Subscription Code, step 1: choose Pro from the list of plansScreenshot pending — add assets/img/pass-step-plan.png (see SCREENSHOTS.md).
Enter Subscription Code, step 2: paste the FCB1 code from the purchase email and press EnterScreenshot pending — add assets/img/pass-step-code.png (see SCREENSHOTS.md).

Dans Visual Studio. Le même code active Fucini Coverage Studio pour Visual Studio, 2022 et 2026 : ouvrez Tools → Coverage Studio → Licence…, collez le code, choisissez le forfait auquel il correspond et appuyez sur Activate. La fenêtre Coverage affiche alors Activated au-dessus de l’arborescence ; dépliée avec sa flèche, la ligne montre la date jusqu’à laquelle la clé est valide et un bouton vers votre compte. Une machine est un siège : activez VS Code ou Visual Studio, et l’autre éditeur sur la même machine suit de lui-même — Visual Studio lit la clé de VS Code et VS Code celle de Visual Studio — si bien que rien n’est saisi deux fois et qu’aucun second siège n’est pris. Les deux maintiennent une clé de la même façon : Pro Plus, Business et Enterprise se signalent deux fois par jour, et une clé Pro est renouvelée dans la semaine qui précède son expiration.

Visual Studio: the Coverage window says no subscription covers this machine, and the Licence dialog takes the subscription code
Visual Studio: the Coverage window after an activation — Activated, valid until a date, and a button to the account

Passer à un nouvel ordinateur et gérer les postes

Une clé est liée à une machine : un nouvel ordinateur en demande donc une nouvelle, et votre abonnement ne paie pas plus de machines quʼil nʼen annonce. Libérez lʼancienne vous-même : connectez-vous à la gestion de votre abonnement, repérez le poste que vous nʼutilisez plus, choisissez Free up, puis activez la nouvelle machine avec le même code. Lʼachat de Pro ne vous envoie pas de mot de passe — votre compte existe, il nʼen a simplement pas encore. La première fois, utilisez donc définir ou réinitialiser votre mot de passe avec lʼadresse de votre abonnement.

Sur Business et Enterprise, invitez chaque collègue par e-mail depuis cette même page. Chacun reçoit un code dʼactivation qui nʼappartient quʼà lui, et dès quʼil sʼen sert son adresse apparaît en face de son poste — lorsque quelquʼun part, vous voyez quel poste était le sien et vous le libérez pour le suivant. Une invitation occupe un poste dès son envoi et expire au bout de 14 jours si elle nʼest pas utilisée ; retirez-la pour récupérer la place immédiatement.

Tester les préversions

Les nouveautés arrivent sur fucini.software avant d'arriver sur la Marketplace, et vous pouvez demander à ce qu'elles vous soient proposées. Ouvrez la vue Coverage, dépliez le panneau de licence et appuyez sur Tester les préversions… — ou activez fuciniCoverage.update.preRelease. À partir de là, l'extension consulte ici un flux de préversions distinct en plus du flux habituel, et propose la plus récente des deux.

The licence panel in the Coverage view, expanded: a Pro licence valid until 2027-03-19, and the button labelled Test pre-release buildsScreenshot pending — add assets/img/licence-prerelease.png (see SCREENSHOTS.md).

Les préversions sont testées, mais ce sont les builds dont nous sommes le moins sûrs — vous vous porteriez volontaire pour trouver ce qui nous a échappé. En rejoignant le canal, vous nous indiquez que cette installation en fait partie, ce qui nous permet de savoir combien de personnes testent et de dire ce qui a changé ; en le quittant, la prochaine version stable vous remet sur le chemin habituel. Il n'y a pas toujours une préversion disponible, et rejoindre le canal quand il n'y en a pas ne coûte rien : l'extension trouve un flux vide, n'en dit rien et continue de proposer les versions stables jusqu'à ce qu'une préversion soit publiée.

The same panel once the install has joined: an update bar offering 0.2026.84 while 0.2026.83 is running, the button now reading Leave the pre-release channel, and a line saying the install is on the channelScreenshot pending — add assets/img/licence-prerelease-joined.png (see SCREENSHOTS.md).

20. Contact et licence

Questions, rapports de bogues ou conditions de licence alternatives — consultez la page de contact ou écrivez à info@fucini.consulting. Sous licence MIT avec une condition d'attribution dans les notes de version ; voir aussi le Notice.

21. En ligne de commande

Le lecteur tourne aussi sans éditeur : npm install -g fucini-coverage, gratuit, sur Windows, Linux, WSL et macOS. fucini-coverage check coverage/lcov.info --lines 80 est le contrôle sur lequel un pipeline échoue ; summary, export, report, badge et compare font ce que font les commandes de ces noms dans les éditeurs, et mcp sert les six outils de la section ci-dessus à un agent, sur un serveur. Il lit fucini-coverage.json, le fichier de réglages que lit l'édition Visual Studio, si bien que les seuils ne sont fixés qu'une fois. fucini-coverage help <command> explique chacune ; la page complète est fucini-coverage sur npm.

The command line on the demo: --help, summary, check with two gates passing, export as Markdown, compare against a baseline, badge, report and the MCP server's helpScreenshot pending — add assets/img/cli-demo.gif (see SCREENSHOTS.md).