GUIDA COMPLETA

Guida utente

Dal primo file di traccia al gating di conformità agli standard di sicurezza — tutto ciò che Fucini Coverage Studio può fare, e come farlo esattamente.

Scarica il VSIX

1. Introduzione

Fucini Coverage Studio trasforma i file di traccia della coverage che la vostra build già produce in coverage di prima classe nell'editor — in VS Code e in Visual Studio. Legge venticinque formati, li normalizza in un unico modello canonico Fucini, unisce più esecuzioni in modo deterministico e mostra il risultato nell'editor stesso — margini, CodeLens, hover e una vista Covered Files — così non c'è un visualizzatore separato per cui lasciare l'editor. Le due edizioni condividono un lettore: lo stesso report dà gli stessi numeri, alla cifra, in entrambe. Questa guida è scritta da VS Code; dove Visual Studio differisce, un riquadro In Visual Studio dice come.

È costruito pensando ai flussi di lavoro di sicurezza funzionale: coverage MC/DC, coverage di regioni e istanziazioni C++, un punteggio composito ponderato per la sicurezza e un verdetto configurabile COMPLIANT / NON-COMPLIANT allineato al pensiero IEC 61508, ISO 26262 e 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. Installazione e requisiti

  • VS Code ≥ 1.88 — la versione minima supportata da questa estensione — oppure Visual Studio 2022 o 2026, Community, Professional o Enterprise (vedi il riquadro qui sotto).
  • Un file di traccia della coverage che il vostro progetto già produce (vedi §4).

Installa dal Marketplace, oppure da un file .vsix tramite Extensions → ⋯ → Install from VSIX…. L'estensione si attiva all'avvio e aggiunge un'icona Coverage alla activity bar.

In Visual Studio. Lo stesso prodotto viene distribuito come una seconda estensione, Fucini Coverage Studio per Visual Studio, per Visual Studio 2022 e 2026 — Community, Professional ed Enterprise. Non usa la code coverage propria di Visual Studio: in Visual Studio 2022 è una funzione Enterprise, quindi su Community e Professional questa è l'unica coverage che l'IDE mostrerà. Installate il .vsix aprendolo — il VSIX Installer chiede quale Visual Studio — oppure tramite Extensions → Manage Extensions; l'estensione si carica all'apertura di una soluzione o di una cartella. La finestra Coverage richiede il Microsoft Edge WebView2 Runtime, che Windows 11 e Visual Studio 2026 già includono; i segni nell'editor funzionano anche senza.

3. Avvio rapido

Vuoi vedere come funziona prima di collegare il tuo progetto? Scarica il progetto demo (~6 KB — un piccolo progetto C con un lcov.info già pronto):

  1. Estrailo ovunque, quindi apri coverage-studio-demo.code-workspace in VS Code (File → Open Workspace from File…).
  2. Installa Fucini Coverage Studio se non l'hai già fatto (vedi §2 sopra).
  3. Il file .vscode/settings.json del workspace punta già al coverage/lcov.info incluso, quindi i gutter e la vista Covered Files compaiono non appena l'estensione si attiva — nessun passaggio Load Coverage necessario.
  4. Vuoi rigenerare tu stesso il tracefile (ad es. con un compilatore diverso)? Esegui scripts/gen-coverage.sh (o .ps1 su Windows) — consulta il README.md del workspace per i compilatori disponibili.

In Visual Studio. Aprite una soluzione, o una cartella (File → Open → Folder, che è come si apre un progetto CMake) — la demo qui sopra si apre come cartella, e il suo .vscode/settings.json viene letto anche lì. Un report nel posto che le impostazioni indicano viene caricato da solo e il riquadro Fucini Coverage della finestra Output dice quali file; altrimenti Tools → Coverage Studio → Load Coverage File…, una volta — viene ricordato. Aprite un file sorgente e scegliete Show Coverage in Editor: rosso è una riga mai eseguita, ambra una decisione presa in un solo verso, e Ctrl+Shift+U, N va alla prossima riga non coperta. View → Other Windows → Coverage è l'albero con i numeri di ogni file e un punteggio su tutti, che la barra di stato mostra per l'esecuzione e per il file in cui siete. Tools → Coverage Studio → Getting Started apre questi passi come una pagina con un pulsante per ciascuno; la prima volta si apre da sola.

  1. Genera un file di traccia di coverage con il tuo normale flusso di test.
  2. Command Palette (Ctrl+Shift+P) → Fucini Coverage: Load Coverage. Con watch.enabled attivo (predefinito), un file corrispondente si carica automaticamente.
  3. Apri un file sorgente coperto: la barra di stato mostra la sua percentuale, la vista Coverage si popola, passando il mouse su una riga si vede il suo conteggio dei colpi, e l'esecuzione compare nel pannello nativo Test Coverage. Barre sulle righe non coperte, una mappa di calore dei conteggi e conteggi ×N in linea sono a un'impostazione di distanza (editorGutter.mode, hitCounts.inline).
Covered (green) and uncovered (red) gutters in the editorScreenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).

4. Produzione di file di traccia

Uno qualsiasi dei seguenti viene rilevato automaticamente al caricamento:

Ricette complete da copiare e incollare per ogni compilatore — tra cui Swift, Rust, Go, Python, .NET, PHP e altri — nella pagina Ricette di copertura: 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

llvm-cov JSON è l'input più ricco — porta con sé regioni, MC/DC e istanziazioni di template C++ oltre a righe, rami e funzioni.

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
FormatoFile tipicoMetriche aggiuntive
LCOVlcov.inforighe, rami, funzioni
llvm-cov JSONcoverage.json+ regioni, MC/DC, istanziazioni
Cobertura XMLcoverage.xmlrighe, rami
JaCoCo XMLjacoco.xmlrighe, rami, funzioni
Istanbul / nyccoverage-final.jsonistruzioni, rami, funzioni
SimpleCov.resultset.jsonrighe
Clover XMLclover.xmlrighe, rami, funzioni
OpenCover XMLcoverage.opencover.xmlrighe, rami, funzioni
coverage.py JSONcoverage.jsonrighe, rami
gcov / gcovr JSONcoverage.jsonrighe, rami, funzioni
Go coverage profilecoverage.outrighe
SonarQube genericcoverage.xmlrighe, rami
GNATcoverage XML (Ada)*.xmlrighe, rami, MC/DC
BullseyeCoverage XMLcoverage.xmlrighe, condizione/decisione
Visual Studio*.coveragexmlrighe, rami
Coveralls JSONcoveralls.jsonrighe, rami
Xcode xccov JSONcoverage.jsonfunzioni e totali per file — nessun dato per riga
gcov plain text*.gcovrighe, rami, chiamate di funzione
VectorCASTcoverage.xmlrighe, rami, coppie MC/DC, funzioni, chiamate di funzione
Testwell CTC++*.txtrighe, condizione/decisione
Lauterbach TRACE32*.xmlistruzioni, decisioni, condizioni, MC/DC, funzioni, chiamate, codice oggetto
EMMA XML (Java)coverage.xmlrighe
UCIS / Aldec UCDB*.xmlistruzioni, rami di decisione
NCover XMLCoverage.xmlrighe, funzioni
dotCover DetailedXMLdotCover.xmlrighe, funzioni
PIT (mutation)mutations.xmlpunteggio di mutazione — nessuna coverage
Stryker (mutation)mutation-report.jsonpunteggio di mutazione — nessuna coverage

Un progetto C++ nativo, misurato da Visual Studio

In Visual Studio. La coverage di un progetto C++ propria di Visual Studio era solo Enterprise, e il plugin gratuito OpenCppCoverage che colmava la lacuna è stato ritirato. Tools → Coverage Studio → Run Native Project with Coverage prende il progetto di avvio — un .vcxproj — chiede a MSBuild dove compila e con quale toolset, e lo misura in uno di due modi. Con il toolset ClangCL, se sulla macchina ci sono llvm-profdata e llvm-cov di LLVM (li porta il componente C++ Clang tools for Windows di Visual Studio), compila di nuovo il progetto in coverage\native\ con -fprofile-instr-generate -fcoverage-mapping, tramite un file props che MSBuild viene istruito a importare per primo — nulla nel progetto cambia — esegue il programma con LLVM_PROFILE_FILE impostato, unisce il profilo ed esporta coverage\native\lcov.info, esatto alla regione. Con qualunque altro toolset, se è installato OpenCppCoverage, compila il progetto com'è — una build Debug ha i PDB — e lo esegue sotto OpenCppCoverage, che scrive coverage\native\opencppcoverage.xml. Ogni comando va nel riquadro Fucini Coverage, e il report viene caricato e ricordato come quello di un'esecuzione dei test. A un progetto che non si può misurare viene detto perché e cosa installare. MSBuild 17.8 (Visual Studio 2022 17.8) o successivo, per la domanda che gli pone.

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).
In Visual Studio: Run Native Project with Coverage su un progetto C++ — la compilazione, l'esecuzione e l'editor che si riempie.

5. Caricamento e rilevamento

Per impostazione predefinita l'estensione esegue la scansione dalla radice dello spazio di lavoro. Precisa questo con due impostazioni:

{
  "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"
  ]
}
  • Ogni voce di paths è relativa a defaultLocation (o alla radice dello spazio di lavoro se non impostata).
  • Una voce contenente * viene cercata ricorsivamente; un nome file semplice corrisponde solo direttamente nella cartella base.
  • Quando paths è vuoto, l'estensione cerca coverage.json, poi lcov.info, caricando quello trovato per primo.
  • Pick Coverage File usa i file selezionati al posto di questi percorsi — ogni selezione si aggiunge all’insieme e tutti vengono uniti — finché non li si scarica o non si modificano queste impostazioni.
  • Variabili — ogni impostazione di percorso espande ${workspaceFolder}, ${workspaceFolderBasename}, ${userHome}, ${env:NAME}, ${command:id} e ${config:section.key}. Una variabile che l'estensione non conosce viene lasciata com'è scritta, così un errore di battitura compare nel log di rilevamento come il percorso cercato anziché sparire. ${command:id} esegue prima quel comando — solo in un’area di lavoro attendibile e per al massimo cinque secondi — così ${command:cmake.buildDirectory} segue il kit CMake selezionato.
  • Voci URL — una voce http(s):// viene scaricata nell'archivio dell'estensione a ogni caricamento e caricata da lì; la vista Coverage nomina l'URL. Ogni scaricamento è condizionale (ETag / Last-Modified), così un artefatto invariato non trasferisce nulla, e quando uno scaricamento fallisce viene caricata l'ultima copia scaricata, con il motivo nell'output. remote.headers aggiunge intestazioni Name: value con le variabili espanse, remote.refreshMinutes riscarica a intervalli, e un frammento #lcov.info indica il formato quando l'URL stesso non termina con un nome di file.
  • Glob di esclusione — fuciniCoverage.ignore esclude file interi (vendorizzati, generati, di terze parti) dall'esecuzione mentre si carica, così ogni vista, gate ed esportazione conta senza di essi; il risultato del caricamento dice quanti sono stati lasciati fuori e l'output li nomina. I pattern corrispondono al percorso relativo allo spazio di lavoro e a quello assoluto, e un pattern senza / corrisponde a un nome di cartella o di file a qualsiasi profondità, come .gitignore.
  • Spazi di lavoro multi-root — ogni cartella viene rilevata per conto proprio: defaultLocation, paths, pathRemap, ignore, watch.* e remote.* vengono letti per cartella, così vale il .vscode/settings.json della cartella stessa o la sua voce nel .code-workspace, e ${workspaceFolder} in una voce indica la cartella della voce stessa. I tracefile di ogni cartella si uniscono in un'unica esecuzione, la vista Coverage raggruppa i file per cartella, e una cartella aggiunta allo spazio di lavoro o rimossa da esso ricarica la copertura da sola.
  • Ricaricamento dopo un'attività — watch.reloadAfterTasks nomina attività (una label di tasks.json, o source: name come le mostra l'elenco Run Task) la cui fine ricarica la copertura, che watch.enabled sia attivo o no — per le build che l'osservatore non può seguire. Anche una voce assoluta di paths fuori dallo spazio di lavoro viene sondata, così un file che compare lì viene caricato.
  • Avanzamento annullabile — un caricamento di dieci o più tracefile, o di 8 MB o più, gira sotto una notifica di avanzamento con un pulsante Annulla che nomina il file in lettura e la fase; uno più piccolo fa solo girare la barra di stato. Annullare lascia caricata l'esecuzione precedente e lo dice.

Dalla 1.2026.6 anche una voce assoluta può contenere una wildcard: ${workspaceFolder}/build/coverage-merged/*.lcov.info carica ogni file del genere in quella cartella, e ** sta per qualsiasi profondità. Le cartelle prima della prima wildcard sono dove cerca, e vengono osservate, così un report che una build scrive lì si carica da solo. L’edizione per Visual Studio legge una voce così allo stesso modo, e dalla 1.2026.5 anche lì una wildcard relativa viene cercata a qualsiasi profondità, come è sempre stato qui.

Se paths non è configurato, viene caricato il primo dei nomi di report più diffusi trovato sotto la cartella di base. Prima i quattro che l'estensione ha sempre cercato — coverage.json, lcov.info, coverage.out, clover.xml — poi, dalla versione 0.2026.83, jacoco.xml, coverage.xml, cobertura.xml, coverage.cobertura.xml, coverage.opencover.xml e coverage-final.json, e infine i percorsi in cui scrivono le configurazioni predefinite: coverage/ (nyc, Jest, vitest, PHPUnit, SimpleCov), target/site/jacoco/jacoco.xml (Maven), build/reports/jacoco/test/jacocoTestReport.xml (Gradle) e TestResults/*/coverage.cobertura.xml (dotnet test). Così un progetto Java o .NET mostra la propria copertura alla prima apertura, come ha sempre fatto un progetto lcov.

Dalla 1.2026.3 una soluzione .NET ha bisogno di ancora meno: la cartella TestResults/<run>/ di ogni progetto di test è tra i percorsi noti, non solo quella della cartella dello spazio di lavoro, e il <user>_<machine>_<date>.cobertura.xml del collector di Microsoft viene trovato accanto al coverage.cobertura.xml di Coverlet — così una soluzione i cui test sono stati eseguiti nel Test Explorer di Visual Studio mostra la sua coverage alla prima apertura, ogni cartella di esecuzione viene caricata, e l'unione conserva per ogni file quanto dice l'esecuzione più recente. E fuciniCoverage.ignore.generated, attivo per impostazione predefinita, lascia i file del designer e quelli generati — *.Designer.cs, *.g.cs, *.generated.cs, *.razor.g.cs, AssemblyInfo, gli using globali, Migrations/ e obj/ — fuori da ogni totale, pagina ed esportazione prima che venga applicato ignore, così una tabella generata che nessuno testa non costa alla soluzione il suo gate.

In Visual Studio: coverage dopo ogni esecuzione dei test. Eseguite i test come sempre. Tools → Coverage Studio → Collect Coverage in Test Explorer… mette un .runsettings con il collector Cobertura di Microsoft accanto alla soluzione. Visual Studio lo raccoglie quando Tools → Options → Test → Auto detect runsettings files è attivo; altrimenti selezionatelo una volta sotto Test → Configure Run Settings. Da quel momento ogni esecuzione scrive un report sotto il progetto di test, e la sorveglianza sulla soluzione lo carica nell'istante in cui compare, unito a tutto ciò che le impostazioni nominano — da Test Explorer, da un terminale o da uno script indifferentemente. Nulla si aggancia a Test Explorer, così Visual Studio 2026 e Microsoft.Testing.Platform funzionano così come sono. Run Tests with Coverage è il comando di VS Code: riconosce dotnet test, vitest, jest, pytest, go, cargo, maven, gradle, phpunit e ctest, esegue i test con la coverage attiva nella finestra Output e carica ciò che hanno scritto; un progetto di test senza coverlet.collector viene eseguito con il collector fornito dall'SDK di test, e testRun.skipWhenTestsFail mantiene sullo schermo l'ultima coverage buona quando un'esecuzione finisce in rosso.

Un artefatto CI dietro un token, ricontrollato ogni quarto d'ora — il token resta nell'ambiente, mai in 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 ricaricamento è silenzioso di proposito: una finestra di dialogo dopo ogni build è una domanda con una sola risposta. Non è silenziosa l’icona Coverage: finché la vista non è davanti a te, porta il numero di tracefile riletti e il suo suggerimento li nomina. Apri la vista e il conteggio sparisce.

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).

File che non devono contare mai, qualunque cosa ne dica il tracefile:

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

Un ricaricamento alla fine dell'attività di test, per una build che l'osservatore dei file non può seguire — un'esecuzione che sostituisce un albero di output con link simbolici, un report su una condivisione di rete, un passo di copertura che post-elabora il proprio file:

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

6. Unione delle esecuzioni

Ogni voce paths esistente viene caricata e fusa in un’unica esecuzione. La fusione è deterministica — il risultato non dipende dall’ordine di caricamento — e un file misurato da più di un tracefile prende i suoi numeri da quello con la mtime più recente su disco: la riesecuzione di un modulo sostituisce ciò che un’esecuzione più ampia e più vecchia diceva di esso, invece di aggiungersi. La vista Copertura mostra cosa ha fatto: ogni riga di file nomina il tracefile da cui vengono i suoi numeri, il badge ha un contorno dove quei numeri hanno prevalso su un report più vecchio, ogni riga di tracefile sopra l’albero conta quanti dei suoi file sono stati sostituiti o ne hanno sostituiti altri, e un clic su una riga di tracefile evidenzia i suoi file nell’albero finché non viene cliccata di nuovo (coverageView.mergedMarks disattiva contorno ed evidenziazione).

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).

Un'esecuzione unita può contenere più delle sei metriche classiche, ciascuna proveniente dal report che la misura: chiamate di funzione, codice oggetto e un punteggio di mutazione accanto a righe, funzioni, regioni, rami, MC/DC e istanziazioni. La vista Coverage mostra una colonna per ogni metrica contenuta nell'esecuzione — e nessuna per quelle che non contiene — ordinate per il peso che ogni metrica ha nel punteggio, dalla più pesante, a qualsiasi larghezza: ciò che non entra scorre lateralmente invece di sparire. Trascinando la vista nel pannello inferiore diventa una tabella. Le schede della barra di stato, il report HTML e le esportazioni CSV e Markdown seguono la stessa regola: ciò che un report contiene viene mostrato, ciò che non contiene viene omesso anziché essere stampato come uno zero.

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).
In Visual Studio: la finestra Coverage su una cartella di undici progetti — compressa a una riga per progetto con la sua barra, poi espansa, poi un file aperto da lì.

Da quale report viene un file

Quando più report caricati misurano lo stesso file, il più recente se lo aggiudica per intero — giusto quando la nuova esecuzione di un modulo sostituisce quanto diceva un'esecuzione più vecchia e più ampia. È sbagliato quando i report misurano lo stesso codice di proposito: allora l'editor salta dall'uno all'altro a ogni build, e ciascuno racconta solo una parte della storia. coverageFile.sources dice cosa fare invece, file per file. Tre situazioni lo richiedono:

  • Un report è il migliore. Il coverage.json di llvm-cov contiene MC/DC, un gcov.info di GCC della stessa build solo righe e rami: scegli coverage.json, e tieni l'altro per i pochi file che solo GCC compila.
  • Più suite di test di una stessa build. Test unitari, test di integrazione e hardware-in-the-loop scrivono ciascuno un report; ognuno da solo tralascia righe che gli altri hanno eseguito. Combina, union: una riga è coperta dove l'ha eseguita un qualsiasi report, e i conteggi si sommano.
  • Un solo codice, due compilatori. Gli stessi sorgenti compilati da clang e da GCC seguono percorsi diversi nel codice specifico di ciascuna toolchain — un intrinsic qui, un fallback portabile là — e ogni report dice che l'altra metà non è mai stata eseguita. Combina, agree: una riga è coperta solo dove l'ha eseguita ogni report che la misura, e le righe su cui non concordano sono segnate in verde acqua. È la domanda che pone un controllo incrociato tra compilatori: cosa ha davvero esercitato ogni build che rilascio?

Raramente scrivi le regole a mano. Fai clic con il tasto destro su un file nella vista Copertura e scegli Choose Coverage Source... (oppure esegui Choose Coverage Source for This File... sul file aperto): l'elenco mostra ogni report che misura il file, ciascuno con le proprie righe, i propri rami e MC/DC, poi Combine them — agree e Combine them — union; scegline uno e indica se vale per il file, la sua cartella o un pattern. Clear Coverage Source for This File... toglie di nuovo la regola. Nelle impostazioni ogni regola è un glob sui file, un glob sul report (un pattern senza / corrisponde al nome file del report, {a,b} ne indica più d'uno) e, per combinare, "combine": "agree" o "union". Decide la prima regola i cui file corrispondono e il cui report misura il file; un file misurato da un solo report non gli viene mai tolto. Rami, MC/DC e regioni di un file combinato vengono dal report che ne è più ricco. coverageFile.mergeStrategy: "order" decide i file per cui nessuna regola si esprime in base all'ordine di coverageFile.paths anziché agli orari.

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

Cosa vedi: la riga del file nella vista Copertura indica il report da cui vengono i suoi numeri oppure, se combinato, ogni report e la modalità, con ≠ n per le righe contese. Il gutter e l'Annotated Source segnano quelle righe in verde acqua e dicono quale report le ha eseguite e quante volte. La scheda che compare al passaggio del mouse sulla barra di stato indica l'origine del file aperto e, per l'intera esecuzione, le regole in vigore e come sono stati decisi gli altri file. Il samples/c-cross-check della demo è il caso dei due compilatori, pronto da aprire. Anche Visual Studio fa tutto questo: Choose Coverage Source... su una riga della vista Copertura, e Choose e Clear Coverage Source for This File... in Tools > Coverage Studio.

Scegliere e combinare le origini fa parte dei piani a pagamento. Su Community il report più recente vince ogni file, come senza alcuna regola, e una regola nelle impostazioni viene segnalata come inutilizzata anziché ignorata in silenzio.

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
In VS Code: Choose Coverage Source... su bits.c dalla vista Copertura — il report di clang, quello di GCC o entrambi combinati.
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
In VS Code: da agree a union in due clic — le righe contese restano in verde acqua, i numeri cambiano.
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
In Visual Studio: lo stesso dal menu di una riga della vista Copertura — i report, poi fin dove arriva la regola, poi il file ricaricato.
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
In VS Code: bits.c, clang e GCC combinati con agree — la riga indica ≠ 4, e le quattro righe eseguite da una sola build sono in verde acqua.
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
Lo stesso file combinato con union: ogni riga eseguita da una qualsiasi delle due build è coperta, quindi bits.c raggiunge il 100% delle sue righe — e le righe su cui le build non concordano restano in verde acqua.
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 indica la combinazione sotto il titolo e, per ogni riga in verde acqua, quante volte l'ha eseguita ciascun report.
The status bar's hover card for bits.c, ending with the coverage source: both reports, combined by agree, disagreeing on four lines
La scheda del file nella barra di stato dice da dove vengono i suoi numeri; quella dell'esecuzione conta i file decisi da ciascuna regola.
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
In Visual Studio: Choose Coverage Source... da una riga della vista Copertura — gli stessi report e gli stessi due modi di combinarli; la barra di stato indica la combinazione.

7. Rimappatura dei percorsi

La CI spesso registra percorsi assoluti della macchina di build che non esistono sulla tua workstation. Riscrivili con regole ordinate:

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

Le regole si applicano in ordine; la prima corrispondenza vince per prefisso. Usa questo per uniformare le differenze dei separatori Windows/Unix o mappare un percorso container sul tuo checkout.

Raramente devi scrivere la regola da solo. Il più comune «ha caricato ma non si accende nulla» è un tracefile i cui percorsi vengono da un container o da un checkout CI (/build/src/a.c, /home/runner/work/repo/repo/src/a.c, C:\agent\_work\1\s\src\a.c) mentre lo spazio di lavoro ha src/a.c. Quando un caricamento lascia file senza corrispondenza, l'estensione cerca i nomi dei file nello spazio di lavoro, deduce la regola di prefisso che ne spiega il maggior numero, la registra come [FUCINI_REMAP_002], e il risultato del caricamento offre Apply Suggested Remap — un clic aggiunge la regola a fuciniCoverage.pathRemap e ricarica. Suggest Path Remap Rule esegue la stessa analisi su richiesta dalla palette. Nulla viene scritto senza il clic.

Un to può usare ${workspaceRoot}, che sta per la cartella dello spazio di lavoro in cui si trova il tracefile; in uno spazio di lavoro multi-root prova prima quella cartella, poi ogni altra cartella che risulta avere il file. Le regole stesse vengono lette per cartella, così ogni radice di uno spazio di lavoro multi-root può avere le proprie.

8. Coverage nell'editor

  • Gutter e righello — per impostazione predefinita il gutter dell'editor stesso mostra solo i rilievi: barre MC/DC, triangoli «dall'ultima esecuzione», puntini sulle righe modificate. editorGutter.mode aggiunge barre solo sulle righe non coperte o una mappa di calore dei conteggi (sotto); la vista a colori di un intero file è l'Annotated Source.
  • CodeLens di funzione — % di coverage sopra ogni funzione; clicca per saltare alla sua prima riga non coperta. Attiva/disattiva con codeLens.enabled.
  • Hover su ramo e MC/DC — passa il mouse su una riga di decisione per i conteggi presi/non presi per ramo e una tabella vettoriale per condizione. Abilita una barra di margine colorata con mcdcGutter.enabled.
  • Avvisi di codice morto — le funzioni con righe misurabili e copertura pari a zero sono segnalate nel pannello Problems (deadCode.enabled).
  • Next / Previous Uncovered — salta tra le lacune.
  • Barra di stato — un elemento $(dashboard) NN% a livello di esecuzione e uno per file, entrambi colorati in base al punteggio composito; passa il mouse per una tabella completa delle metriche.
  • Badge dell'Esplora file — badge di copertura per file e per cartella, con il dettaglio per metrica al passaggio del mouse. Disattivati per impostazione predefinita: attivali con explorerBadges.enabled.
  • Dall'ultima esecuzione — un triangolo rosso su ogni riga eseguita nell'esecuzione precedente e non in questa, uno verde per il caso inverso, con il righello panoramico e i conteggi al passaggio del mouse.
  • Buffer modificati — ogni contrassegno, suggerimento e CodeLens si sposta con il testo mentre modifichi, e si ritira da una riga riscritta, dove un punto grigio dice perché.
  • Conteggi dei colpi in linea — hitCounts.inline scrive ×12 dopo ogni riga su cui inizia un'istruzione, ×0 compreso: il numero che è sempre stato al passaggio del mouse, senza passarci il mouse. Toggle Inline Hit Counts lo alterna; il menu della barra di stato lo offre come Mostra o Nascondi, a seconda del caso.
  • Voci per riga nel pannello Problems — problems.perLine mette una diagnostica di tipo Information, con una sottolineatura ondulata nell'editor, su ogni blocco contiguo di righe mai eseguite in un documento aperto (una funzione morta di quaranta righe è una voce, non quaranta) e, come uncoveredAndPartial, su ogni riga il cui arco di ramo non è mai stato preso. Le voci seguono le loro righe mentre modifichi e spariscono alla chiusura del documento; la voce per file dietro problems.enabled è invariata.
  • Tinta di riga — lineHighlight mette una tinta traslucida dietro le righe stesse, per ciò che il margine segna (uncovered, oppure heatmap anche per le righe eseguite). Un’impostazione a sé, così il margine può restare pulito mentre i vuoti sono colorati, o viceversa.
  • Righello di panoramica — overviewRuler decide la striscia nella barra di scorrimento indipendentemente dal margine: follow (con le barre, come prima), uncovered (sempre, così il margine può essere disattivato mentre la barra di scorrimento continua a mappare i vuoti) oppure off.
  • Quale tracefile ha coperto una riga — con più report uniti, il suggerimento con il conteggio dei passaggi termina con Coperto da: e ogni report che ha coperto quella riga, compreso il nome della suite dal TN: di lcov; un clic su una riga di tracefile nella vista Coverage illumina le righe che ha contribuito in ogni editor aperto.
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).

Modalità del gutter dell'editor

editorGutter.mode decide cosa mostra sulla copertura il gutter dell'editor stesso, oltre ai rilievi che mostra sempre. off (il predefinito) è solo quelli. uncovered mette una barra su ogni riga mai eseguita e una ambra su ogni riga con un arco di ramo mai preso, e nulla sulle righe coperte, così un muro verde non nasconde le tre rosse. coverage aggiunge una barra verde su ogni riga coperta, così l'intero file si legge in rosso, ambra e verde con i colori della scala cromatica. heatmap aggiunge invece una tinta calda su ogni riga eseguita, più intensa quanto più spesso è stata eseguita — mostra quante volte una riga è stata eseguita, non se è coperta, per cui un file al 100% lì va dal giallo al marrone, mai verde. Choose Editor Gutter Mode... ne sceglie una dalla palette o dal menu della barra di stato; il pulsante della modalità a destra nella barra di stato, o Alt+G, passa alla successiva con una sola pressione (statusBar.showModeToggle nasconde il pulsante). Entrambi scrivono l'impostazione. L'esempio attiva insieme le barre sulle righe non coperte e i conteggi in linea:

{
  "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
In VS Code: la modalità coverage — verde dove una riga è stata eseguita per intero, ambra dove un arco di ramo non lo è mai stato, rosso dove non è stato eseguito nulla. L'elemento del file nella barra di stato indica il report da cui vengono i suoi numeri; il pulsante della modalità accanto dice Coverage.
Alt+G pressed four times: heatmap, off, uncovered and back to coverage
In VS Code: Alt+G quattro volte — heatmap, off, uncovered e di nuovo coverage.
Visual Studio: Gutter: Coverage on Quote.cs, green, amber and red bars beside the hit counts
In Visual Studio: Gutter: Coverage (Red, Amber, Green) su Quote.cs.

La heatmap è relativa al file. La tonalità di una riga confronta il suo conteggio con quello della riga più calda dello stesso file, su scala logaritmica, in cinque gradini — così il corpo di un ciclo eseguito mille volte e una funzione eseguita due volte sono entrambi visibili, senza che l'uno sommerga l'altra, e un file in cui tutto è stato eseguito esattamente una volta risulta uniformemente caldo anziché uniformemente pallido. Con un tema scuro la scala va dall'oliva spento all'arancione vivo, con un tema chiaro dal giallo pallido al marrone: in entrambi i casi più colore significa più esecuzioni, e il rosso resta riservato alle righe mai eseguite. lineHighlight: "heatmap" stende le stesse tonalità dietro il codice come sfondo, e hitCounts.inline scrive il conteggio esatto dopo la riga.

{
  "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).

I colori li scegli tu. colorScale.lowColor, midColor e highColor danno il rosso, l'ambra e il verde del gutter, delle tinte di riga e di ogni percentuale; heatmap.colors e heatmap.colorsDark contengono le cinque tinte della heatmap per un tema chiaro e uno scuro, dalla riga eseguita meno volte a quella eseguita più volte. La pagina delle impostazioni mostra il risultato prima che venga salvato qualcosa: sotto Colour scale, un'anteprima resta visibile mentre le righe scorrono — il gradiente con i suoi due punti di snodo, alcune percentuali nei loro colori, e un piccolo editor chiaro e uno scuro colorati nella modalità coverage e nella heatmap — e si ridisegna non appena si sceglie un colore.

{
  "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
In VS Code: due colori digitati nella pagina delle impostazioni — l'anteprima si ridisegna ogni volta.
Visual Studio: the same settings page and the same colour preview
In Visual Studio: la stessa pagina, la stessa anteprima.

La parte di una riga che non è mai stata eseguita

Una riga è coperta oppure no, e la verità sta spesso nel mezzo: return x > hi ? hi : x; è stata eseguita, il suo ramo hi mai. Con lineHighlight attivo, la parte mai eseguita di una riga eseguita viene colorata nell'editor, per ogni formato che riporta gli intervalli di colonne (llvm-cov, Istanbul, Go, dotnet-coverage) — gli stessi intervalli che evidenzia Annotated Source. Solo sulle righe eseguite: una riga mai eseguita è già contrassegnata per intero. Un template C++ conta come eseguito là dove una qualsiasi istanziazione lo ha eseguito; che cosa abbia fatto ciascuna istanziazione è ciò che riporta la metrica delle istanziazioni.

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).

Quali test hanno eseguito questa riga

Alcuni report dicono non solo che una riga è stata eseguita, ma anche quali test l'hanno eseguita: coverage.py scritto con coverage json --show-contexts e dynamic_context = test_function in .coveragerc, OpenCover raccolto con -coverbytest, e un tracefile lcov scritto una sezione per test (TN:), le cui sezioni vengono sommate in un unico record con i test per riga. Passando il mouse sull'inizio di una riga, dove si trova il conteggio delle esecuzioni, i test vengono elencati — abbreviati a classe e metodo, i primi cinque per nome e gli altri come numero; il CodeLens della funzione dice quanti test l'hanno eseguita. Show Tests That Ran This Line — dalla Command Palette, dal menu contestuale dell'editor, in Visual Studio da Tools → Coverage Studio o con Ctrl+Shift+U, T — li elenca, dal più attivo in poi, e apre quello scelto dove è scritto nello spazio di lavoro. Un'esecuzione dotnet test non sa dire quale test ha eseguito cosa; impostate testRun.perTest e Run Tests with Coverage elenca le classi di test e le esegue una alla volta, ogni report contrassegnato con la sua classe, così l'hover, il lens e il comando possono rispondere anche per .NET. L'informazione è conservata per file, quindi sopravvive all'unione con un report che dei test non sa nulla.

{
  "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: l'elenco, dal più attivo in poi, e il test aperto dove è scritto.
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
In Visual Studio: Show Tests That Ran This Line sulla riga 62 di Quote.cs — il test che l’ha eseguita, e Go to Test che lo apre.

Superato o fallito, sui segni

Una riga coperta ha lo stesso aspetto, che il suo test sia passato o no. Dove il report dice quali test hanno eseguito una riga e il file dei risultati del runner dice come sono finiti, una riga eseguita da un test fallito riceve una barra rossa al suo inizio e una striscia nel righello di panoramica; il suo hover nomina i test falliti, e Show Tests That Ran This Line scrive fallito accanto a ciascuno. Quando un test è rosso, il posto in cui guardare è il codice che ha attraversato. I risultati vengono letti a ogni caricamento dalla cartella di ciascun report — qualsiasi .trx, e i nomi usati dagli strumenti che scrivono JUnit (TEST-*.xml, junit*.xml, test-results*.xml) — e da testResults.paths, come percorsi o glob relativi alla cartella. Run Tests with Coverage chiede a dotnet test un test-results.trx accanto al report, così con testRun.perTest attivo non c'è nulla da configurare. testResults.enabled disattiva questa lettura.

{
  "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).
In Visual Studio: un test rosso — la barra rossa sulle righe che ha eseguito, la scheda che lo nomina, e Show Tests That Ran This Line che scrive failed accanto.

I test che una modifica tocca

Un'esecuzione completa risponde lentamente a ciò a cui Run Tests Affected by My Changes… risponde subito: fra tutti i test, quali sono passati per il codice che ho appena modificato? A git viene chiesto il diff dell'albero di lavoro rispetto a testImpact.baseRef — HEAD per impostazione predefinita, cioè ciò che non è ancora in un commit; origin/main per tutto ciò che il ramo cambia — e vengono elencati i test che hanno eseguito una riga modificata, per primo quello che ha eseguito la parte maggiore della modifica. Scegliere un test lo apre. Dove i report provengono da un'esecuzione per test (testRun.perTest), la prima voce esegue solo quei test, ogni classe nel proprio report, così il report di tutte le altre classi resta valido e i totali restano quelli dell'intera suite. Viene elencato anche un test che ha eseguito solo righe sotto un inserimento o una rimozione: altrimenti il suo report nominerebbe le righe sbagliate.

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).
In Visual Studio: una modifica, Run Tests Affected by My Changes…, l’elenco con per primo il test che ha eseguito la maggior parte della modifica, e l’esecuzione di quelli soltanto.

Il minor numero di test che eseguono ancora ogni riga

Show Minimal Test Set… risponde a due domande a partire dalle stesse righe per test: quali pochi test eseguirebbero ancora ogni riga che la suite esegue — per l'esecuzione rapida prima di un commit — e quali test non eseguono alcuna riga che un altro non esegua già. I test scelti vengono per primi, ciascuno con le righe che aggiunge e le righe che esegue solo lui; poi gli altri, ciascuno segnato come uno che non aggiunge nulla. La scelta è quella greedy — il test che esegue più righe, poi quello che ne aggiunge di più a quelle — quindi è vicina all'insieme più piccolo ed è la stessa ogni volta. Ridondante per righe non vuol dire ridondante per ciò che un test verifica: un test che non aggiunge alcuna riga può comunque essere l'unico a verificare un valore su quelle righe. L'elenco dice dove guardare quando si sfoltisce una suite, mai che cosa eliminare.

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).
In Visual Studio: Show Minimal Test Set… — i test scelti, poi quelli che non aggiungono nulla.

Eseguire questo test, con la coverage

Mettete il cursore in un test ed eseguite Run This Test with Coverage — dalla Command Palette, dal menu contestuale dell'editor, in Visual Studio da Tools → Coverage Studio o con Ctrl+Shift+U, R — e quel solo test viene eseguito con la coverage attiva: il metodo di test in cui sta il cursore, oppure la classe di test o il blocco describe quando è tra un metodo e l'altro, oppure il file quando è sopra ogni classe. Ciò che sta sotto il cursore viene letto dal testo, quindi funziona per C#, VB e F# ([Fact], [Test], [TestMethod] e simili), JavaScript e TypeScript (it, test, describe) e Python (def test_…), qualunque servizio di linguaggio sia installato. La ricetta della cartella viene ristretta a esso — dotnet test --filter "FullyQualifiedName~…", jest o vitest <file> -t "…", un node id di pytest — e ciò che ha scritto viene caricato come qualsiasi esecuzione; un runner che non si può restringere lo dice, e Run Tests with Coverage li esegue tutti.

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, un'esecuzione, la classe sotto test illuminata.
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)
In Visual Studio: Run This Test with Coverage in un [Fact] — l’esecuzione nell’elenco Tracefiles, le righe sopra i metodi che dicono che un solo test ha eseguito il codice.

Go e Rust. In un file Go il func TestXxx (o Fuzz…, Example…) in cui sta il cursore viene eseguito da solo, nel proprio package e con il suo nome esatto — go test ./pkg/calc -run "^TestTotal$" — e fuori da un test viene eseguito il package del file. In un file Rust la funzione #[test] viene eseguita tramite il suo percorso nel crate con --exact; con il cursore in un mod e in nessun test, vengono eseguiti i test di quel modulo; un test di integrazione sotto tests/ viene eseguito nel proprio binario (--test api). A un runner vengono passati solo file del suo linguaggio: un file TypeScript in una cartella Go ottiene una frase, non un'esecuzione di nulla.

La coverage dopo ogni salvataggio

Con testRun.onSave attivo, salvare un sorgente esegue i test che lo coprono, con la coverage, un istante dopo il salvataggio, e il gutter segue. Per una soluzione .NET il progetto del file salvato viene trovato attraverso il grafo dei .csproj e vengono eseguiti solo i progetti di test che lo referenziano — direttamente, o attraverso altri progetti — un dotnet test <project> ciascuno; qualunque altro runner esegue la sua ricetta intera; un file che nessun progetto possiede e nessun report misura non esegue nulla. Più salvataggi di seguito sono una sola esecuzione, e un'esecuzione già in corso non viene interrotta. Il resto è come lo fa Run Tests with Coverage: il terminale, il riquadro Output, il report caricato. Disattivato per impostazione predefinita — è un'abitudine da scegliere, non un predefinito da scoprire.

{
  "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 coverage dopo ogni salvataggio: modificate, salvate, e il gutter segue un istante dopo.
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
In Visual Studio: testRun.onSave attivo — Quote.cs salvato, i test partono da soli, la riga sopra il metodo cambia.

L'app stessa, con la coverage

Un'esecuzione di test dice ciò che i test raggiungono. Ciò che raggiunge una persona — facendo clic fra le schermate prima di un rilascio, ripetendo i passi di un cliente — è anch'esso coverage, e Run App with Coverage… lo raccoglie. L'app .NET della cartella — un Exe, un WinExe, un progetto web o worker, mai un progetto di test; una scelta dove ce n'è più d'una — viene avviata sotto dotnet-coverage di Microsoft in una console tutta sua, così che in un'app console si possa digitare, e resta in esecuzione finché non la chiudete. Ciò che avete percorso viene poi caricato come qualsiasi esecuzione, e in una sessione di coverage si aggiunge a ciò che i test hanno eseguito. Come l'app è terminata non conta contro l'esecuzione. Lo strumento va installato una volta: 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).
In Visual Studio: Run App with Coverage… — l’app console, qualche input, chiusa, e la sua copertura caricata.

I mutanti, e dove si trovano

Uno strumento di mutation testing — PIT per Java, Stryker per JavaScript, C# e Scala, Mull per C e C++ — modifica il codice in piccoli punti ed esegue i test contro ogni modifica. Una modifica che nessun test nota è un mutante sopravvissuto: il codice è stato eseguito, e niente ha verificato che cosa abbia fatto. Il punteggio di mutazione dice quanti sono stati individuati; dalla versione 0.2026.83 l'editor dice dove si trovano gli altri. Una riga che ne contiene uno porta una nota in coda (⚑ 2 mutants survived), il testo modificato è sottolineato quando il report indica di quale testo si trattava (lo fanno Stryker e Mull), il righello di panoramica ha una striscia, e al passaggio del mouse si vede che cosa è stato modificato, quanti test lo hanno eseguito e, per i mutanti individuati, quale test li ha individuati.

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).

Sopravvissuto significa che i test hanno eseguito il codice modificato e sono tutti passati. Non testato (il no coverage del report) significa che nessun test esegue quel codice, quindi niente avrebbe potuto accorgersene. I mutanti individuati vengono contati al passaggio del mouse e mai contrassegnati, e i mutanti che non sono mai stati una prova equa — uno che non compilerebbe — restano fuori dal punteggio. Annotated Source ha una riga sotto ciascuna di queste righe e un pulsante Next Mutant (U), e i report HTML hanno una sezione Surviving Mutants con il collegamento alla riga. Non c'è nulla da attivare, e un progetto senza report di mutazione non ne vede niente.

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 se ne accorgerebbe? Un'esecuzione di mutazione sotto il cursore

L'esecuzione di mutazione di un progetto richiede un'ora; quella di una funzione, un minuto. Run Mutation Tests Here esegue quel minuto: la funzione in cui sta il cursore — o le righe selezionate, o il file — è ciò che al runner di mutazione della cartella viene detto di mutare, e il suo report viene caricato accanto alla coverage sullo schermo, dove i mutanti sopravvissuti sono segnati. Per C# è Stryker.NET (dotnet tool install --global dotnet-stryker), a cui vengono indicati l'intervallo di caratteri e il progetto di test che referenzia il progetto del file; per JavaScript e TypeScript StrykerJS, a cui vengono indicate le righe; per Java PIT con Maven, a cui viene indicata la classe. Come il runner è terminato non conta contro l'esecuzione: un punteggio sotto la sua soglia è un codice di uscita, e resta un report. Un runner che non ha scritto nulla viene segnalato, con ciò che gli serve installato.

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).
In Visual Studio: Run Mutation Tests Here su una sola funzione, e i mutanti sopravvissuti segnati.

La vista Test Coverage di VS Code stesso

Con testCoverage.publish attivo (il predefinito), ogni esecuzione caricata va anche alla vista Test Coverage nativa dell'editor — il pannello di copertura del Test Explorer, le percentuali per file che mette nell'Explorer, e l'interruttore Show Inline Coverage dell'editor stesso — come righe, archi di ramo e funzioni, con i dettagli caricati su richiesta, da qualunque tracefile provengano e senza alcun adattatore di test di mezzo. Show in Test Coverage View pubblica l'esecuzione attiva e apre il pannello qualunque cosa dica l'impostazione; il menu della barra di stato lo offre dietro quickActions.showTestCoverage. Disattivato, nel Test Explorer non compare alcuna voce Fucini Coverage. Quando un file di traccia nomina i suoi test (le sezioni TN: di lcov), ogni test compare sotto Fucini Coverage nel Test Explorer e la vista può filtrare la copertura di un file per 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).

Righe non coperte nel pannello Problems

Disattivato per impostazione predefinita perché rumoroso per natura, e solo per i documenti aperti — un'esecuzione da duemila file non può inondare il pannello. Indipendente da problems.enabled, che si limita a una voce per file:

{
  "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. Coverage differenziale

Limita le decorazioni alle righe modificate rispetto a un riferimento base git — ideale per rivedere esattamente cosa una PR ha coperto o meno:

{
  "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).

In Visual Studio. Le stesse due impostazioni, lette dagli stessi file: l'estensione esegue da sé git diff <baseRef> per ogni file dell'esecuzione e riduce l'esecuzione alle righe che il vostro ramo ha cambiato — nel margine, nella finestra Coverage e nei gate. Il riquadro Output dice cosa ha risposto git quando non risponde nulla.

Un gate sul codice nuovo

threshold.newCode è un gate a sé, accanto a quelli sull'intera esecuzione: delle righe modificate rispetto a gitDiff.baseRef che si possono misurare, la percentuale minima che deve essere stata eseguita. Un progetto al 62% complessivo può comunque chiedere che ciò che viene scritto oggi sia testato. Viene calcolato a ogni caricamento sull'intera esecuzione, che resta sullo schermo — gitDiff.enabled è un'altra cosa: le righe modificate al posto dell'esecuzione. Check Coverage Thresholds e le voci di conformità in Problems lo danno per fallito in una frase tutta sua: New code 72.00% < 80% (18 of 25 line(s) changed against origin/main ran). Una modifica senza alcuna riga misurabile — commenti, un README — non fa fallire nulla.

{
  "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).
In Visual Studio: Check Coverage Thresholds che boccia il gate del codice nuovo, accanto a un’esecuzione che supera i propri gate.

Codice nuovo per tag, per autore, per data

Il codice nuovo sono, per impostazione predefinita, le righe che l'albero di lavoro cambia rispetto a gitDiff.baseRef — un ramo, un commit o un tag: "v1.4.0" è tutto ciò che è venuto dopo quel rilascio. Due impostazioni chiedono ciò che un riferimento git non può. gitDiff.author prende parte del nome di un autore, e il codice nuovo sono allora le righe che git attribuisce a quell'autore; gitDiff.since prende un giorno, e sono le righe modificate per l'ultima volta in quel giorno o dopo, qualunque sia il ramo da cui sono arrivate; entrambe insieme, le righe di quell'autore da quel giorno. Si basano su git blame, un file alla volta — cosa che un'esecuzione grande sentirà a ogni caricamento — e prendono il posto del diff per la coverage del diff e per il gate qui sopra. Una riga non ancora in un commit conta in entrambi i casi.

{
  "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).

Modifiche indirette: ciò che si è mosso senza che nessuno lo toccasse

Un diff dice quali righe sono cambiate; due esecuzioni dicono quali righe hanno smesso o iniziato a essere eseguite. Le righe che meritano uno sguardo sono quelle in cui i due discordano: codice che nessuno ha modificato e che non viene più eseguito, perché un test è stato eliminato, perché un ramo a monte ora ritorna prima, perché una fixture è cambiata. Una revisione del diff non può vederle — ne sono fuori per definizione. Show Indirect Coverage Changes… le elenca per file, per primo il file che ha perso di più, e apre quello che scegliete alla sua prima riga di questo tipo. L'esecuzione viene confrontata con la baseline CI dove baseline.report ne indica una — che è ciò su cui viene giudicata una pull request — e altrimenti con l'esecuzione precedente; le righe che l'albero di lavoro cambia rispetto a gitDiff.baseRef, e tutto ciò che sta sotto un punto in cui quella modifica sposta le righe del file, vengono lasciati fuori.

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).
In Visual Studio: Show Indirect Coverage Changes… — un file che ha perso righe che nessuno ha modificato, dopo che un test è stato tolto tra due esecuzioni.

10. Il punteggio composito

Invece di riportare sei numeri, l'estensione li combina in un'unica Media Armonica Ponderata (WHM). Per metriche con percentuali pᵢ e pesi wᵢ:

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

Una media armonica è dominata dal suo termine più piccolo, quindi una metrica debole non può essere mascherata da una perfetta — esattamente la proprietà che vuoi da un gate di sicurezza. Pesi predefiniti:

MetricaPesoMotivazione
MC/DC4IEC 61508 SIL 3–4 / ISO 26262 ASIL C–D / DO-178C DAL A–B.
Rami2IEC 61508 SIL 2+ / ISO 26262 ASIL B+.
Condizioni3Tra i rami e MC/DC (DO-178C, ISO 26262).
Regioni1.5Percorsi interni a un’istruzione (es. corto circuito parziale).
Righe1IEC 61508 SIL 1+ / ISO 26262 ASIL A+.
Funzioni1Controllo del codice morto.
Istanziazioni0.5Copertura dei template C++; ambito più ristretto.
Chiamate di funzione1Punti di chiamata che sono stati eseguiti (gcov, VectorCAST, Testwell CTC++, TRACE32).
Codice oggetto0Disattivato finché non gli si assegna un peso: comprende già la copertura delle istruzioni.
Punteggio di mutazione0Disattivato finché non gli si assegna un peso: non è copertura.

Imposta un peso a 0 per escludere quella metrica dal punteggio. Le metriche non presenti nei dati (ad es. MC/DC in una semplice esecuzione lcov) vengono semplicemente omesse.

Il codice oggetto e il punteggio di mutazione pesano 0 finché non si decide diversamente (whmWeights.objectCode, whmWeights.mutation). La copertura del codice oggetto comprende già la copertura delle istruzioni, quindi pesarle entrambe conta due volte la stessa evidenza; un punteggio di mutazione non è affatto copertura — una suite di test può eseguire ogni riga e non rilevare nulla. Entrambi hanno comunque una colonna propria e una soglia propria.

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).

Copertura delle condizioni

a && b è una decisione — due rami — e due condizioni con quattro esiti. Una suite può percorrere entrambi i rami e non vedere mai b falso: la copertura dei rami è completa e la copertura delle condizioni è tre su quattro. Questo livello si colloca tra la copertura dei rami e MC/DC in DO-178C e ISO 26262, e dalla versione 0.2026.83 è una metrica a sé anziché essere inglobata nei rami: una riga nelle schede della barra di stato, una colonna nella vista Coverage, nei report e nelle esportazioni, un peso di 3 nel punteggio (whmWeights.conditions) e un gate (threshold.conditions; nessun gate con il profilo standard, 100 con 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).

Lette dalle sonde condition di BullseyeCoverage, da un'esportazione cond di TRACE32 e da GCC 14 compilato con -fcondition-coverage. Un report che non distingue le condizioni dalle decisioni non ha né riga, né colonna, né peso di questo tipo. Se si usa Bullseye o TRACE32: le condizioni finora contavano come rami, quindi con questa versione la percentuale dei rami cambia e, con il nuovo peso, anche il punteggio composito; impostare whmWeights.conditions su 0 per avere il punteggio com'era.

GCC 14, riga per riga. -fcondition-coverage fa dire a gcov quale esito di quale condizione manca — la condizione 1 mai vera, la condizione 0 mai né vera né falsa — e ogni condizione è segnata sulla sua riga e nominata nell'hover, dal JSON di gcov come dal suo listato testuale (condition outcomes covered 3/6). La metrica sta dove stanno le altre: threshold.conditions le fa da gate e resta non giudicato dove un'esecuzione non ha quel valore, Copy Coverage Summary ha una colonna Conditions, badge.metric accetta conditions, e la casella di ricerca accetta conditions < 80. Il valore dei rami di una funzione lascia fuori gli esiti delle sue condizioni, come quelli del file e dell'esecuzione.

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).

Complessità e CRAP

Alcuni report contengono la complessità ciclomatica di ogni funzione: OpenCover (che è ciò che scrive Coverlet), JaCoCo, Clover e Cobertura. In tal caso l'estensione calcola un punteggio CRAP — Change Risk Anti-Patterns — per la funzione, a partire da quella complessità e dalla copertura che essa stessa ha misurato:

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

Una funzione semplice e completamente testata ottiene come punteggio la propria complessità e nulla più; una funzione complessa e appena testata arriva a diverse centinaia. Nell'esempio C# del progetto dimostrativo Price() ha complessità 22 e circa il 37% delle righe coperte, il che dà 142.2, mentre Shipping() ha complessità 12 ed è completamente coperta, il che dà 12. Il limite consueto è 30: una funzione che lo raggiunge o lo supera è elencata sotto Riskiest Methods nel report HTML, a partire dalla peggiore.

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 complessità e il punteggio compaiono nel CodeLens della funzione e accanto alla funzione nel sorgente annotato. Max CRAP è il punteggio più alto fra tutte le funzioni di un file — il peggiore, non una media — ed è una colonna nella vista Coverage, nel report HTML e nelle esportazioni CSV e Markdown. È un'informazione: non ha soglia né peso nel punteggio composito. I report che non contengono la complessità (lcov, gcov, Istanbul, coverage.py) non hanno CRAP, e nemmeno una colonna vuota.

Dalla versione 0.2026.83 lo hanno anche C e C++. llvm-cov non riporta alcuna complessità, quindi viene calcolata dai dati sui rami che il report già contiene: le condizioni scritte nel file della funzione stessa, più uno — la definizione di McCabe, ed è ciò che gli strumenti a livello di sorgente contano per .NET e Java. Le condizioni uscite da una macro di un altro file, ogni assert per esempio, non vengono contate.

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, e quali file mostrare

Sotto l'albero della vista Coverage, Risk hotspots elenca le funzioni dove il codice complesso incontra poca coverage, dalla peggiore in poi, ciascuna apre il suo file alla funzione. Una funzione si qualifica per punteggio CRAP — hotspots.crapThreshold, 30 per impostazione predefinita, la cifra proposta dagli autori della metrica — o per la sola complessità ciclomatica, hotspots.complexityThreshold, disattivata per impostazione predefinita; solo i report che riportano la complessità (OpenCover, Cobertura di Coverlet, JaCoCo, llvm-cov) ne hanno. Community vede il conteggio e il punteggio peggiore; l'elenco ordinato è Pro. Accanto all'ordinamento, un secondo menu a discesa dice quali file mostra l'albero — tutti, i file con lacune, i file non testati, o i file cambiati dall'ultima esecuzione; le cartelle seguono i loro file e conservano i propri numeri. Entrambi sono anche in Visual Studio, nella finestra 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).
In Visual Studio: la finestra Coverage, con il filtro accanto all'ordinamento e i Risk hotspots sotto l'albero.

Namespace, classi e metodi

Per un report .NET che nomina le sue classi — Cobertura e il coverage.cobertura.xml di Coverlet, OpenCover — un terzo menu a discesa, Folders / Namespaces, disegna la stessa esecuzione come namespace, classi e metodi: il numero di un namespace è la somma di quelli delle sue classi, quello di una classe dei suoi metodi, esattamente come quello di una cartella è dei suoi file, con lo stesso ordinamento e lo stesso filtro. Una riga di metodo apre il file al metodo; una classe dichiarata in nessun namespace sta sotto (no namespace). La scelta viene scritta in coverageView.perspective; un'esecuzione che non porta nomi di classe non ha il menu a discesa e mostra le sue cartelle. In Visual Studio la finestra Coverage ha lo stesso menu a discesa.

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 stessa esecuzione per namespace, classe e metodo.
Visual Studio: the Coverage window with the dropdown on Namespaces, the Pricing namespace open on Customer and its methods
In Visual Studio: la finestra Coverage per namespace, classe e metodo.

Sotto i pulsanti e i menu a discesa, una casella di ricerca. Una parola tiene le righe il cui nome o percorso la contiene — ogni parola digitata deve esserci; un confronto tiene le righe la cui cifra lo soddisfa — < 80% sul punteggio, lines >= 90, branches = 0, functions != 100, mcdc < 50 — e invoice < 80 vuole entrambe le cose. Le righe di metodo della prospettiva per namespace e i risk hotspot vengono cercati insieme ai file, così una funzione si trova dove l'esecuzione la tiene. L'albero viene filtrato mentre digitate, nella pagina, senza ridisegnarlo; una cartella che contiene una corrispondenza si apre per essa e si richiude quando la casella si svuota; Esc la cancella. La stessa casella, la stessa grammatica, in 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).
Cercare nell'albero: un nome, poi lines < 80.

L'albero segue l'editor

Il file che state guardando viene evidenziato nella vista Coverage, le cartelle sopra di esso vengono aperte e la sua riga viene portata in vista scorrendo — non occorre più cercare nell'albero il file che è già aperto. Per il resto l'albero mantiene la sua posizione di scorrimento, e nulla viene ridisegnato. coverageView.followActiveEditor, attivo per impostazione predefinita, lo disattiva per chi preferisce lasciare l'albero dove l'ha messo.

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).
In Visual Studio: cambiando documento, la riga evidenziata della finestra Coverage lo segue.

11. Gating di conformità

Il verdetto COMPLIANT / NON-COMPLIANT (mostrato nella vista sorgente annotata, nel report HTML ed entrambi gli hover della barra di stato) è determinato da soglie per metrica e una modalità:

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).
ModalitàCOMPLIANT quando…
strict (default)ogni metrica controllata singolarmente raggiunge la propria soglia: nessun compromesso.
whml’unico punteggio composito ponderato raggiunge threshold.weighted.
bothsono soddisfatti sia il controllo ponderato SIA quello rigoroso per metrica.
eitherè soddisfatto il controllo ponderato OPPURE quello rigoroso per metrica (il più permissivo).

Una soglia di 0 disattiva quel gate, e una metrica che il report non contiene non viene mai giudicata. Che cosa vale una soglia non impostata lo decide il profilo descritto più sotto. Esegua Fucini Coverage: Check Coverage Thresholds per valutare su richiesta.

In Visual Studio. Tools → Coverage Studio → Check Coverage Thresholds giudica l'esecuzione rispetto alle stesse chiavi threshold.* e lo dice nella barra di stato e nel riquadro Output; con compliance.diagnostics, problems.enabled, problems.perLine o deadCode.enabled i rilievi stanno nell'Error List accanto a quelli del compilatore — una voce per file sotto un gate, una per intervallo non coperto, una per funzione mai eseguita — ciascuna apre il suo file alla riga.

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).
In Visual Studio: Check Coverage Thresholds, con i risultati nell'Error List.

Profili delle soglie

threshold.profile stabilisce che cosa vale una soglia che non è stata impostata. standard, il valore predefinito dalla versione 0.2026.82, è ciò che si può esigere da un progetto ordinario non legato alla sicurezza funzionale. safety porta ogni gate a 100 — ciò che richiede un safety case, ed esattamente ciò che veniva distribuito fino alla versione 0.2026.81.

Metricastandardsafety
Righe80100
Funzioni80100
Regioni75100
Rami70100
Punteggio composito75100
MC/DC, istanziazioni, chiamate di funzione, codice oggettosenza gate100
Condizionisenza gate100
Punteggio di mutazionesenza gatesenza gate

Una soglia impostata esplicitamente prevale su entrambi i profili. L'esempio fissa il gate dei rami a 90 e tutto il resto a 100; per esigere 100 solo da alcune metriche, si resti su standard e si impostino quelle manualmente. Un'avvertenza deriva dal funzionamento delle impostazioni: un valore uguale a quello predefinito di fabbrica non è distinguibile dall'assenza di valore, perciò con safety una soglia scritta esattamente con la sua cifra standard — 80 per le righe, ad esempio — conta comunque come 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).

Se faceva affidamento sui vecchi valori predefiniti, dopo l'aggiornamento alla versione 0.2026.82 il giudizio sarà più indulgente finché non seleziona safety. Un'installazione già in uso in precedenza ne viene informata una sola volta, con un pulsante Keep 100% (safety) che scrive il profilo nelle impostazioni utente; per un progetto condiviso lo inserisca anche nelle impostazioni dell'area di lavoro, in modo che tutti siano giudicati allo stesso modo. Configure Coverage Compliance & Thresholds... presenta il profilo sopra la griglia delle soglie, e la sua anteprima in tempo reale giudica con i gate effettivamente in vigore. In ogni scheda e report, una metrica il cui gate è disattivato mostra la propria cifra con un trattino neutro anziché un segno di spunta o una croce.

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. Coverage del codice oggetto

Ogni altra metrica qui si misura dal sorgente: uno strumento instrumenta il codice, la build instrumentata gira e i contatori dicono quali istruzioni, rami o condizioni sono stati esercitati. La coverage del codice oggetto misura altro — quanta parte del binario costruito è stata davvero eseguita, contata in byte di istruzioni, osservando il flusso di istruzioni anziché instrumentando il sorgente. Conta perché un compilatore emette codice di cui nessuna riga del vostro sorgente rende conto: controlli sui limiti degli array, tabelle di salto di switch, salvataggi di registri, sonde di stack, chiamate a routine di supporto del runtime per divisione o virgola mobile su core privi dell'istruzione. È anche l'unica metrica qui che risponde a questo copre l'assembly? — l'assembly scritto a mano non viene mai instrumentato e uno strumento basato sul sorgente non lo raggiunge. DO-178C dice esplicitamente perché: al livello A, dove un compilatore o un linker genera codice non direttamente tracciabile alle istruzioni sorgente, l'obiettivo 6.4.4.2b richiede una verifica aggiuntiva proprio di quel codice generato.

Sussume la coverage delle istruzioni: ogni istruzione macchina eseguita proviene da un'istruzione sorgente, quindi il 100% di coverage del codice oggetto implica il 100% di coverage delle istruzioni. Il contrario non vale, e proprio quell'asimmetria è il motivo per misurarla. Ne seguono due cose. Non ha alcun peso nel punteggio composito, perché mediare due misure delle stesse esecuzioni conta due volte la stessa prova; è invece controllata da fuciniCoverage.threshold.objectCode, un requisito anziché un peso, che è come la norma la richiede. E il divario è ciò che conta: un'esecuzione al 100% di coverage delle righe con meno del 100% di coverage del codice oggetto ha individuato esattamente il codice generato dal compilatore di cui il vostro sorgente non rende conto, perciò la scheda di conformità dice 312 byte mai eseguiti, con 100% di coverage delle righe invece di seppellirlo come «94%». Il contrario — un intero binario dato per eseguito mentre il suo sorgente no — è una contraddizione, non un punteggio basso: quasi sempre un tracefile obsoleto da un lato di una fusione, o nomi di moduli che non hanno mai corrisposto ai percorsi dei file. Viene segnalato come rilievo.

La coverage del codice oggetto richiede che il binario giri dove le sue istruzioni possano essere osservate. Ci sono tre strade e differiscono enormemente per costo. Solo la terza produce coverage del codice oggetto; le prime due sono qui perché risolvono un problema affine, spesso quello che conviene davvero risolvere.

  1. Una build instrumentata, in esecuzione sul target. I cross-compilatori GCC accettano -fprofile-arcs -ftest-coverage, quindi l'instrumentazione che funziona su una workstation funziona sul target — salvo che un sistema bare-metal non ha un filesystem su cui scrivere i contatori .gcda e spesso non ha un exit() in cui scriverli. I contatori stanno comunque in RAM, quindi la soluzione è scaricare quella memoria e ricostruire i file fuori dal target; embedded-gcov del JPL della NASA (Apache-2.0) fa esattamente questo, senza filesystem, sistema operativo o libreria C standard. Si ottiene coverage di istruzioni, rami e funzioni di una build prodotta dal vostro cross-compilatore, per il vostro set di istruzioni, sul vostro hardware — non coverage del codice oggetto, e il binario misurato è instrumentato, quindi più grande e più lento di quello che spedite. Caricate il risultato come LCOV, gcovr JSON, gcov JSON o, su una toolchain anteriore a GCC 9, come il listato in testo semplice .gcov.
  2. Un simulatore del set di istruzioni. Eseguite il vero binario target in un simulatore e ricavate la coverage dagli indirizzi eseguiti: niente hardware, niente instrumentazione, nessuna sonda e, poiché osserva istruzioni, può produrre vera coverage del codice oggetto. Il limite è la fedeltà: un simulatore modella bene il core e meno bene le periferiche, quindi trattate con sospetto i risultati di sistema completo a meno che non modelli da vicino il vostro silicio.
  3. Trace on-chip e un debugger. La via di livello certificativo, e l'unica davvero non intrusiva: l'unità di trace del core riporta il flusso di istruzioni a un debugger, che lo trasforma in coverage. Nulla viene instrumentato, la dimensione del codice non cambia e i tempi non sono alterati — ed è questo che rende il risultato una prova sul binario che spedite davvero. Verificate il silicio prima di metterlo a budget: in molte famiglie di microcontrollori il trace completo esiste solo su una variante di emulazione o sviluppo, con un ampio buffer di trace e una porta veloce, mentre i pezzi di produzione espongono un'unità di trace ridotta, il cui ripiego offerto dal fornitore è un trace software che instrumenta il codice e consuma tempo di CPU — eliminando proprio la proprietà per cui quella via era stata scelta.

Molti progetti embedded misurano la coverage compilando gli stessi sorgenti per la macchina di sviluppo ed eseguendo lì gli unit test. È veloce, non richiede hardware, ed è la scelta predefinita giusta per la maggior parte dei team — ma vale la pena essere chiari su cosa descriva davvero quella prova: un compilatore diverso, un ottimizzatore diverso, un set di istruzioni diverso e un binario diverso da quello che si spedisce. Per la maggior parte del software è un compromesso accettabile e ben compreso. Per lavori valutati secondo IEC 61508, ISO 26262 o DO-178C è la classica obiezione host-contro-target, e le vie sopra sono le risposte classiche: la prima la chiude per la coverage del sorgente, la terza per il codice oggetto.

Oggi l'export letto per il codice oggetto è quello di COVerage.EXPORT.ListModule di Lauterbach TRACE32 con metric="object"; caricatelo come qualsiasi altro tracefile. Questa metrica viene valutata e controllata solo con una licenza a pagamento e durante il periodo di valutazione. Un'installazione Community non la valuta — ma viene informata quando un tracefile la contiene, perché un verdetto di conformità che omettesse silenziosamente la prova più forte nel file sarebbe peggiore di uno che dice cosa ha omesso.

12. Esclusione delle righe non di codice

Con excludeComments attivo (predefinito), le istruzioni che cadono interamente su righe solo commento o vuote sono escluse dai totali — questo neutralizza anche una nota particolarità di llvm-cov/gcov in cui un conteggio dei colpi vagante finisce su un commento. Sono rispettati anche i marcatori standard:

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

Anche le direttive del preprocessore non contano come codice, in C, C++, Objective-C, CUDA e C#: una riga che inizia con # — #define, #include, #if — e le righe su cui la prosegue una barra rovesciata finale. gcov attribuisce ogni uso di una macro alla riga in cui è definita, così un header la cui unica riga riportata era #define CHANNEL_COUNT (33U) risultava coperto al 100% perché un ciclo nel file .c arrivava fino a quel valore, e uno la cui costante nessuno usava risultava allo 0%. Un header del genere ora non ha nulla da misurare e non viene elencato.

Imposta excluded.includeInTotals su true per contare comunque le righe escluse.

Lasciare fuori un file o una cartella, dall'albero

Fate clic destro su un file o una cartella nella vista Coverage e scegliete Exclude from Coverage — è anche tra le azioni di percorso della riga — oppure eseguite Exclude This File from Coverage sul file aperto: il percorso del file relativo allo spazio di lavoro, o il /** della cartella, va in fuciniCoverage.ignore nelle impostazioni della cartella, una volta sola, e il ricaricamento lo toglie da ogni totale e da ogni pagina; il pattern è lì per poter essere tolto di nuovo. In Visual Studio il menu della riga e Tools → Coverage Studio hanno gli stessi due comandi, che scrivono la stessa impostazione nello stesso file.

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 su una cartella: l'albero senza di essa, il pattern nelle impostazioni.
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
In Visual Studio: Exclude This File from Coverage su fees.ts — l’albero senza di esso, il pattern in .vscode/settings.json.

Attributi e namespace, per .NET

Due impostazioni leggono dal sorgente ciò che il report non sa dire. ignore.attributes — ExcludeFromCodeCoverage per impostazione predefinita — esclude la classe, il metodo o la proprietà sotto un attributo che nomina, come farebbero LCOV_EXCL_START/STOP, qualunque strumento abbia scritto il report: Coverlet rispetta l'attributo, OpenCover, dotCover e un lcov convertito no, e ora tutti concordano. Nomi con o senza il suffisso Attribute, con o senza namespace; aggiungete GeneratedCode, Obsolete o i vostri. ignore.namespaces lascia fuori ogni file la cui dichiarazione di namespace corrisponde a un prefisso, con * come jolly — Acme.Generated, Acme.*.Migrations, *Tests — e il riquadro Output nomina i file che ha tolto. Entrambe vengono lette nello stesso passaggio che legge i marcatori nei commenti, in entrambe le edizioni.

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

Escludere dall'editor

Selezionate le righe e prendete Exclude Selection from Coverage dalla lampadina, dal menu contestuale dell'editor o dalla Command Palette — in Visual Studio dalla lampadina (Ctrl+.), dal menu del clic destro della finestra di codice, da Tools → Coverage Studio o con Ctrl+Shift+U, X — e l'esclusione viene scritta dove sta il codice: [ExcludeFromCodeCoverage] sopra una classe, un metodo o una proprietà C#, VB o F#, con il nome breve quando il file importa già System.Diagnostics.CodeAnalysis e con il nome completo quando non lo importa, così che non si debba aggiungere alcuno using; LCOV_EXCL_LINE alla fine di una sola riga di codice; LCOV_EXCL_START e LCOV_EXCL_STOP attorno a più righe, all'indentazione della prima — con il segno di commento del linguaggio, //, #, ', -- o ;. Un solo passo di annullamento. La lampadina lo offre anche su una riga che le voci di Problems segnano come non coperta. Una riga già marcata, o un membro già attribuito, viene lasciato com'è.

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: i marcatori scritti attorno alla selezione, con il segno di commento del file.
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
In Visual Studio: Exclude Selection from Coverage — i marcatori LCOV_EXCL attorno a un ramo, poi [ExcludeFromCodeCoverage] sopra un metodo.

Solo i rami, e i marcatori di gcovr

Un else difensivo, un default: che nessun valore raggiunge, l'arco che un compilatore aggiunge per un'eccezione: la riga viene eseguita e deve contare, e solo il suo ramo non può essere preso. LCOV_EXCL_BR_LINE e LCOV_EXCL_BR_START … LCOV_EXCL_BR_STOP tolgono dal conteggio i rami sulle loro righe e vi lasciano le righe. LCOV_EXCL_EXCEPTION_BR_LINE e la sua regione tolgono ancora meno — solo gli archi percorsi da un'eccezione, dove il report dice quali sono, come fa il JSON di gcov. Ogni marcatore viene letto anche con i prefissi di gcovr: GCOVR_EXCL_LINE, GCOVR_EXCL_START, GCOVR_EXCL_BR_LINE, GCOV_EXCL_STOP e gli altri significano ciò che significano quelli LCOV_EXCL_, così un sorgente scritto per gcovr si legge qui allo stesso modo, qualunque strumento abbia prodotto il report. Non letto: GCOVR_EXCL_FUNCTION — nulla su quella riga dice dove finisce la funzione.

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 perché: esclusioni giustificate

Togliere codice dal conteggio è un'affermazione — «questo non si può testare», «questo è un aiuto per lo sviluppatore» — e sotto DO-178C, ISO 26262 o IEC 61508 un'affermazione che cambia il numero su cui poggia un certificato deve essere messa per iscritto e poter essere riesaminata. Perciò un'esclusione può dire perché, nel punto in cui è scritta: il testo dopo LCOV_EXCL_LINE o LCOV_EXCL_START, oppure la Justification di [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) { /* … */ }

Le motivazioni vengono lette a ogni caricamento e il log le conta. Export Coverage Report… scrive l'elenco — esclusioni e relative giustificazioni, come Markdown o CSV: il file, le righe, come l'esclusione è stata scritta, e la giustificazione oppure none given. Un file a cui non resta nulla di misurabile è comunque in quell'elenco. Con exclusions.requireReason attivo, un'esclusione che non dà alcuna motivazione è un rilievo: un avviso in Problems alla sua riga, e un fallimento di Check Coverage Thresholds. Exclude Selection from Coverage chiede allora prima la motivazione e la scrive con il marcatore o come Justification dell'attributo; se la richiesta viene chiusa o lasciata vuota, non viene escluso nulla.

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).
In Visual Studio: un’esclusione senza motivo come avviso sulla sua riga, e l’elenco esportato con none given.

12a. Questa copertura descrive ancora questo file?

La copertura letta da un tracefile descrive il sorgente com'era quando i test sono stati eseguiti, e la maggior parte dei formati non dice di quale versione si trattasse. Ogni file nel pannello Copertura si trova quindi in uno di tre stati:

  • ✓ Verificato — il tracefile registra ciò che conteneva ogni riga misurata, e corrisponde ancora al file.
  • Nessun segno — non smentito. Nulla contraddice la copertura e nulla la conferma. È lo stato ordinario.
  • ⚠ Smentito — il file stesso smentisce la propria copertura. La riga è attenuata e il tooltip dice cosa è stato trovato.

Solo due formati possono guadagnarsi il segno di spunta, perché solo due registrano qualcosa del sorgente misurato: lcov scritto con --checksum (disattivato per impostazione predefinita in geninfo; il suo scopo documentato è proprio impedire di combinare la copertura di due versioni di un file) e GNATcoverage XML, che incorpora il testo di ogni riga misurata. Attivare l'opzione lcov conviene.

L'avviso non ha bisogno di nessuno dei due e funziona con ogni formato: copertura registrata oltre la fine del file, una funzione con nome che non è più dove il report la colloca, o righe eseguite che nel file sono vuote. I timestamp da soli non bastano mai — un git checkout li cambia tutti senza modificare un byte —, quindi un timestamp cambiato è al più un motivo per guardare di nuovo. Il controllo viene eseguito al caricamento della copertura e di nuovo ogni volta che un file viene salvato o cambia su disco, così il contrassegno segue il file: una modifica che contraddice l'esecuzione lo mette, un checkout che ripristina la versione misurata lo toglie. Il suggerimento dice esattamente cosa lo ha dimostrato. Imposta staleWarning.enabled su false per disattivare tutto.

12b. Non misurato contro non coperto

Un file che l'esecuzione non nomina mai è non misurato: nessun test l'ha caricato, quindi nessuno strumento ha scritto una riga per esso. Non è la stessa cosa di non coperto — misurato, con zero colpi — e l'estensione non ha mai valutato un file assente come 0%. Ciò che non faceva, fino alla 0.2026.69, era mostrare affatto gli assenti: un modulo senza alcun test non compariva mai nell'albero, nei totali o nel controllo delle soglie, e chi leggeva vedeva «92%» per un progetto metà dei cui file non era mai stato esercitato.

Ora, con un'esecuzione caricata, l'elemento per file della barra di stato dice not measured per un file sorgente del tipo dell'esecuzione stessa che l'esecuzione non contiene — «del tipo dell'esecuzione» nel senso che ha una delle estensioni di file che l'esecuzione ha misurato, così le intestazioni e le sorgenti di un progetto C sono candidate e i suoi script Python no. Tutto il resto è su richiesta tramite fuciniCoverage.unmeasured.mode:

  • off (predefinito) — nient'altro cambia.
  • list — la vista Coverage riceve in fondo un gruppo Non misurati che nomina ogni file del genere, e ciascuna riga lo apre; il risultato del caricamento li conta; i badge li contrassegnano con ? nell'Explorer; e fuciniCoverage.threshold.unmeasuredFiles può far fallire Check Coverage Thresholds quando sono più di un numero che imposti tu. Nessuna percentuale si muove.
  • count — tutto ciò che fa list, e ogni file non misurato conta inoltre contro l'esecuzione come file non coperto per le sue righe di codice, così la barra di stato, le soglie, i badge, la cronologia, ogni esportazione e la vista Test Coverage mostrano il numero più basso. Il file è disegnato come non misurato ovunque compaia, le sue barre nel gutter dicono «non misurato» anziché «mai eseguito», e il controllo di discrepanza lo lascia in pace — non c'è alcuna misurazione che il suo contenuto possa contraddire.
{
  "fuciniCoverage.unmeasured.mode": "list",
  "fuciniCoverage.threshold.unmeasuredFiles": 0
}

I file di intestazione sono il falso positivo noto in C: hanno la famiglia di estensioni dell'esecuzione e nessun tracefile ne nominerà mai uno, perché da solo non compila in nulla. fuciniCoverage.unmeasured.exclude lascia quindi fuori **/*.h, **/*.hpp, **/*.hh, **/*.inl e **/*.d.ts per impostazione predefinita, nella stessa sintassi glob di fuciniCoverage.ignore; aggiungi un port per una piattaforma che qui non viene compilato, o degli stub generati, ed escono dall'elenco, dal conteggio e dallo stato della barra di stato. Neppure un file nominato da ignore viene mai detto non misurato — lasciarlo fuori era lo scopo. threshold.unmeasuredFiles è predefinito a -1, che non controlla; 0 fallisce nel momento in cui un qualsiasi file del tipo dell'esecuzione non è mai stato caricato da un test, e si applica solo mentre unmeasured.mode è list o count.

13. Report HTML

  • Generate Full HTML Report — un report multi-pagina, auto-generato, per directory. L'output va in htmlReport.outputDir, o nell'archivio globale dell'estensione se non impostato.
  • Open Annotated Source — una vista annotata per un singolo file. Punta externalHtmlReport.dir a una directory llvm-cov show --format=html pre-costruita per usare quelle pagine invece del renderer integrato.
  • Export Fucini JSON — il modello normalizzato completo per i tuoi strumenti.
  • Export Coverage Report... — l'esecuzione come CSV (per file o per funzione), riepilogo Markdown, file di trace LCOV, XML Cobertura, SARIF, o badge SVG autonomo per il vostro README. Raggiungibile anche dal pulsante accanto a Generate Full HTML Report nella vista Covered Files. Tutto tranne i CSV perde informazioni — MC/DC, regioni e istanziazioni non trovano posto in LCOV, Cobertura o SARIF — perciò Fucini JSON e i CSV restano i formati che portano ogni metrica.
  • Copy Uncovered Lines — un riepilogo Markdown di ogni lacuna, pronto da incollare in una PR.

In Visual Studio. Il gruppo Reports di Tools → Coverage Studio: Show Annotated Source apre il documento attivo come pagina nell'area dei documenti — ogni riga nel suo colore, i rilievi accanto — che scorre con l'editor in entrambe le direzioni; Open HTML Report scrive il report a pagina singola in htmlReport.outputDir (o %LOCALAPPDATA%\Fucini\CoverageStudio\html-report) e apre il browser; Generate Full HTML Report vi scrive l'indice per cartella e la pagina per file; Export Coverage Report… offre gli stessi otto formati e chiede dove salvare; Generate Coverage Badge scrive il badge dove dice badge.outputPath, dopo ogni caricamento con badge.autoUpdate. La pagina annotata ha bisogno di WebView2, come la finestra Coverage; i report su disco no.

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).
In Visual Studio: Show Annotated Source — il file come pagina nell'area dei documenti, accanto all'editor.
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).

Sorgente annotato rispetto al sorgente semplice

Open Annotated Source sostituisce la scheda attiva con una webview di copertura a colori per quel file, nella stessa colonna; Open Annotated Source to the Side fa lo stesso ma in una vista divisa, così sorgente e vista annotata stanno fianco a fianco. Per passare invece dall'uno all'altro sul posto — utile su schermi piccoli dove una divisione rende ogni riquadro troppo stretto — usa Toggle Annotated Source: scambia la scheda attiva tra le due viste, ricordando quale stai visualizzando. Dall'interno della vista annotata stessa, Show Source torna direttamente all'editor normale per quel file.

L'HTML che vedi effettivamente dipende da externalHtmlReport.dir: se è impostato ed esiste già una pagina corrispondente al file attivo (llvm-cov organizza le pagine per file come <nome-repo>/<percorso-relativo>.html, quindi la cartella con il nome del repository del report non richiede mai configurazione), viene mostrata quella pagina generata dalla toolchain al posto del renderer integrato — i suoi link/foglio di stile locali vengono riscritti per funzionare all'interno della webview, e contiene dettagli che la vista integrata non riproduce (viste di espansione MC/DC, evidenziazione delle regioni, riepiloghi per directory). Nessuna pagina corrispondente per quel file, o impostazione lasciata vuota? Viene allora usato il renderer integrato. L'estensione si limita a leggere questa directory — non vi scrive mai.

Un badge di copertura per il README

Generate Coverage Badge scrive un SVG in stile shields per l'esecuzione attiva nello spazio di lavoro — badge.outputPath, predefinito coverage-badge.svg, relativo alla cartella dello spazio di lavoro o assoluto, con le stesse variabili di ogni altra impostazione di percorso — e propone di aprirlo. È un semplice file nel tuo repository, così un README lo incorpora senza alcun servizio dietro, senza andata e ritorno da shields.io, e funziona anche in un repository isolato dalla rete:

![coverage](coverage-badge.svg)

coverage: 83%

badge.metric sceglie cosa mostra il badge: lines (etichettato coverage), branches, mcdc o weighted, lo stesso punteggio composito che mostra la barra di stato, etichettato score. Un'esecuzione senza dati per la metrica scelta riceve un n/a grigio anziché uno 0% rosso. Il colore segue i tuoi livelli di colorScale.*: lowColor sotto lowThreshold, midColor fino a highThreshold, highColor da lì in su. Con badge.autoUpdate attivo, il badge viene riscritto dopo ogni caricamento riuscito, in silenzio, e il canale di output registra ogni scrittura come [FUCINI_BADGE] — disattivato per impostazione predefinita perché scrive nello spazio di lavoro a ogni caricamento. Fai il commit dell'SVG insieme al codice e l'immagine sulla pagina del repository segue il numero nell'editor.

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

14. Cronologia e tendenze

Abilita history.enabled per persistere localmente le esecuzioni (mantenendone history.retention). Otterrai quindi una freccia di tendenza (▲/▼) nella barra di stato, il grafico della tendenza nella vista Coverage e due comandi di confronto: Compare with Last Run e Compare Two History Runs, ciascuno che produce un diff di regressione/miglioramento per file.

In Visual Studio. Ogni caricamento viene confrontato con il precedente: un triangolo nel margine su ogni riga che ha iniziato o smesso di essere eseguita (sinceLastRun.enabled), la tendenza accanto al punteggio nella barra di stato, e Compare with Last Run per i file i cui numeri si sono mossi. Con history.enabled le esecuzioni vengono conservate sotto %LOCALAPPDATA%\Fucini\CoverageStudio\history, history.retention di esse, così il confronto sopravvive a un riavvio, il grafico della tendenza ha qualcosa da disegnare, e Compare Two History Runs… ne sceglie due qualsiasi.

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).

Il grafico della tendenza

Sotto la barra degli strumenti della vista Coverage, con due o più esecuzioni salvate, la coverage di riga della cronologia come una linea, dalla più vecchia alla più recente, le ultime trenta: un punto per esecuzione che al passaggio del mouse dice la sua data e la sua cifra, e l'ultima cifra accanto con una freccia per la direzione dalla prima. La scala verticale è l'intervallo delle esecuzioni stesse, così un team a 92–94% vede il movimento invece di una linea piatta sotto il 100. Entrambe le edizioni lo disegnano dalla stessa cronologia.

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 tendenza: un punto per esecuzione salvata, l'ultima cifra accanto.
Visual Studio: the trend line under the Coverage window toolbar, the last figure 68.25%
In Visual Studio: l’andamento sotto la barra degli strumenti della finestra Coverage, l’ultima cifra 68.25%.

Sessioni di coverage

Una sola esecuzione dei test raramente copre tutto ciò che una modifica ha toccato: i test unitari sono girati qui, la suite di integrazione là, un giro nell'interfaccia con la coverage attiva da un'altra parte. Start Coverage Session trasforma i caricamenti che seguono in una sola somma — ogni esecuzione si aggiunge alla precedente riga per riga come unione, una riga che una qualsiasi di esse ha eseguito è coperta e i conteggi si sommano — così il gutter, l'albero e il punteggio mostrano ciò che tutte insieme hanno raggiunto. L'esecuzione sullo schermo, se ce n'è una, è la prima della sessione. Una barra sopra l'albero dice quante esecuzioni da quando e termina la sessione; End Coverage Session fa lo stesso, e il caricamento successivo sta di nuovo da solo. In Visual Studio una sola voce sotto Tools → Coverage Studio avvia la sessione e, spuntata, la termina.

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).
Una sessione di due esecuzioni: la seconda aggiunta alla prima, la barra sopra l'albero che le conta.
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
In Visual Studio: Start Coverage Session, e una seconda esecuzione sommata alla prima — la barra conta due esecuzioni, le righe salgono da 50.79% a 68.25%.

La baseline CI: dove sono rispetto a main?

Compare with Last Run risponde a cosa ha fatto la vostra ultima modifica; prima di una pull request la domanda è dove state rispetto a main, e la risposta sta sul server di build. baseline.report indica il report che pubblica la build del ramo main, e ogni caricamento viene confrontato con esso: la scheda della barra di stato porta il delta in una riga — vs CI baseline: 84.20% → 85.10% (+0.90%), 3 file(s) moved — e Compare with CI Baseline elenca i file che si sono mossi, file per file, con le stesse parole di Compare with Last Run. In Visual Studio il comando è sotto Tools → Coverage Studio e scarica o legge il report quando lo chiedete. Tre modi per indicarlo, in .vscode/settings.json:

  1. Un URL servito dalla CI. GitLab tiene gli artefatti dell'ultimo job di un ramo a un indirizzo stabile; il token resta fuori dal file delle impostazioni grazie a ${env:…} in 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 con Authorization: Bearer ${env:TC_TOKEN}. L'URL viene scaricato e messo in cache esattamente come un URL di coverageFile.paths (ETag, remote.refreshMinutes).
  2. Un file che la pipeline ha copiato su una condivisione — un percorso assoluto come \\build\drops\app\main\coverage.cobertura.xml.
  3. Un artefatto scaricato tenuto sotto la cartella, diciamo ci/main.lcov.info (mettete la cartella in .gitignore) — un percorso relativo alla cartella.
{
  "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}"]
}

Va bene qualunque formato il lettore conosca. Un percorso che la CI ha scritto relativo al suo checkout — src/Billing/Invoice.cs, come lo scrive Coverlet sul runner — viene collocato sotto questa cartella prima del diff, così incontra il file che l'esecuzione locale ha risolto; un percorso assoluto di un'altra macchina non corrisponde a nulla, quindi fate scrivere alla pipeline percorsi relativi. Una baseline che non si può scaricare o leggere è una riga nel riquadro Output, mai un caricamento fallito.

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 baseline CI: il delta sulla scheda, e i file che si sono mossi rispetto a 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
In Visual Studio: Compare with CI Baseline — istruzioni e rami rispetto al report dei test unitari, e il file che è cambiato.

Un artefatto è uno zip, e viene letto anche quello. GitHub e GitLab consegnano un artefatto come archivio, qualunque cosa vi sia stata messa. Indicate il report al suo interno dopo un #: il membro viene trovato dal suo percorso o dalla parte finale di esso; senza # è l'unico file dell'archivio, o il suo unico file che sembra un report, e dove ce ne sono più d'uno il riquadro Output li nomina. Lo stesso vale per uno zip che avete scaricato (ci/artifact.zip#lcov.info) e, in VS Code, per un URL in coverageFile.paths. Il token va al server per cui è stato impostato e non oltre: il reindirizzamento verso lo storage che contiene l'archivio viene seguito senza di esso.

{
  "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. Per gli agenti IA: la coverage sullo schermo

Un agente che scrive test può eseguirli e leggere una percentuale. Ciò che non può fare da solo è chiedere ciò che l'editor sa: quali righe di questa funzione non sono mai state eseguite, quale lato di quale ramo, quali test raggiungono una riga, se il diff che ha appena scritto è coperto. Sei strumenti rispondono esattamente a questo, con parole su cui un agente può agire, a partire dall'esecuzione caricata — le stesse esclusioni, la stessa rimappatura, gli stessi numeri dello schermo. Così un agente a cui è stato detto di coprire le lacune di una funzione e un revisore che guarda il gutter parlano delle stesse righe.

StrumentoA cosa risponde
coverage_summaryI totali dell'esecuzione per metrica, e i file più lontani dall'essere coperti. La prima cosa da chiedere.
coverage_gapsCiò che non è mai stato eseguito in un file, in una funzione o in un intervallo di righe: le righe non coperte, gli archi di ramo non presi, le condizioni MC/DC senza la loro coppia, i mutanti sopravvissuti.
tests_for_lineQuali test hanno eseguito una riga, dove il report lo dice — un'esecuzione per test.
patch_coverageLa coverage di un diff — l'albero di lavoro rispetto a un riferimento git, o una patch fornita — e le sue righe mai eseguite.
coverage_deltaCiò che si è mosso dall'esecuzione precedente: i totali, e i file che hanno guadagnato o perso.
test_run_commandIl comando che esegue i test di questo spazio di lavoro con la coverage attiva. Lo esegue l'agente; l'editor ricarica il report da sé.

L'agente di VS Code stesso li ha come strumenti, senza nulla da configurare. Tutti gli altri agenti — qualsiasi client che parli MCP, il Model Context Protocol — vi accedono attraverso un server che l'editor avvia quando mcp.enabled è attivo, in VS Code come in Visual Studio. Copy MCP Server Configuration mette negli appunti la voce del client, così come VS Code e Visual Studio la leggono in un mcp.json; un client che chiama mcpServers la chiave esterna prende la stessa voce sotto quel nome.

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).
In Visual Studio: Copy MCP Server Configuration e il suo messaggio; il token coperto.
{
  "servers": {
    "fucini-coverage": {
      "type": "http",
      "url": "http://127.0.0.1:39217/mcp",
      "headers": { "Authorization": "Bearer …" }
    }
  }
  }
  • È disattivato finché non lo attivate, e ascolta solo su 127.0.0.1: nulla di esterno a questa macchina lo raggiunge.
  • Una chiamata deve portare il vostro token, creato una volta e conservato per voi; senza, la risposta è 401. La configurazione copiata contiene il token: tenetela fuori dal repository.
  • Una chiamata inviata da una pagina web — lo dice nel suo Origin — viene rifiutata, qualunque cosa porti.
  • Legge l'esecuzione caricata e non scrive nulla. L'esecuzione dei test viene indicata, non avviata: l'agente esegue il comando nel proprio terminale.

La porta è mcp.port, 39217 se non impostata. Dove quella è occupata — una seconda finestra, l'altra edizione accanto a questa — viene usata la prima libera successiva, e la configurazione copiata indica quella che funziona. Il riquadro Output dice dove il server ascolta ([FUCINI_MCP]) e perché non ha potuto ([FUCINI_MCP_001]). Ciò che un piano non include — i nomi dei test, il dettaglio MC/DC — gli strumenti lo contano senza esplicitarlo, come fa l'hover.

15. Riferimento comandi

In Visual Studio. Ogni comando è sotto Tools → Coverage Studio, con il nome della tabella senza il prefisso Fucini Coverage:; la barra degli strumenti della finestra Coverage e il menu del clic destro su una riga hanno quelli che vi appartengono, e il menu del clic destro della finestra di codice ha i tre che agiscono sull'editor: Run This Test with Coverage, Show Tests That Ran This Line ed Exclude Selection from Coverage. Quelli con i tasti sono accordi a due pressioni dopo Ctrl+Shift+U: R ricarica, N e P vanno alla riga non coperta successiva e precedente, B alla prossima decisione parzialmente testata, T elenca i test che hanno eseguito la riga, X esclude la selezione — non l'Alt+N di VS Code, perché in Visual Studio Alt e una lettera aprono un menu. Cambiateli sotto Tools → Options → Keyboard, dove sono elencati come Coverage Studio: …. Non in questa edizione: il pannello Test Coverage è un'API di VS Code — l'esecuzione è invece nella finestra Coverage — e Solution Explorer non può mostrare badge. Solo in questa edizione: Run Native Project with Coverage, per un progetto di avvio C++.

In Visual Studio: dove si trova tutto. La finestra Coverage è sotto View → Other Windows → Coverage, e per prima sotto Tools → Coverage Studio, dove sta ogni comando di questa edizione, a gruppi: caricare e ricaricare, sorvegliare il file, le due copie e le schede; Run Tests with Coverage, Run Native Project with Coverage e Collect Coverage in Test Explorer…; Next e Previous Uncovered e le decisioni testate in parte; la colorazione, i contatori di esecuzione e le modalità del margine; la sorgente di coverage di un file, i test che hanno eseguito una riga, un solo test con la coverage, i due modi di escludere; Compare with Last Run, Compare Two History Runs…, Compare with CI Baseline, la sessione di coverage e Check Coverage Thresholds; il gruppo Reports — Show Annotated Source, Open HTML Report, Generate Full HTML Report, Export Coverage Report… e Generate Coverage Badge; poi Getting Started, le soglie di conformità e Licence…. La barra degli strumenti della finestra ha i cinque più usati: Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary e le soglie di conformità; sotto di essi la prospettiva, il filtro e l'ordinamento, e la casella di ricerca; sotto ancora la tendenza. Lasciate il puntatore su una riga dell'albero e premete il suo ⋯ per il menu della riga — aprire il file, aprire la sua cartella, copiarne il percorso, assoluto o relativo, con l'uno o l'altro tipo di barra, escluderlo dalla coverage. All'estremità destra della barra di stato ci sono il punteggio dell'esecuzione e quello del file aperto, con la tendenza dall'ultima esecuzione; Show Coverage Card e Show Coverage Card for This File aprono le schede che li spiegano, le stesse che VS Code mostra quando il puntatore si ferma sul suo elemento della barra di stato.

Visual Studio: Tools → Coverage Studio, open, with every command of the edition
In Visual Studio: Tools → Coverage Studio, con ogni comando di questa edizione.
Visual Studio: View → Other Windows, where the Coverage window is
In Visual Studio: View → Other Windows, dove si trova la finestra Coverage.
Visual Studio: the Coverage window's toolbar — Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary, compliance thresholds
In Visual Studio: la barra degli strumenti della finestra Coverage — Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary e le soglie di conformità.
Visual Studio: a row's menu in the Coverage window — Open, Open Containing Folder, and the four Copy Path entries
In Visual Studio: il menu ⋯ di una riga — aprire il file, aprire la sua cartella, copiare il percorso in quattro forme.
Visual Studio: the status bar's two items, the run's score and the open file's
In Visual Studio: le due voci della barra di stato, il punteggio dell’esecuzione e quello del file aperto.
Visual Studio: the run's coverage card, opened by Show Coverage Card
In Visual Studio: la scheda di copertura dell’esecuzione, da Show Coverage Card.
Visual Studio: the open file's coverage card, opened by Show Coverage Card for This File
In Visual Studio: la scheda del file aperto, da 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).
In VS Code: le schede al passaggio del mouse nella barra di stato per esecuzione e file, poi la barra degli strumenti della vista Coverage, fino al report generato.
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).
In VS Code: il menu della barra di stato — scegliere un file di copertura, eseguire i test con copertura, ricaricare, aprire il report, scegliere la modalità del margine.
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).
In VS Code: Show Worst-Covered Functions, copertura più bassa per prima, con il punteggio CRAP dove il report riporta la complessità.
ComandoCosa fa
Load CoverageIndividua e carica la copertura per il workspace. Alt+Shift+R per impostazione predefinita (Ctrl+Alt+R su macOS).
Pick Coverage FileScegli i tracefile — uno, più d'uno o un altro ogni volta; le scelte si sommano, vengono unite e scritte in coverageFile.paths, così da allora si caricano da sole.
Show Loaded Coverage FilesElenca i tracefile dell'esecuzione attiva. Anche la vista Copertura li elenca, ciascuno con un pulsante di scaricamento e uno di scelta accanto.
Toggle Tracefile WatchControlla le modifiche ai tracefile e ricarica automaticamente.
Run Tests with CoverageRiconosci il test runner, eseguilo con la copertura in un'attività del terminale, carica ciò che scrive e proponi di aggiungere il percorso alle impostazioni.
Run This Test with CoverageIl test sotto il cursore — il metodo, la classe o il blocco describe, oppure il file — eseguito dalla ricetta ristretta a esso, poi caricato come qualsiasi esecuzione. Anche nel menu contestuale dell'editor.
Show Tests That Ran This LineDove il report dice quali test hanno eseguito cosa, elenca i test che hanno eseguito la riga sotto il cursore, dal più attivo in poi, e apre quello scelto dove è scritto.
Run Tests Affected by My Changes…Elenca i test che hanno eseguito una riga che l'albero di lavoro cambia rispetto a testImpact.baseRef, apre quello scelto, oppure esegue solo quelli dove i report provengono da un'esecuzione per test.
Show Minimal Test Set…Il minor numero di test che eseguono ancora ogni riga che la suite esegue, poi i test che non aggiungono alcuna riga propria.
Run App with Coverage…Avvia l'app .NET della cartella sotto dotnet-coverage, e carica ciò che avete percorso quando si chiude.
Run Mutation Tests HereMuta la funzione in cui sta il cursore — o la selezione, o il file — con Stryker.NET, StrykerJS o PIT, e carica il report accanto alla coverage sullo schermo.
Exclude This File from Coverage / Exclude from CoverageMette il file aperto — o, su una riga della vista Coverage, il file o il /** della cartella — in fuciniCoverage.ignore nelle impostazioni della cartella, una volta sola.
Exclude Selection from CoverageScrive l'esclusione dove sta il codice: [ExcludeFromCodeCoverage] sopra un membro .NET, LCOV_EXCL_LINE su una sola riga, LCOV_EXCL_START/STOP attorno a più righe, con il segno di commento del file. Anche dalla lampadina e dal menu contestuale dell'editor.
Start Coverage Session / End Coverage SessionFinché una sessione è attiva, ogni caricamento si aggiunge al precedente come unione; una barra sopra l'albero conta le esecuzioni e la termina.
Next / Previous UncoveredSalta tra le regioni non coperte. Alt+N / Alt+P per impostazione predefinita (Ctrl+Alt+N / Ctrl+Alt+P su macOS).
Choose Editor Gutter Mode...Disattivato, barre solo sulle righe non coperte, barre rosso-ambra-verde, o una mappa di calore dei conteggi nel gutter dell'editor.
Cycle Editor Gutter ModeUn passo avanti fra off, uncovered, coverage e heatmap — Alt+G, o il pulsante della modalità nella barra di stato.
Choose Coverage Source for This File...Quando più di un report caricato misura il file aperto, scegliere da quale vengono i suoi numeri, per il file, la sua cartella o un pattern — scrive una regola coverageFile.sources.
Clear Coverage Source for This File...Togliere le regole coverageFile.sources che si applicano al file aperto.
Toggle Inline Hit CountsMostra o nasconde i conteggi di esecuzione ×N dopo ogni riga — alterna hitCounts.inline.
Show in Test Coverage ViewPubblica l'esecuzione attiva nel pannello Test Coverage di VS Code stesso (anche con testCoverage.publish disattivato) e lo apre.
Suggest Path Remap RuleDeduce la regola pathRemap che farebbe corrispondere allo spazio di lavoro i file senza corrispondenza dell'esecuzione attiva, e propone di aggiungerla.
What Community IncludesOgni limite e ogni funzionalità trattenuta del livello gratuito in un unico elenco, con quanto di ogni limite è stato usato.
Open HTML ReportApri il report statico generato.
Generate Full HTML ReportGenera il report multipagina.
Open Annotated Source / …to the SideVista annotata della copertura di un file.
Toggle Annotated SourceAlterna tra sorgente e vista annotata. Alt+A per impostazione predefinita (Ctrl+Alt+A su macOS).
Show Worst-Covered Files / Folders / FunctionsQuick Pick ordinato dal più basso.
Copy Uncovered LinesRiepilogo Markdown di ogni intervallo non coperto.
Compare Two History Runs / with Last RunDiff di regressione per file — due esecuzioni conservate dalla cronologia, o l'esecuzione sullo schermo rispetto a quella che ha sostituito.
Compare with CI BaselineL'esecuzione caricata rispetto al report che baseline.report indica — quello del ramo main dalla CI, un URL o un artefatto scaricato — file per file.
Show Indirect Coverage Changes…Le righe la cui coverage si è mossa senza che nessuno le modificasse, rispetto alla baseline CI o all'esecuzione precedente, per file.
Check Coverage ThresholdsValuta i controlli di conformità.
Export Fucini JSONEsporta l’esecuzione corrente come Fucini JSON.
Export Coverage Report...Scegliete un formato — CSV, Markdown, LCOV, XML Cobertura, SARIF o un badge SVG — e una destinazione.
Generate Coverage BadgeScrive il badge SVG dell'esecuzione attiva in badge.outputPath, mostrando badge.metric, e propone di aprirlo.
Copy MCP Server ConfigurationMette negli appunti ciò che serve a un client MCP per interrogare la coverage sullo schermo — l'indirizzo del server e il vostro token; con il server disattivato, propone di attivarlo.
Show Status Bar MenuApri il menu delle azioni rapide.
Browse for External HTML Report / Full Report Output Dir…Imposta le directory dei report tramite un selettore.

16. Riferimento impostazioni

La tabella completa e categorizzata delle impostazioni — ogni opzione con il suo valore predefinito — si trova nella pagina Funzionalità e impostazioni. Tutte le chiavi hanno il prefisso fuciniCoverage..

Da notare: fuciniCoverage.language fissa l'interfaccia a runtime di questa estensione (barra di stato, notifiche, suggerimenti, webview) su una lingua specifica, indipendentemente dalla lingua di visualizzazione di VS Code — il valore predefinito è auto e include pacchetti per tutte le 18 lingue supportate. Non modifica le voci della palette dei comandi né le etichette delle impostazioni, che VS Code continua a risolvere dalla propria lingua di visualizzazione.

In Visual Studio. Le stesse chiavi fuciniCoverage.*, lette da fino a quattro file, vincendo l'ultimo: le impostazioni utente proprie di VS Code se VS Code è sulla macchina — lette, mai scritte, così i vostri colori e le soglie vi seguono; %APPDATA%\Fucini\CoverageStudio\settings.json, le impostazioni utente di questa edizione; .vscode\settings.json nella cartella o accanto alla soluzione, così un repository configurato per VS Code è configurato per Visual Studio; e fucini-coverage.json nella radice della soluzione, per un team che preferisce non tenere una cartella .vscode in un repository .NET — lo legge anche l'edizione per VS Code. L'ingranaggio nella barra degli strumenti della finestra Coverage apre una finestra di impostazioni che scrive il file utente o il file della cartella che esiste, come dice il suo selettore Write changes to, e conserva i commenti di un file che modifica. fuciniCoverage.language funziona lì allo stesso modo; i menu seguono la lingua di Visual Studio stesso.

17. Codici di errore

La diagnostica va nel canale di output Fucini Coverage (View → Output → Fucini Coverage), ciascuna con un codice FUCINI_* stabile.

In Visual Studio. Gli stessi codici vanno nel riquadro Fucini Coverage della finestra Output (View → Output) e vengono conservati in %LOCALAPPDATA%\Fucini\CoverageStudio\coverage-studio.log, per la domanda che arriva dopo la chiusura dell'IDE. Tre che capitano: nulla è segnato sebbene il riquadro dica che i file sono stati caricati — la modalità del margine è off, scegliete Show Coverage in Editor; FUCINI_REMAP_001 e una barra informativa — il report nomina percorsi che qui non esistono, e il riquadro suggerisce la regola pathRemap; la finestra Coverage dice che le serve WebView2 — installate il Microsoft Edge WebView2 Runtime, i segni nell'editor non ne hanno bisogno.

CodiceSignificato
FUCINI_PARSE_001Formato di copertura non supportato o non riconosciuto: nessun parser corrisponde al file.
FUCINI_PARSE_010Il file lcov non conteneva record SF.
FUCINI_PARSE_020JSON llvm-cov non valido, data[] mancante o nessun file.
FUCINI_PARSE_030Radice Cobertura <coverage> mancante o XML non valido.
FUCINI_PARSE_040Radice JaCoCo <report> mancante o nessun file sorgente.
FUCINI_PARSE_050JSON Istanbul/SimpleCov non valido o senza file.
FUCINI_PARSE_060JSON SimpleCov non valido o privo dell’array files di primo livello.
FUCINI_PARSE_070Profilo Go senza intestazione mode: o senza blocchi di copertura.
FUCINI_PARSE_080Radice Clover <coverage> o <project> mancante, o nessun file al suo interno.
FUCINI_PARSE_090Radice OpenCover <CoverageSession> mancante, o nessun file al suo interno.
FUCINI_PARSE_100JSON di coverage.py non valido o privo dell'oggetto files di primo livello.
FUCINI_PARSE_110JSON di gcov/gcovr non valido o privo dell'array files di primo livello.
FUCINI_PARSE_120XML GNATcoverage senza elemento <source>, o un index.xml i cui xi:include non sono mai stati risolti — carica invece i file *.xml per sorgente.
FUCINI_PARSE_130Elemento radice <BullseyeCoverage> mancante, o nessun elemento <src> al suo interno.
FUCINI_PARSE_140Elemento radice <CoverageDSPriv> mancante, nessuna tabella <SourceFileNames> con cui risolvere le righe, o nessun dato di riga.
FUCINI_PARSE_150JSON di copertura Xcode non valido, o manca l’array targets di primo livello.
FUCINI_PARSE_160Elemento radice <coverage> di SonarQube mancante, o nessun elemento <file> al suo interno.
FUCINI_PARSE_170JSON Coveralls non valido, o manca l’array source_files di primo livello.
FUCINI_LOADUn caricamento è stato annullato dalla sua notifica di avanzamento; l'esecuzione precedente, se c'era, resta caricata.
FUCINI_REMOTE_001Un URL di coverageFile.paths non si è potuto scaricare, con il motivo; viene caricata l'ultima copia scaricata. Le semplici righe [FUCINI_REMOTE] registrano ogni scaricamento e ogni controllo senza modifiche (304).
FUCINI_REMOTE_002Un URL di coverageFile.paths non ha dato una risposta completa entro 30 secondi — quasi sempre un proxy o una VPN che accetta la connessione e poi tace; viene caricata l'ultima copia scaricata.
FUCINI_REMOTE_003Un URL di coverageFile.paths ha risposto con una pagina HTML anziché con un tracefile — una pagina di accesso, molto probabilmente. La pagina non viene messa in cache e viene caricata l'ultima copia scaricata; controllare il token in remote.headers.
FUCINI_REMAP_002È stata suggerita una regola pathRemap per i percorsi che un caricamento ha lasciato senza corrispondenza, con quanti ne spiega — oppure non se n'è potuta dedurre nessuna, o la regola dedotta è già nell'impostazione e non li ha risolti.
FUCINI_REMAP_003La regola suggerita è stata aggiunta a fuciniCoverage.pathRemap da Apply Suggested Remap e la copertura viene ricaricata.
FUCINI_GITDIFF_001L'estensione Git non è disponibile; la copertura del diff viene saltata e viene mostrata l'intera esecuzione.
FUCINI_GITDIFF_002gitDiff.baseRef inizia con -, cosa che nessun ref git può fare (git lo leggerebbe come un'opzione); la copertura del diff viene saltata e viene mostrata l'intera esecuzione.
FUCINI_IGNOREQuanti file fuciniCoverage.ignore ha lasciato fuori dall'esecuzione, e quali.
FUCINI_UNMEASURED_001I file del tipo dell'esecuzione che nessun test ha caricato, uno per riga.
FUCINI_UNMEASURED_002Più di 5.000 file dello spazio di lavoro corrispondevano a una delle estensioni dell'esecuzione; solo i primi 5.000 sono stati considerati per l'elenco Non misurati.
FUCINI_UNMEASURED_003In modalità count, alcuni file non misurati sono elencati ma non contati: è stato raggiunto il limite di lettura (2.000 file o 50 MB per caricamento).
FUCINI_UNMEASURED_004Un file non misurato non si è potuto leggere; viene elencato ma non contato.
FUCINI_TESTCOVERAGEQuanti file sono stati pubblicati nella vista Test Coverage di VS Code.
FUCINI_BADGEIl badge è stato scritto, con il suo percorso, l'etichetta e il valore.
FUCINI_BADGE_001Il badge non si è potuto scrivere, con il motivo.
FUCINI_WORKSPACEUna cartella è stata aggiunta allo spazio di lavoro o rimossa da esso; la copertura viene rilevata di nuovo.
FUCINI_VARIABLESChe cosa ha risposto ogni ${command:…} nelle impostazioni dei percorsi, o perché è rimasto com’era scritto: il comando non è riuscito, non ha restituito nulla di utilizzabile o l’area di lavoro non è attendibile.
FUCINI_WATCHCosa sta facendo l'osservatore: i percorsi osservati, un file configurato che è comparso, un'attività nominata in watch.reloadAfterTasks che è terminata (con il suo codice di uscita) e ha attivato un ricaricamento, o un percorso sotto files.watcherExclude che viene invece sondato.

18. Privacy

La telemetria è controllata dall'impostazione telemetry.enabled con ambito window. È disattivata per impostazione predefinita. Il riepilogo giornaliero e l'avviso di rimozione richiedono inoltre che il telemetry.telemetryLevel globale di VS Code consenta la telemetria; l'avviso di installazione e alcuni piccoli eventi vengono inviati in ogni caso, e così pure la voce nel registro d'uso di un'installazione in prova o sul livello gratuito Community. Su Community, Unlock Full Features scambia questa telemetria con tutte le funzionalità Pro, MC/DC compresa, per 30 giorni, una sola volta per macchina: disattivala di nuovo e vale il set standard di Community; una licenza a pagamento non ne risente in nessun caso. Vedi l'informativa sulla privacy per sapere cosa viene inviato.

Due cose vale la pena conoscere, perché puoi intervenire su di esse. La prima è il tuo ID del registro d'uso: in prova e su Community l'estensione lo mostra in Show License / Activation e in fondo a What Community Includes, dove selezionando la riga lo copi e si apre l'informativa sulla privacy. Il registro conosce la tua macchina tramite un hash e nient'altro, quindi quell'ID è l'unico modo per chiedere che cosa contiene sul tuo conto, farlo cancellare oppure opporti — indicacelo e troveremo la tua riga; senza di esso non possiamo. La seconda è la registrazione di installazione: una riga scritta la prima volta che un'installazione si segnala e conservata anziché cancellata dopo 90 giorni, con l'identificatore di installazione, il giorno, il luogo a cui è stato risolto il suo indirizzo, le versioni e il sistema operativo — non l'indirizzo stesso, e nulla sul tuo codice. È ciò che ci permette di dire quante installazioni ci sono state negli anni. Entrambe le cose sono descritte per esteso nell'informativa sulla privacy, ed entrambe vengono cancellate se lo chiedi.

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 fine di What Community Includes: come vengono conteggiati i limiti e la riga che ti consegna il tuo ID del registro d'uso.

19. Valutazione e attivazione

Fucini Coverage Studio è distribuito come anteprima di valutazione. Al primo avvio ti viene chiesto di accettare di valutarlo e la prova inizia: tutte le funzionalità sono disponibili durante una prova di 14 giorni, contati dal primo utilizzo su quell'installazione. Non c'è una data fissa dopo la quale qualcosa smette di funzionare.

Dalla versione 2.2026.2 la prova di una nuova installazione inizia non appena l’estensione ha raggiunto una volta il server delle licenze; fino ad allora funziona al livello Community e lo dice. In un container di sviluppo o in un Codespace non inizia alcuna prova: un codice di abbonamento, una chiave o il pass di 7 giorni sblocca lì l’insieme completo.

Alla fine della prova non viene bloccato nulla: l'estensione passa al livello gratuito Community. Per riavere il set completo, attiva: l'attivazione si collega al server delle licenze e applica automaticamente la chiave restituita, senza e-mail e senza chiavi da copiare a mano:

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. Esegui Fucini Coverage: Show License / Activation (raggiungibile anche dalla barra di stato una volta scaduta la prova o la chiave) e fai clic su Request License… (oppure Request Renewed Key… se hai già attivato).
  2. Conferma la richiesta. La chiave viene emessa automaticamente e i tuoi dati di contatto di una richiesta precedente vengono riutilizzati anziché richiesti di nuovo.
  3. Fatto. La chiave di attivazione viene generata e scritta automaticamente in fuciniCoverage.license.key. La barra di stato passa dalla prova a una licenza attivata in un attimo.

La via manuale in un’immagine: apri il pannello della licenza, scegli Enter Key, incolla la chiave ricevuta per e-mail e il banner passa a «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).

Se la richiesta automatica dovesse fallire (nessuna connessione, problema del server): esegui Fucini Coverage: Copy Activation Request Code, invialo tramite la pagina dei contatti o a info@fucini.consulting, e incolla la chiave FCK1.… che ricevi in risposta con Fucini Coverage: Enter Activation Key (oppure direttamente in settings.json):

{ "fuciniCoverage.license.key": "FCK1.…incolla qui l'intera chiave…" }

Il nome dell'impostazione è fuciniCoverage.license.key (ambito utente/globale). La chiave è vincolata alla tua macchina e all'utente del sistema operativo, può avere una scadenza e può abilitare o limitare singole funzionalità e limitare i caricamenti di coverage al giorno. Se mostra “invalid for this machine”, richiedi una nuova chiave da questa installazione: una chiave emessa per un'altra macchina non sarà mai valida qui.

In Visual Studio. In quell'edizione non c'è un livello gratuito: senza un abbonamento non viene letto nulla. Con un abbonamento, il piano decide lì ciò che decide in VS Code — una funzionalità che il piano non include viene trattenuta, e il suo comando lo dice invece di eseguirsi. Anche lì vale la versione più vecchia che il server delle licenze supporta ancora: una build precedente viene avvisata una volta al giorno, con la data in cui smette di funzionare, e continua a funzionare fino ad allora. Essere offline non ferma mai una build.

Il livello gratuito Community: una quota settimanale

Community non smette mai di mostrare la copertura. I margini, il righello di panoramica, i suggerimenti al passaggio del mouse, CodeLens, la vista Coverage, la modalità watch, la copertura del diff e la cronologia non vengono conteggiati affatto, e il caricamento di un tracefile tramite comando ha come unico limite 25 al giorno. Ciò che viene misurato è l'output: cinque alla settimana ciascuno per l'apertura del report HTML, l'esportazione, il confronto tra due esecuzioni, la verifica delle soglie e la visualizzazione del sorgente annotato in loco.

La settimana è tua, non del calendario: inizia con il primo utilizzo e finisce sette giorni dopo. Quando una quota è esaurita, il messaggio indica l'azione e il giorno in cui torna disponibile, e dopo quell'unico messaggio ne parla soltanto la barra di stato. Fucini Coverage: What Community Includes elenca ogni quota con quanto è stato usato e quando si azzera, prima ancora che tu ne raggiunga una.

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).

Tre dettagli appartengono ai piani a pagamento, mentre i relativi risultati restano gratuiti: Community contrassegna ogni riga che ha mutanti sopravvissuti e dice quanti sono, ma non che cosa ha modificato ciascun mutante; dice quanti test hanno eseguito una riga, ma non i loro nomi; e mostra il Max CRAP di un'esecuzione, ma non l'elenco in classifica 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).

Se usavi già Community quando è arrivata la quota settimanale (0.2026.83), i tuoi limiti precedenti restano validi per 30 giorni; ti viene comunicato una sola volta, con la data. I contatori sono conservati sul tuo computer — nell'archivio proprio di VS Code e in ~/.fucini-coverage/, così un nuovo profilo VS Code prosegue la stessa settimana — e non vengono mai inviati da nessuna parte.

Il pass di 7 giorni

Non sei pronto per un abbonamento? Un pass di 7 giorni è tutto ciò che offre Pro per una settimana, pagato una volta sola: nessun rinnovo e niente da disdire. Acquistalo nella pagina dei prezzi (il messaggio mostrato a un limite di Community ha un pulsante apposito) e il codice di attivazione arriva via email.

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. Esegui Fucini Coverage: Enter Subscription Code — esiste sia nell'edizione Community sia in Pro.
  2. Scegli Pro e incolla il codice FCB1-… ricevuto via email.
  3. Tutto qui. La chiave viene emessa e applicata per te, e funziona offline. La settimana decorre dal pagamento, quindi attiva il pass quando lo acquisti. Al termine, l'estensione torna da sola a Community e continua a mostrare la copertura.
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).

In Visual Studio. Lo stesso codice attiva Fucini Coverage Studio per Visual Studio, 2022 e 2026: aprite Tools → Coverage Studio → Licence…, incollate il codice, scegliete il piano a cui si riferisce e premete Activate. La finestra Coverage mostra allora Activated sopra l’albero; aperta con la sua freccia, la riga mostra la data fino alla quale la chiave è valida e un pulsante verso il vostro account. Una macchina è un posto: attivate VS Code o Visual Studio, e l’altro editor sulla stessa macchina segue da sé — Visual Studio legge la chiave di VS Code e VS Code quella di Visual Studio —, così nulla viene inserito due volte e nessun secondo posto viene occupato. Entrambi tengono in vita una chiave allo stesso modo: Pro Plus, Business ed Enterprise si registrano due volte al giorno, e una chiave Pro viene rinnovata nella settimana prima della scadenza.

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

Passare a un nuovo computer e gestire i posti

Una chiave è legata a una macchina, quindi un computer nuovo ne richiede una nuova — e il tuo abbonamento paga solo le macchine che dichiara. Libera tu stesso quella vecchia: accedi a gestisci il tuo abbonamento, individua il posto che non usi più, scegli Free up e attiva la nuova macchina con lo stesso codice. Lʼacquisto di Pro non ti invia alcuna password: il tuo account esiste, semplicemente non ne ha ancora una, quindi la prima volta usa imposta o reimposta la password con lʼindirizzo con cui ti sei abbonato.

Su Business ed Enterprise inviti ogni collega via e-mail dalla stessa pagina. Ognuno riceve un codice di attivazione solo suo e, appena lo usa, il suo indirizzo compare accanto al suo posto: quando qualcuno se ne va vedi qual era il suo e lo liberi per il prossimo. Un invito occupa un posto dal momento in cui lo mandi e scade dopo 14 giorni se resta inutilizzato; ritiralo per riavere subito il posto.

Provare le versioni preliminari

Le novità arrivano su fucini.software prima che sul Marketplace, e puoi chiedere che ti vengano proposte. Apri la vista Coverage, espandi il pannello della licenza e premi Prova le versioni preliminari… — oppure imposta fuciniCoverage.update.preRelease. Da quel momento l'estensione controlla qui un feed preliminare separato oltre a quello ordinario, e propone la più recente delle due.

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).

Le versioni preliminari sono testate, ma sono le build di cui siamo meno sicuri: ti offriresti volontario per trovare ciò che ci è sfuggito. Unendoti ci dici che questa installazione è sul canale, così sappiamo quante persone stanno provando e possiamo dirti cosa è cambiato; uscendo, la prossima versione stabile ti riporta sul percorso abituale. Non c'è sempre una versione preliminare disponibile, e unirsi quando non ce n'è non costa nulla: l'estensione trova un feed vuoto, non ne dice niente e continua a proporre versioni stabili finché non ne viene pubblicata una.

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. Contatti e licenza

Domande, segnalazioni di bug o termini di licenza alternativi — vedi la pagina contatti o scrivi a info@fucini.consulting. Concesso in licenza secondo MIT con una condizione di attribuzione nelle note di rilascio; vedi anche Notice.

21. Sulla riga di comando

Il lettore gira anche senza un editor: npm install -g fucini-coverage, gratis, su Windows, Linux, WSL e macOS. fucini-coverage check coverage/lcov.info --lines 80 è il gate su cui una pipeline fallisce; summary, export, report, badge e compare fanno ciò che fanno i comandi degli editor con quei nomi, e mcp serve i sei strumenti della sezione qui sopra a un agente su un server. Legge fucini-coverage.json, il file delle impostazioni che legge l'edizione per Visual Studio, così le soglie si impostano una volta sola. fucini-coverage help <command> spiega ciascuno; la pagina completa è fucini-coverage su 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).