GUÍA COMPLETA

Guía del usuario

Desde su primer archivo de traza hasta el control de cumplimiento de normas de seguridad — todo lo que puede hacer Fucini Coverage Studio, y exactamente cómo manejarlo.

Descargar el VSIX

1. Introducción

Fucini Coverage Studio convierte los archivos de traza de cobertura que su build ya produce en cobertura de primera clase dentro del editor — en VS Code y en Visual Studio. Lee veinticinco formatos, los normaliza en un único modelo canónico Fucini, combina varias ejecuciones de forma determinista y lo muestra en el propio editor — márgenes, CodeLens, información al pasar el ratón y una vista Covered Files — de modo que no hay un visor aparte por el que abandonar su editor. Las dos ediciones comparten un lector: el mismo informe da las mismas cifras, dígito a dígito, en ambas. Esta guía está escrita desde VS Code; donde Visual Studio difiere, un recuadro In Visual Studio dice cómo.

Está diseñado pensando en flujos de trabajo de seguridad funcional: cobertura MC/DC, cobertura de regiones e instanciaciones de C++, una puntuación compuesta ponderada por seguridad y un veredicto COMPLIANT / NON-COMPLIANT configurable, alineado con los enfoques de IEC 61508, ISO 26262 y 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. Instalación y requisitos

  • VS Code ≥ 1.88 — la versión mínima que admite esta extensión — o Visual Studio 2022 o 2026, Community, Professional o Enterprise (vea el recuadro más abajo).
  • Un archivo de traza de cobertura que su proyecto ya produce (vea §4).

Instale la extensión desde el Marketplace, o desde un archivo .vsix mediante Extensions → ⋯ → Install from VSIX…. La extensión se activa al iniciar y añade un icono Coverage a la barra de actividad.

En Visual Studio. El mismo producto se distribuye como una segunda extensión, Fucini Coverage Studio para Visual Studio, para Visual Studio 2022 y 2026 — Community, Professional y Enterprise. No usa la cobertura de código propia de Visual Studio: en Visual Studio 2022 es una función de Enterprise, así que en Community y Professional es la única cobertura que el IDE mostrará. Instale el .vsix abriéndolo — el VSIX Installer pregunta en qué Visual Studio — o mediante Extensions → Manage Extensions; la extensión se carga al abrir una solución o una carpeta. La ventana Coverage necesita el Microsoft Edge WebView2 Runtime, que Windows 11 y Visual Studio 2026 ya traen; las marcas en el editor funcionan sin él.

3. Inicio rápido

¿Quiere ver cómo funciona antes de conectar su propio proyecto? Descargue el proyecto de demostración (~6 KB — un pequeño proyecto en C con un lcov.info ya preparado):

  1. Descomprímalo donde quiera y luego abra coverage-studio-demo.code-workspace en VS Code (File → Open Workspace from File…).
  2. Instale Fucini Coverage Studio si aún no lo ha hecho (véase el §2 anterior).
  3. El propio .vscode/settings.json del workspace ya apunta al coverage/lcov.info incluido, por lo que los indicadores y la vista Covered Files aparecen en cuanto se activa la extensión, sin necesidad del paso Load Coverage.
  4. ¿Quiere regenerar usted mismo el archivo de traza (por ejemplo, con otro compilador)? Ejecute scripts/gen-coverage.sh (o .ps1 en Windows); consulte el propio README.md del workspace para ver los compiladores disponibles.

En Visual Studio. Abra una solución, o una carpeta (File → Open → Folder, que es como se abre un proyecto CMake) — la demo de arriba se abre como carpeta, y su .vscode/settings.json también se lee allí. Un informe en el lugar que la configuración nombra se carga por sí solo y el panel Fucini Coverage de la ventana Output dice qué archivos; si no, Tools → Coverage Studio → Load Coverage File…, una vez — se recuerda. Abra un archivo fuente y elija Show Coverage in Editor: rojo es una línea que nunca se ejecutó, ámbar una decisión tomada en un solo sentido, y Ctrl+Shift+U, N salta a la siguiente línea sin cubrir. View → Other Windows → Coverage es el árbol con las cifras de cada archivo y una puntuación sobre todos, que la barra de estado muestra para la ejecución y para el archivo en el que está. Tools → Coverage Studio → Getting Started abre estos pasos como una página con un botón para cada uno; la primera vez se abre por sí sola.

  1. Genere un archivo de traza de cobertura con su flujo de pruebas habitual.
  2. Paleta de comandos (Ctrl+Shift+P) → Fucini Coverage: Load Coverage. Con watch.enabled activado (valor predeterminado), un archivo coincidente se carga automáticamente.
  3. Abra un archivo fuente con cobertura: la barra de estado muestra su porcentaje, la vista Coverage se rellena, al pasar el cursor sobre una línea se ve su recuento de aciertos, y la ejecución aparece en el panel nativo Test Coverage. Las barras en las líneas sin cubrir, un mapa de calor de recuentos de aciertos y los recuentos ×N en línea están a un ajuste de distancia (editorGutter.mode, hitCounts.inline).
Covered (green) and uncovered (red) gutters in the editorScreenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).

4. Generación de archivos de traza

Al cargar se detectan automáticamente cualquiera de los siguientes:

Recetas completas para copiar y pegar por compilador — incluidos Swift, Rust, Go, Python, .NET, PHP y más — en la página Recetas de cobertura: 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

El JSON de llvm-cov es la entrada más completa: además de líneas, ramas y funciones, incluye regiones, MC/DC e instanciaciones de plantillas de C++.

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

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

JavaScript / TypeScript — Istanbul / nyc

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

Java — JaCoCo

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

Ruby — SimpleCov

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

Go

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

Python — coverage.py

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

PHP — PHPUnit (Clover)

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

.NET / C# — Coverlet (OpenCover)

dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
FormatoArchivo típicoMétricas adicionales
LCOVlcov.infolíneas, ramas, funciones
llvm-cov JSONcoverage.json+ regiones, MC/DC, instanciaciones
Cobertura XMLcoverage.xmllíneas, ramas
JaCoCo XMLjacoco.xmllíneas, ramas, funciones
Istanbul / nyccoverage-final.jsonsentencias, ramas, funciones
SimpleCov.resultset.jsonlíneas
Clover XMLclover.xmllíneas, ramas, funciones
OpenCover XMLcoverage.opencover.xmllíneas, ramas, funciones
coverage.py JSONcoverage.jsonlíneas, ramas
gcov / gcovr JSONcoverage.jsonlíneas, ramas, funciones
Go coverage profilecoverage.outlíneas
SonarQube genericcoverage.xmllíneas, ramas
GNATcoverage XML (Ada)*.xmllíneas, ramas, MC/DC
BullseyeCoverage XMLcoverage.xmllíneas, condición/decisión
Visual Studio*.coveragexmllíneas, ramas
Coveralls JSONcoveralls.jsonlíneas, ramas
Xcode xccov JSONcoverage.jsonfunciones y totales por archivo — sin datos por línea
gcov plain text*.gcovlíneas, ramas, llamadas a funciones
VectorCASTcoverage.xmllíneas, ramas, pares MC/DC, funciones, llamadas a funciones
Testwell CTC++*.txtlíneas, condición/decisión
Lauterbach TRACE32*.xmlsentencias, decisiones, condiciones, MC/DC, funciones, llamadas, código objeto
EMMA XML (Java)coverage.xmllíneas
UCIS / Aldec UCDB*.xmlsentencias, ramas de decisión
NCover XMLCoverage.xmllíneas, funciones
dotCover DetailedXMLdotCover.xmllíneas, funciones
PIT (mutation)mutations.xmlpuntuación de mutación — sin cobertura
Stryker (mutation)mutation-report.jsonpuntuación de mutación — sin cobertura

Un proyecto C++ nativo, medido desde Visual Studio

En Visual Studio. La cobertura propia de Visual Studio para un proyecto C++ era solo de Enterprise, y el complemento gratuito OpenCppCoverage que cubría ese hueco se retiró. Tools → Coverage Studio → Run Native Project with Coverage toma el proyecto de inicio — un .vcxproj —, pregunta a MSBuild dónde se compila y con qué conjunto de herramientas, y lo mide de una de dos maneras. En el conjunto de herramientas ClangCL, con llvm-profdata y llvm-cov de LLVM en la máquina (el componente C++ Clang tools for Windows de Visual Studio los trae), vuelve a compilar el proyecto en coverage\native\ con -fprofile-instr-generate -fcoverage-mapping, mediante un archivo props que se indica a MSBuild que importe primero — nada cambia en el proyecto —, ejecuta el programa con LLVM_PROFILE_FILE establecido, combina el perfil y exporta coverage\native\lcov.info, exacto hasta la región. En cualquier otro conjunto de herramientas, con OpenCppCoverage instalado, compila el proyecto tal como está — una compilación Debug tiene los PDB — y lo ejecuta bajo OpenCppCoverage, que escribe coverage\native\opencppcoverage.xml. Cada comando va al panel Fucini Coverage, y el informe se carga y se recuerda como el de una ejecución de pruebas. A un proyecto que no se puede medir se le dice por qué y qué instalar. MSBuild 17.8 (Visual Studio 2022 17.8) o posterior, para la pregunta que le hace.

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).
En Visual Studio: Run Native Project with Coverage en un proyecto C++ — la compilación, la ejecución y el editor rellenándose.

5. Carga y detección

De forma predeterminada, la extensión analiza desde la raíz del espacio de trabajo. Afine esto con dos ajustes:

{
  "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"
  ]
}
  • Cada entrada de paths es relativa a defaultLocation (o a la raíz del espacio de trabajo si no se establece).
  • Una entrada que contenga * se busca recursivamente; un nombre de archivo sin comodines solo coincide directamente en la carpeta base.
  • Cuando paths está vacío, la extensión busca primero coverage.json y luego lcov.info, cargando el que encuentre primero.
  • Pick Coverage File usa los archivos que elija en lugar de estas rutas —cada elección se añade al conjunto y todas se fusionan— hasta que los descargue o edite estos ajustes.
  • Variables — todos los ajustes de ruta expanden ${workspaceFolder}, ${workspaceFolderBasename}, ${userHome}, ${env:NAME}, ${command:id} y ${config:section.key}. Una variable que la extensión no conoce se deja tal como está escrita, de modo que una errata aparece en el registro de detección como la ruta que se buscó en lugar de desaparecer. ${command:id} ejecuta antes ese comando — solo en un área de trabajo de confianza y durante cinco segundos como mucho —, de modo que ${command:cmake.buildDirectory} sigue el kit de CMake seleccionado.
  • Entradas URL — una entrada http(s):// se descarga al almacenamiento de la extensión en cada carga y se carga desde allí; la vista Coverage nombra la URL. Cada descarga es condicional (ETag / Last-Modified), así que un artefacto sin cambios no descarga nada, y cuando una descarga falla se carga en su lugar la última copia descargada, con el motivo en la salida. remote.headers añade cabeceras Name: value con las variables expandidas, remote.refreshMinutes vuelve a descargar con un temporizador, y un fragmento #lcov.info nombra el formato cuando la propia URL no termina en un nombre de archivo.
  • Globs de exclusión — fuciniCoverage.ignore descarta archivos enteros (de proveedores, generados, de terceros) de la ejecución mientras se carga, de modo que cada vista, control y exportación cuenta sin ellos; el resultado de la carga dice cuántos se dejaron fuera y la salida los nombra. Los patrones se comparan con la ruta relativa al espacio de trabajo y con la absoluta, y un patrón sin / coincide con un nombre de carpeta o de archivo a cualquier profundidad, como en .gitignore.
  • Espacios de trabajo multirraíz — cada carpeta se detecta por su cuenta: defaultLocation, paths, pathRemap, ignore, watch.* y remote.* se leen por carpeta, de modo que se aplica el .vscode/settings.json propio de la carpeta o su entrada en el .code-workspace, y ${workspaceFolder} en una entrada significa la carpeta de esa entrada. Los archivos de traza de todas las carpetas se fusionan en una sola ejecución, la vista Coverage agrupa los archivos por carpeta, y una carpeta añadida al espacio de trabajo o quitada de él recarga la cobertura por sí sola.
  • Recarga tras una tarea — watch.reloadAfterTasks nombra tareas (un label de tasks.json, o source: name tal como lo muestra la lista Run Task) cuyo final recarga la cobertura, esté o no activado watch.enabled — para compilaciones que el observador no puede seguir. Una entrada absoluta de paths fuera del espacio de trabajo también se sondea, de modo que un archivo que aparece allí se carga.
  • Progreso que se puede cancelar — una carga de diez o más archivos de traza, o de 8 MB o más, se ejecuta bajo una notificación de progreso con un botón Cancelar que nombra el archivo que se está leyendo y la fase; una más pequeña solo hace girar la barra de estado. Cancelar deja cargada la ejecución anterior y lo dice.

Desde 1.2026.6 una entrada absoluta también puede llevar un comodín: ${workspaceFolder}/build/coverage-merged/*.lcov.info carga todos los archivos así de esa carpeta, y ** representa cualquier profundidad. Las carpetas anteriores al primer comodín son donde busca, y se vigilan, de modo que un informe que una compilación escriba allí se carga por sí solo. La edición para Visual Studio lee una entrada así de la misma manera, y desde 1.2026.5 un comodín relativo también se busca allí a cualquier profundidad, como siempre se ha hecho aquí.

Si no hay ningún paths configurado, se carga el primero de los nombres de informe habituales que se encuentre bajo la carpeta base. Primero los cuatro que siempre se han buscado —coverage.json, lcov.info, coverage.out, clover.xml—; después, desde la versión 0.2026.83, jacoco.xml, coverage.xml, cobertura.xml, coverage.cobertura.xml, coverage.opencover.xml y coverage-final.json, y a continuación los lugares donde escriben las configuraciones predeterminadas: coverage/ (nyc, Jest, vitest, PHPUnit, SimpleCov), target/site/jacoco/jacoco.xml (Maven), build/reports/jacoco/test/jacocoTestReport.xml (Gradle) y TestResults/*/coverage.cobertura.xml (dotnet test). Así, un proyecto Java o .NET muestra su cobertura la primera vez que se abre, como siempre lo ha hecho un proyecto lcov.

Desde 1.2026.3 una solución .NET necesita aún menos: la carpeta TestResults/<run>/ de cada proyecto de pruebas está entre los lugares conocidos, no solo la de la propia carpeta del espacio de trabajo, y el <user>_<machine>_<date>.cobertura.xml del recopilador de Microsoft se encuentra junto al coverage.cobertura.xml de Coverlet — así que una solución cuyas pruebas se ejecutaron en el Test Explorer de Visual Studio muestra su cobertura al abrirse por primera vez, cada carpeta de ejecución se carga, y la fusión conserva para cada archivo lo que dice la ejecución más reciente. Y fuciniCoverage.ignore.generated, activado por defecto, deja los archivos de diseñador y los generados — *.Designer.cs, *.g.cs, *.generated.cs, *.razor.g.cs, AssemblyInfo, los usings globales, Migrations/ y obj/ — fuera de cada total, página y exportación antes de que se aplique ignore, de modo que una tabla generada que nadie prueba no le cuesta a la solución su puerta.

En Visual Studio: cobertura tras cada ejecución de pruebas. Ejecute sus pruebas como siempre. Tools → Coverage Studio → Collect Coverage in Test Explorer… coloca un .runsettings con el recopilador Cobertura de Microsoft junto a la solución. Visual Studio lo recoge cuando Tools → Options → Test → Auto detect runsettings files está activado; si no, selecciónelo una vez en Test → Configure Run Settings. Desde entonces cada ejecución escribe un informe bajo el proyecto de pruebas, y la vigilancia de la solución lo carga en cuanto aparece, fusionado con lo que la configuración nombre — tanto desde Test Explorer como desde un terminal o un script. Nada se engancha a Test Explorer, así que Visual Studio 2026 y Microsoft.Testing.Platform funcionan tal como están. Run Tests with Coverage es el comando de VS Code: reconoce dotnet test, vitest, jest, pytest, go, cargo, maven, gradle, phpunit y ctest, ejecuta las pruebas con la cobertura activada en la ventana Output y carga lo que escribieron; un proyecto de pruebas sin coverlet.collector se ejecuta con el recopilador que incluye el SDK de pruebas, y testRun.skipWhenTestsFail mantiene en pantalla la última cobertura buena cuando una ejecución termina en rojo.

Un artefacto de CI tras un token, comprobado de nuevo cada cuarto de hora — el token se queda en el entorno, nunca en 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).

Una recarga es silenciosa a propósito: un diálogo tras cada compilación es una pregunta con una sola respuesta. Lo que no es silencioso es el icono Coverage: mientras la vista no esté delante de usted, lleva el número de tracefiles vueltos a leer, y su información sobre herramientas los nombra. Abra la vista y la cuenta desaparece.

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

Archivos que nunca deben contar, diga lo que diga de ellos el archivo de traza:

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

Una recarga cuando termina la tarea de pruebas, para una compilación que el observador de archivos no puede seguir — una ejecución que reemplaza un árbol de salida con enlaces simbólicos, un informe en un recurso compartido de red, un paso de cobertura que posprocesa su archivo:

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

6. Fusión de ejecuciones

Cada entrada paths existente se carga y se fusiona en una sola ejecución. La fusión es determinista — el resultado no depende del orden de carga — y un archivo medido por más de un tracefile toma sus números del que tenga la mtime más reciente en disco: la repetición propia de un módulo reemplaza lo que una ejecución más amplia y antigua decía de él, en lugar de sumarse. La vista de Cobertura muestra lo que eso hizo: cada fila de archivo nombra el tracefile del que proceden sus números, la insignia lleva contorno donde esos números anularon un informe más antiguo, cada fila de tracefile sobre el árbol cuenta cuántos de sus archivos fueron anulados o anularon otros, y hacer clic en una fila de tracefile resalta sus archivos en el árbol hasta volver a hacer clic (coverageView.mergedMarks desactiva el contorno y el resaltado).

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

Una ejecución fusionada puede contener más que las seis métricas clásicas, cada una procedente del informe que la mide: llamadas a funciones, código objeto y una puntuación de mutación junto a líneas, funciones, regiones, ramas, MC/DC e instanciaciones. La vista Coverage muestra una columna por cada métrica que la ejecución contiene —y ninguna para las que no contiene— ordenadas por el peso de cada métrica en su puntuación, la más pesada primero y con cualquier anchura: lo que no cabe se desplaza lateralmente en lugar de desaparecer. Arrástrela al panel inferior y se convierte en una tabla. Las tarjetas de la barra de estado, el informe HTML y las exportaciones CSV y Markdown siguen la misma regla: lo que un informe contiene se muestra, y lo que no contiene se omite en lugar de imprimirse como un cero.

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).
En Visual Studio: la ventana Coverage sobre una carpeta con once proyectos — plegada a una fila por proyecto con su barra, luego desplegada, luego un archivo abierto desde ella.

De qué informe procede un archivo

Cuando varios informes cargados miden el mismo archivo, el más reciente se lo queda por completo — lo correcto cuando la nueva ejecución de un módulo sustituye lo que decía una ejecución anterior y más amplia. Es incorrecto cuando los informes miden el mismo código a propósito: entonces el editor salta de uno a otro con cada compilación, y cada uno cuenta solo parte de la historia. coverageFile.sources dice qué hacer en su lugar, por archivo. Tres situaciones lo requieren:

  • Un informe es el mejor. El coverage.json de llvm-cov incluye MC/DC; un gcov.info de GCC de la misma compilación, solo líneas y ramas: elija coverage.json y conserve el otro para los pocos archivos que solo compila GCC.
  • Varias suites de pruebas de una compilación. Las pruebas unitarias, las de integración y las de hardware-in-the-loop escriben cada una un informe; cada uno por sí solo deja fuera líneas que los otros ejecutaron. Combinar, union: una línea está cubierta donde cualquier informe la ejecutó, y los recuentos se suman.
  • Una base de código, dos compiladores. Las mismas fuentes compiladas con clang y con GCC toman caminos distintos por el código específico de cada toolchain — un intrínseco aquí, una alternativa portable allá — y cada informe dice que la otra mitad nunca se ejecutó. Combinar, agree: una línea está cubierta solo donde todos los informes que la miden la ejecutaron, y las líneas en las que discrepan se marcan en verde azulado. Esa es la pregunta que plantea una comprobación cruzada entre compiladores: ¿qué ejercitó realmente cada compilación que entrego?

Rara vez escribirá las reglas a mano. Haga clic con el botón derecho en un archivo de la vista Cobertura y elija Choose Coverage Source... (o ejecute Choose Coverage Source for This File... sobre el archivo abierto): se listan todos los informes que miden el archivo, cada uno con sus propias líneas, ramas y MC/DC, y después Combine them — agree y Combine them — union; elija uno e indique si vale para el archivo, su carpeta o un patrón. Clear Coverage Source for This File... vuelve a quitar la regla. En los ajustes, cada regla es un glob sobre los archivos, un glob sobre el informe (un patrón sin / coincide con el nombre de archivo del informe, {a,b} nombra varios) y, para combinar, "combine": "agree" o "union". Decide la primera regla cuyos archivos coinciden y cuyo informe mide el archivo; a un archivo que solo mide un informe nunca se le quita ese informe. Las ramas, el MC/DC y las regiones de un archivo combinado proceden del informe más rico en ellos. coverageFile.mergeStrategy: "order" resuelve los archivos de los que no habla ninguna regla por el orden de coverageFile.paths en lugar de por las horas.

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

Lo que verá: la fila del archivo en la vista Cobertura nombra el informe del que proceden sus números o, si está combinado, todos los informes y el modo, con ≠ n para las líneas en disputa. El margen y Annotated Source marcan esas líneas en verde azulado y dicen qué informe las ejecutó y cuántas veces. La tarjeta emergente de la barra de estado nombra la fuente del archivo abierto y, para toda la ejecución, las reglas vigentes y cómo se decidieron los demás archivos. El samples/c-cross-check de la demo es el caso de dos compiladores, listo para abrir. Visual Studio también hace todo esto: Choose Coverage Source... en una fila de la vista Cobertura, y Choose y Clear Coverage Source for This File... en Tools > Coverage Studio.

Elegir y combinar fuentes forma parte de los planes de pago. En Community el informe más reciente gana cada archivo, como sin ninguna regla, y una regla en los ajustes se indica como no utilizada en lugar de ignorarse en silencio.

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
En VS Code: Choose Coverage Source... sobre bits.c desde la vista Cobertura — el informe de clang, el de GCC o ambos combinados.
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
En VS Code: de agree a union en dos clics — las líneas en disputa siguen en verde azulado, los números cambian.
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
En Visual Studio: lo mismo desde el menú de una fila de la vista Cobertura — los informes, luego hasta dónde llega la regla, luego el archivo cargado de nuevo.
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
En VS Code: bits.c, clang y GCC combinados con agree — la fila indica ≠ 4, y las cuatro líneas que solo ejecutó una compilación están en verde azulado.
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
El mismo archivo combinado con union: toda línea que ejecutó cualquiera de las dos compilaciones está cubierta, así que bits.c alcanza el 100% de sus líneas — y las líneas en las que las compilaciones discrepan siguen en verde azulado.
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
Annotated Source nombra la combinación bajo el título, y cada fila en verde azulado, cuántas veces la ejecutó cada informe.
The status bar's hover card for bits.c, ending with the coverage source: both reports, combined by agree, disagreeing on four lines
La tarjeta emergente del archivo en la barra de estado dice de dónde proceden sus números; la de la ejecución cuenta los archivos que decidió cada regla.
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
En Visual Studio: Choose Coverage Source... desde una fila de la vista Cobertura — los mismos informes y las mismas dos formas de combinarlos; la barra de estado nombra la combinación.

7. Remapeo de rutas

La integración continua a menudo registra rutas absolutas de la máquina de compilación que no existen en su estación de trabajo. Reescríbalas con reglas ordenadas:

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

Las reglas se aplican en orden; la primera coincidencia gana por prefijo. Úselo para salvar diferencias de separadores Windows/Unix o para mapear una ruta de contenedor a su copia de trabajo.

Rara vez tendrá que escribir la regla usted mismo. El «se cargó pero no se ilumina nada» más habitual es un archivo de traza cuyas rutas vienen de un contenedor o de un checkout de CI (/build/src/a.c, /home/runner/work/repo/repo/src/a.c, C:\agent\_work\1\s\src\a.c) mientras que el espacio de trabajo tiene src/a.c. Cuando una carga deja archivos sin coincidencia, la extensión busca los nombres de archivo en el espacio de trabajo, infiere la regla de prefijo que explica el mayor número de ellos, la registra como [FUCINI_REMAP_002], y el resultado de la carga ofrece Apply Suggested Remap — un clic añade la regla a fuciniCoverage.pathRemap y recarga. Suggest Path Remap Rule ejecuta el mismo análisis bajo demanda desde la paleta. No se escribe nada sin el clic.

Un to puede usar ${workspaceRoot}, que representa la carpeta del espacio de trabajo en la que está el archivo de traza; en un espacio de trabajo multirraíz prueba primero esa carpeta y luego todas las demás que resulten tener el archivo. Las propias reglas se leen por carpeta, de modo que cada raíz de un espacio de trabajo multirraíz puede tener las suyas.

8. Cobertura en el editor

  • Márgenes y regla — de forma predeterminada el propio margen del editor muestra solo hallazgos: barras MC/DC, triángulos de desde-la-última-ejecución, puntos de líneas editadas. editorGutter.mode añade barras solo en las líneas sin cubrir o un mapa de calor de recuentos de aciertos (más abajo); la vista codificada por colores de un archivo entero es Annotated Source.
  • CodeLens de función — % de cobertura sobre cada función; haga clic para saltar a su primera línea no cubierta. Se activa o desactiva con codeLens.enabled.
  • Información al pasar el cursor sobre ramas y MC/DC — pase el cursor sobre una línea de decisión para ver los recuentos de tomado/no tomado por rama y una tabla de vectores por condición. Active una barra de margen coloreada con mcdcGutter.enabled.
  • Avisos de código muerto — las funciones con líneas medibles y cobertura nula se marcan en el panel Problems (deadCode.enabled).
  • Next / Previous Uncovered — salte entre huecos.
  • Barra de estado — un elemento $(dashboard) NN% para toda la ejecución y un elemento por archivo, ambos coloreados según la puntuación compuesta; pase el cursor para ver una tabla completa de métricas.
  • Insignias del Explorador — insignias de cobertura por archivo y por carpeta, con el desglose por métrica al pasar el ratón. Desactivadas de forma predeterminada: actívelas con explorerBadges.enabled.
  • Desde la última ejecución — un triángulo rojo en cada línea ejecutada en la ejecución anterior y no en esta, uno verde para el caso inverso, con la regla de vista general y los recuentos al pasar el ratón.
  • Búferes editados — cada marca, descripción emergente y CodeLens se mueve con el texto al editar, y se retira de una línea reescrita, donde un punto gris dice por qué.
  • Recuentos de aciertos en línea — hitCounts.inline escribe ×12 tras cada línea en la que empieza una sentencia, ×0 incluido: el número que siempre ha estado al pasar el cursor, sin pasar el cursor. Toggle Inline Hit Counts lo alterna; el menú de la barra de estado lo ofrece como Mostrar u Ocultar, según corresponda.
  • Entradas por línea en Problems — problems.perLine pone un diagnóstico de tipo Information, con un subrayado ondulado en el editor, en cada bloque contiguo de líneas que nunca se ejecutaron en un documento abierto (una función muerta de cuarenta líneas es una entrada, no cuarenta) y, como uncoveredAndPartial, en cada línea con una rama nunca tomada. Las entradas siguen a sus líneas mientras edita y desaparecen al cerrar el documento; la entrada por archivo que hay tras problems.enabled no cambia.
  • Tinte de línea — lineHighlight pone un tinte translúcido detrás de las líneas mismas, para lo que marca el margen (uncovered, o heatmap también para las líneas ejecutadas). Una opción propia, para que el margen pueda quedar limpio mientras se tiñen los huecos, o al revés.
  • Regla de vista general — overviewRuler decide la franja de la barra de desplazamiento con independencia del margen: follow (con las barras, como antes), uncovered (siempre, de modo que el margen puede estar desactivado mientras la barra de desplazamiento sigue mapeando los huecos) u off.
  • Qué archivo de traza cubrió una línea — con varios informes combinados, la información al pasar el cursor termina con Cubierto por: y cada informe que cubrió esa línea, incluido el nombre de suite del TN: de lcov; un clic en una fila de archivo de traza en la vista Coverage ilumina las líneas que aportó en cada editor abierto.
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).

Modos de margen del editor

editorGutter.mode decide qué muestra el propio margen del editor sobre la cobertura, además de los hallazgos que muestra siempre. off (el valor predeterminado) es solo esos. uncovered pone una barra en cada línea que nunca se ejecutó y una ámbar en cada línea con una rama nunca tomada, y nada en las líneas cubiertas, de modo que una pared verde no oculte las tres rojas. coverage añade una barra verde en cada línea cubierta, de modo que todo el archivo se lee en rojo, ámbar y verde con los colores de la escala de colores. heatmap añade en su lugar un tono cálido en cada línea ejecutada, más intenso cuantas más veces se ejecutó — muestra cuántas veces se ejecutó una línea, no si está cubierta, así que un archivo al 100% aparece ahí de amarillo a marrón, nunca verde. Choose Editor Gutter Mode... elige uno desde la paleta o el menú de la barra de estado; el botón de modo a la derecha de la barra de estado, o Alt+G, pasa al siguiente con una sola pulsación (statusBar.showModeToggle oculta el botón). Ambos escriben el ajuste. El ejemplo activa a la vez las barras de líneas sin cubrir y los recuentos en línea:

{
  "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
En VS Code: el modo coverage — verde donde una línea se ejecutó por completo, ámbar donde una rama nunca se tomó, rojo donde no se ejecutó nada. El elemento de la barra de estado del archivo nombra el informe del que proceden sus números; el botón de modo a su lado dice Coverage.
Alt+G pressed four times: heatmap, off, uncovered and back to coverage
En VS Code: Alt+G cuatro veces — heatmap, off, uncovered y de vuelta a coverage.
Visual Studio: Gutter: Coverage on Quote.cs, green, amber and red bars beside the hit counts
En Visual Studio: Gutter: Coverage (Red, Amber, Green) en Quote.cs.

El mapa de calor es relativo al archivo. El tono de una línea compara su recuento con el de la línea más caliente del mismo archivo, en una escala logarítmica y en cinco pasos; así, el cuerpo de un bucle que se ejecutó mil veces y una función que se ejecutó dos veces son ambos visibles, en lugar de que uno eclipse al otro, y un archivo en el que todo se ejecutó exactamente una vez queda uniformemente cálido en lugar de uniformemente pálido. En un tema oscuro la gama va del oliva apagado al naranja vivo, y en un tema claro del amarillo pálido al marrón: en ambos casos más color significa más ejecuciones, y el rojo queda reservado para las líneas que nunca se ejecutaron. lineHighlight: "heatmap" coloca los mismos tonos detrás del código como un fondo, y hitCounts.inline escribe el recuento exacto después de la línea.

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

Los colores los elige usted. colorScale.lowColor, midColor y highColor dan el rojo, el ámbar y el verde del margen, de los tintes de línea y de cada porcentaje; heatmap.colors y heatmap.colorsDark contienen los cinco tonos del mapa de calor para un tema claro y uno oscuro, desde la línea que menos se ejecutó hasta la que más. La página de ajustes muestra el resultado antes de guardar nada: bajo Colour scale, una vista previa permanece a la vista mientras las filas se desplazan — el degradado con sus dos puntos de pivote, algunos porcentajes en sus colores, y un pequeño editor claro y otro oscuro pintados en el modo coverage y en el mapa de calor — y se vuelve a pintar en cuanto se elige un color.

{
  "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
En VS Code: dos colores escritos en la página de ajustes — la vista previa se vuelve a pintar cada vez.
Visual Studio: the same settings page and the same colour preview
En Visual Studio: la misma página, la misma vista previa.

La parte de una línea que nunca se ejecutó

Una línea está cubierta o no lo está, y la verdad suele quedar en medio: return x > hi ? hi : x; se ejecutó, pero su rama hi nunca. Con lineHighlight activado, la parte nunca ejecutada de una línea ejecutada se tiñe en el editor, para todos los formatos que incluyen rangos de columnas (llvm-cov, Istanbul, Go, dotnet-coverage): los mismos tramos que marca el código fuente anotado. Solo en las líneas que se ejecutaron: una línea que nunca se ejecutó ya está marcada entera. Una plantilla de C++ cuenta como ejecutada allí donde cualquier instanciación la ejecutó; lo que hizo cada instanciación es lo que informa la métrica de instanciaciones.

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

Qué pruebas ejecutaron esta línea

Algunos informes no solo dicen que una línea se ejecutó, sino qué pruebas la ejecutaron: coverage.py escrito con coverage json --show-contexts y dynamic_context = test_function en .coveragerc, OpenCover recopilado con -coverbytest, y un archivo de traza lcov escrito con una sección por prueba (TN:), cuyas secciones se suman en un solo registro con una prueba por línea. Pase el cursor sobre el inicio de una línea, donde está el contador de ejecuciones, y se nombran las pruebas: abreviadas a clase y método, las cinco primeras por su nombre y el resto como una cifra; el CodeLens de la función dice cuántas pruebas la ejecutaron. Show Tests That Ran This Line — la Command Palette, el menú contextual del editor, en Visual Studio Tools → Coverage Studio o Ctrl+Shift+U, T — las enumera, las más activas primero, y abre la que elija donde está escrita en el espacio de trabajo. Una ejecución de dotnet test no sabe decir qué prueba ejecutó qué; active testRun.perTest y Run Tests with Coverage enumera las clases de prueba y las ejecuta una a una, cada informe etiquetado con su clase, de modo que la información al pasar el cursor, la lente y el comando responden también para .NET. Se conserva por archivo, de modo que sobrevive a una fusión con un informe que no sabe nada de pruebas.

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

coverage run -m pytest && coverage json --show-contexts
Hovering the start of two lines of a Python file: each names the tests that ran it; an uncovered line names noneScreenshot pending — add assets/img/tests-per-line.gif (see SCREENSHOTS.md).
Show Tests That Ran This Line: the caret on a line, the list of tests that ran it busiest first, and the picked test opened where it is writtenScreenshot pending — add assets/img/tests-for-line.gif (see SCREENSHOTS.md).
Show Tests That Ran This Line: la lista, las más activas primero, y la prueba abierta donde está escrita.
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
En Visual Studio: Show Tests That Ran This Line en la línea 62 de Quote.cs — la prueba que la ejecutó, y Go to Test abriéndola.

Aprobado o fallido, en las marcas

Una línea cubierta se ve igual tanto si su prueba pasó como si no. Donde el informe dice qué pruebas ejecutaron una línea y el archivo de resultados del ejecutor dice cómo terminaron, una línea que ejecutó una prueba fallida recibe una barra roja en su inicio y una franja en la regla de vista general; la información al pasar el cursor nombra las pruebas fallidas, y Show Tests That Ran This Line escribe fallida junto a cada una. Cuando una prueba está en rojo, el sitio donde mirar es el código por el que pasó. Los resultados se leen en cada carga de la carpeta de cada informe — cualquier .trx, y los nombres que usan las herramientas que escriben JUnit (TEST-*.xml, junit*.xml, test-results*.xml) — y de testResults.paths, como rutas o globs relativos a la carpeta. Run Tests with Coverage pide a dotnet test un test-results.trx junto al informe, de modo que con testRun.perTest activado no hay que configurar nada. testResults.enabled desactiva esa lectura.

{
  "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).
En Visual Studio: una prueba en rojo — la barra roja en las líneas que ejecutó, la tarjeta emergente que la nombra, y Show Tests That Ran This Line escribiendo failed a su lado.

Las pruebas a las que afecta un cambio

Una ejecución completa responde despacio a lo que Run Tests Affected by My Changes… responde al instante: de todas las pruebas, ¿cuáles pasaron por el código que acabo de editar? Se pide a git el diff del árbol de trabajo respecto a testImpact.baseRef — HEAD por defecto, que es lo que aún no está en un commit; origin/main para todo lo que cambia la rama — y se enumeran las pruebas que ejecutaron una línea modificada, primero la que ejecutó la mayor parte del cambio. Elegir una prueba la abre. Donde los informes proceden de una ejecución por prueba (testRun.perTest), la primera entrada ejecuta solo esas pruebas, cada clase en su propio informe, de modo que el informe de todas las demás clases sigue valiendo y los totales siguen siendo los de toda la suite. Una prueba que solo ejecutó líneas situadas debajo de una inserción o una eliminación también aparece: de lo contrario, su informe nombraría las líneas equivocadas.

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).
En Visual Studio: una edición, Run Tests Affected by My Changes…, la lista con la prueba que ejecutó la mayor parte del cambio en primer lugar, y la ejecución de solo esas.

El menor número de pruebas que siguen ejecutando todas las líneas

Show Minimal Test Set… responde a dos preguntas a partir de las mismas líneas por prueba: qué pocas pruebas seguirían ejecutando todas las líneas que ejecuta la suite — para la ejecución rápida antes de un commit — y qué pruebas no ejecutan ninguna línea que otra no ejecute ya. Las pruebas elegidas van primero, cada una con las líneas que añade y las líneas que solo ella ejecuta; después el resto, cada una marcada como que no añade nada. La elección es la voraz — la prueba que más líneas ejecuta, luego la que más añade a esas —, así que se acerca al conjunto más pequeño y es la misma cada vez. Redundante por líneas no es redundante por lo que una prueba comprueba: una prueba que no añade ninguna línea puede ser aun así la única que comprueba un valor en esas líneas. La lista dice dónde mirar cuando se poda una suite, nunca qué borrar.

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).
En Visual Studio: Show Minimal Test Set… — las pruebas elegidas, y después las que no aportan nada.

Ejecutar esta prueba, con cobertura

Ponga el cursor en una prueba y ejecute Run This Test with Coverage — la Command Palette, el menú contextual del editor, en Visual Studio Tools → Coverage Studio o Ctrl+Shift+U, R — y solo esa prueba se ejecuta con la cobertura activada: el método de prueba en el que está el cursor, o la clase de prueba o el bloque describe cuando está entre métodos, o el archivo cuando está por encima de toda clase. Lo que hay bajo el cursor se lee del texto, así que funciona para C#, VB y F# ([Fact], [Test], [TestMethod] y similares), JavaScript y TypeScript (it, test, describe) y Python (def test_…), sea cual sea el servicio de lenguaje instalado. La receta de la carpeta se acota a ella — dotnet test --filter "FullyQualifiedName~…", jest o vitest <file> -t "…", un id de nodo de pytest — y lo que escribió se carga como cualquier ejecución; un ejecutor que no se puede acotar lo dice, y Run Tests with Coverage las ejecuta todas.

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: una prueba, una ejecución, la clase bajo prueba iluminada.
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)
En Visual Studio: Run This Test with Coverage en un [Fact] — la ejecución en la lista Tracefiles, las líneas sobre los métodos diciendo que una prueba ejecutó el código.

Go y Rust. En un archivo Go, el func TestXxx (o Fuzz…, Example…) en el que está el cursor se ejecuta solo, en su propio paquete y por su nombre exacto — go test ./pkg/calc -run "^TestTotal$" — y fuera de una prueba se ejecuta el paquete del archivo. En un archivo Rust, la función #[test] se ejecuta por su ruta en el crate con --exact; con el cursor en un mod y en ninguna prueba, se ejecutan las pruebas de ese módulo; una prueba de integración bajo tests/ se ejecuta en su propio binario (--test api). A un ejecutor solo se le entregan archivos de su propio lenguaje: un archivo TypeScript en una carpeta Go recibe una frase, no una ejecución de nada.

Cobertura tras cada guardado

Con testRun.onSave activado, guardar un archivo fuente ejecuta las pruebas que lo cubren, con cobertura, un momento después de guardar, y el margen lo sigue. Para una solución .NET, el proyecto del archivo guardado se encuentra a través del grafo de .csproj y solo se ejecutan los proyectos de pruebas que lo referencian — directamente, o a través de otros proyectos —, un dotnet test <project> cada uno; cualquier otro ejecutor ejecuta su receta completa; un archivo que no pertenece a ningún proyecto y que ningún informe mide no ejecuta nada. Varios guardados seguidos son una sola ejecución, y una ejecución ya en marcha no se interrumpe. El resto es como lo hace Run Tests with Coverage: el terminal, el panel Output, el informe cargado. Desactivado por defecto — es un hábito que se elige, no un valor predeterminado que se descubre.

{
  "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).
Cobertura tras cada guardado: editar, guardar, y el margen lo sigue un momento después.
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
En Visual Studio: testRun.onSave activado — Quote.cs guardado, las pruebas se ejecutan solas, la línea sobre el método cambia.

La propia aplicación, con cobertura

Una ejecución de pruebas dice lo que alcanzan las pruebas. Lo que alcanza una persona — al recorrer las pantallas antes de una versión, al repetir los pasos de un cliente — también es cobertura, y Run App with Coverage… la recoge. La aplicación .NET de la carpeta — un Exe, un WinExe, un proyecto web o worker, nunca un proyecto de pruebas; una elección cuando hay varias — se inicia bajo dotnet-coverage de Microsoft en una consola propia, para que se pueda escribir en una aplicación de consola, y se ejecuta hasta que usted la cierra. Lo que recorrió se carga entonces como cualquier ejecución, y en una sesión de cobertura se suma a lo que ejecutaron las pruebas. Cómo terminó la aplicación no cuenta en contra de la ejecución. La herramienta hay que instalarla una vez: 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).
En Visual Studio: Run App with Coverage… — la aplicación de consola, unas entradas, cerrada, y su cobertura cargada.

Los mutantes, y dónde están

Una herramienta de mutación —PIT para Java, Stryker para JavaScript, C# y Scala, Mull para C y C++— modifica su código en pequeños detalles y ejecuta las pruebas contra cada cambio. Un cambio que ninguna prueba advierte es un mutante superviviente: el código se ejecutó y nada comprobó lo que hacía. La puntuación de mutación dice cuántos fueron detectados; desde la versión 0.2026.83, el editor dice dónde están los demás. Una línea que tiene uno lleva una nota detrás (⚑ 2 mutants survived), el texto modificado aparece subrayado cuando el informe indica de qué texto se trataba (Stryker y Mull lo hacen), la regla de vista general muestra una franja, y al pasar el cursor se ve qué se cambió, cuántas pruebas lo ejecutaron y, para los mutantes detectados, qué prueba los detectó.

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

Sobrevivió significa que hubo pruebas que ejecutaron el código modificado y todas pasaron. Sin probar (el no coverage del informe) significa que ninguna prueba ejecuta ese código, de modo que nada habría podido advertirlo. Los mutantes detectados se cuentan al pasar el cursor y nunca se marcan, y los mutantes que nunca fueron una prueba justa —uno que no compilaría— quedan fuera de la puntuación. El código fuente anotado tiene una fila debajo de cada una de esas líneas y un botón Next Mutant (U), y los informes HTML tienen una sección Surviving Mutants que enlaza con la línea. No hay que activar nada, y un proyecto sin informe de mutación no ve nada de ello.

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

¿Lo notaría una prueba? Una ejecución de mutación en el cursor

La ejecución de mutación de un proyecto lleva una hora; la de una función, un minuto. Run Mutation Tests Here ejecuta ese minuto: la función en la que está el cursor — o las líneas seleccionadas, o el archivo — es lo que se le indica mutar al ejecutor de mutación de la carpeta, y su informe se carga junto a la cobertura en pantalla, donde se marcan los mutantes supervivientes. Para C# es Stryker.NET (dotnet tool install --global dotnet-stryker), al que se le indican el intervalo de caracteres y el proyecto de pruebas que referencia el proyecto del archivo; para JavaScript y TypeScript, StrykerJS, al que se le indican las líneas; para Java, PIT con Maven, al que se le indica la clase. Cómo terminó el ejecutor no cuenta en contra de la ejecución: una puntuación por debajo de su umbral es un código de salida, y sigue siendo un informe. Un ejecutor que no escribió nada se señala, junto con lo que necesita tener instalado.

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).
En Visual Studio: Run Mutation Tests Here en una sola función, y los mutantes supervivientes marcados.

La propia vista Test Coverage de VS Code

Con testCoverage.publish activado (el valor predeterminado), cada ejecución cargada va también a la vista Test Coverage nativa del editor — el panel de cobertura del Test Explorer, los porcentajes por archivo que pone en el Explorer y el propio conmutador Show Inline Coverage del editor — como líneas, ramas y funciones, con los detalles cargados bajo demanda, vengan del archivo de traza que vengan y sin ningún adaptador de pruebas de por medio. Show in Test Coverage View publica la ejecución activa y abre el panel diga lo que diga el ajuste; el menú de la barra de estado lo ofrece tras quickActions.showTestCoverage. Desactivado, no aparece ninguna entrada Fucini Coverage en el Test Explorer. Cuando un archivo de traza nombra sus pruebas (las secciones TN: de lcov), cada prueba aparece bajo Fucini Coverage en el Test Explorer y la vista puede filtrar la cobertura de un archivo por prueba.

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

Líneas sin cubrir en el panel Problems

Desactivado de forma predeterminada porque es ruidoso por naturaleza, y solo para los documentos abiertos — una ejecución de dos mil archivos no puede inundar el panel. Independiente de problems.enabled, que se limita a una entrada por archivo:

{
  "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. Cobertura de diferencias

Restrinja las decoraciones a las líneas modificadas respecto a una referencia base de git — ideal para revisar exactamente qué cubrió o no una PR:

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

En Visual Studio. Las mismas dos claves de configuración, leídas de los mismos archivos: la extensión ejecuta ella misma git diff <baseRef> para cada archivo de la ejecución y reduce la ejecución a las líneas que cambió su rama — en el margen, en la ventana Coverage y en las puertas. El panel Output dice qué respondió git cuando no responde nada.

Una puerta para el código nuevo

threshold.newCode es una puerta propia, junto a las que se aplican a toda la ejecución: de las líneas modificadas respecto a gitDiff.baseRef que se pueden medir, el porcentaje mínimo que debe haberse ejecutado. Un proyecto al 62 % en total puede exigir aun así que lo que se escribe hoy esté probado. Se calcula en cada carga sobre toda la ejecución, que sigue en pantalla — gitDiff.enabled es otra cosa: las líneas modificadas en lugar de la ejecución. Check Coverage Thresholds y las entradas de cumplimiento de Problems la dan por fallida en una frase propia: New code 72.00% < 80% (18 of 25 line(s) changed against origin/main ran). Un cambio sin ninguna línea que se pueda medir — comentarios, un README — no hace fallar nada.

{
  "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).
En Visual Studio: Check Coverage Thresholds suspendiendo la puerta del código nuevo, junto a una ejecución que pasa sus propias puertas.

Código nuevo por etiqueta, por autor, por fecha

El código nuevo son, por defecto, las líneas que el árbol de trabajo cambia respecto a gitDiff.baseRef — una rama, un commit o una etiqueta: "v1.4.0" es todo lo posterior a esa versión. Dos ajustes preguntan lo que una referencia de git no puede. gitDiff.author toma parte del nombre de un autor, y el código nuevo son entonces las líneas que git atribuye a ese autor; gitDiff.since toma un día, y son las líneas modificadas por última vez ese día o después, sea cual sea la rama por la que llegaron; los dos juntos, las líneas de ese autor desde ese día. Se obtienen de git blame, archivo por archivo — algo que una ejecución grande notará en cada carga — y ocupan el lugar del diff para la cobertura de diferencias y para la puerta anterior. Una línea que aún no está en un commit cuenta en ambos casos.

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

Cambios indirectos: lo que se movió aunque nadie lo tocó

Un diff dice qué líneas cambiaron; dos ejecuciones dicen qué líneas dejaron de ejecutarse o empezaron a hacerlo. Las líneas que merecen un vistazo son aquellas en las que ambos discrepan: código que nadie editó y que ya no se ejecuta, porque se borró una prueba, porque una rama previa ahora retorna antes, porque cambió un fixture. Una revisión del diff no puede verlas — quedan fuera de él por definición. Show Indirect Coverage Changes… las enumera por archivo, primero el archivo que más perdió, y abre el que usted elija en su primera línea de ese tipo. La ejecución se compara con la línea base de CI donde baseline.report nombra una — que es por la que se juzga una pull request — y, si no, con la ejecución anterior; las líneas que el árbol de trabajo cambia respecto a gitDiff.baseRef, y todo lo que queda por debajo de un punto donde ese cambio desplaza las líneas del archivo, se dejan fuera.

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).
En Visual Studio: Show Indirect Coverage Changes… — un archivo que perdió líneas que nadie editó, tras quitar una prueba entre dos ejecuciones.

10. La puntuación compuesta

En lugar de informar seis números, la extensión los combina en una única media armónica ponderada (WHM). Para métricas con porcentajes pᵢ y pesos wᵢ:

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

Una media armónica está dominada por su término más pequeño, por lo que una métrica débil no puede quedar enmascarada por una perfecta — exactamente la propiedad que se busca en una puerta de seguridad. Pesos predeterminados:

MétricaPesoJustificación
MC/DC4IEC 61508 SIL 3–4 / ISO 26262 ASIL C–D / DO-178C DAL A–B.
Ramas2IEC 61508 SIL 2+ / ISO 26262 ASIL B+.
Condiciones3Entre las ramas y MC/DC (DO-178C, ISO 26262).
Regiones1.5Rutas dentro de una sentencia (p. ej. cortocircuito parcial).
Líneas1IEC 61508 SIL 1+ / ISO 26262 ASIL A+.
Funciones1Control de código muerto.
Instanciaciones0.5Cobertura de plantillas de C++; el alcance más estrecho.
Llamadas a funciones1Puntos de llamada que se ejecutaron (gcov, VectorCAST, Testwell CTC++, TRACE32).
Código objeto0Desactivado salvo que le asigne un peso: engloba la cobertura de sentencias.
Puntuación de mutación0Desactivada salvo que le asigne un peso: no es cobertura.

Ponga cualquier peso en 0 para excluir esa métrica de la puntuación. Las métricas ausentes en los datos (por ejemplo, MC/DC en una ejecución lcov simple) simplemente se omiten.

El código objeto y la puntuación de mutación pesan 0 hasta que usted decida lo contrario (whmWeights.objectCode, whmWeights.mutation). La cobertura de código objeto engloba la cobertura de sentencias, de modo que ponderar ambas cuenta dos veces la misma evidencia; una puntuación de mutación no es cobertura en absoluto: un conjunto de pruebas puede ejecutar todas las líneas y no detectar nada. Aun así, ambas tienen su propia columna y su propio umbral.

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

Cobertura de condiciones

a && b es una decisión —dos ramas— y dos condiciones con cuatro resultados. Un conjunto de pruebas puede tomar ambas ramas sin ver nunca b como falso: la cobertura de ramas es completa y la cobertura de condiciones es de tres sobre cuatro. Ese nivel se sitúa entre la cobertura de ramas y MC/DC en DO-178C e ISO 26262, y desde la versión 0.2026.83 es una métrica propia en lugar de quedar integrada en las ramas: una fila en las tarjetas de la barra de estado, una columna en la vista Coverage, en los informes y en las exportaciones, un peso de 3 en la puntuación (whmWeights.conditions) y una puerta (threshold.conditions; sin puerta en el perfil standard, 100 en 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).

Se lee de las sondas condition de BullseyeCoverage, de una exportación cond de TRACE32 y de GCC 14 compilado con -fcondition-coverage. Un informe que no distingue las condiciones de las decisiones no tiene esa fila, esa columna ni ese peso. Si utiliza Bullseye o TRACE32: las condiciones contaban antes como ramas, por lo que su porcentaje de ramas cambia con esta versión y, con el nuevo peso, también su puntuación compuesta; establezca whmWeights.conditions en 0 para obtener la puntuación tal como era.

GCC 14, línea a línea. -fcondition-coverage hace que gcov diga qué resultado de qué condición falta — la condición 1 nunca verdadera, la condición 0 nunca verdadera ni falsa — y cada condición se marca en su línea y se nombra en la información al pasar el cursor, tanto desde el JSON de gcov como desde su listado de texto (condition outcomes covered 3/6). La métrica está donde están las demás: threshold.conditions le pone una puerta y queda sin juzgar donde una ejecución no tiene esa cifra, Copy Coverage Summary tiene una columna Conditions, badge.metric admite conditions, y el cuadro de búsqueda admite conditions < 80. La cifra de ramas de una función deja fuera los resultados de sus condiciones, igual que la del archivo y la de la ejecución.

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

Complejidad y CRAP

Algunos informes contienen la complejidad ciclomática de cada función: OpenCover (que es lo que escribe Coverlet), JaCoCo, Clover y Cobertura. Cuando es así, la extensión calcula una puntuación CRAP —Change Risk Anti-Patterns— para la función, a partir de esa complejidad y de la cobertura que ella misma midió:

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

Una función sencilla y completamente probada obtiene su propia complejidad y nada más; una compleja y apenas probada obtiene una puntuación de varios cientos. En el ejemplo de C# del proyecto de demostración, Price() tiene una complejidad de 22 y alrededor del 37% de sus líneas cubiertas, lo que da 142.2, mientras que Shipping() tiene una complejidad de 12 y está completamente cubierta, lo que da 12. El límite habitual es 30: una función que lo alcanza o lo supera aparece bajo Riskiest Methods en el informe HTML, empezando por la peor.

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 complejidad y la puntuación figuran en el CodeLens de la función y junto a la función en el código fuente anotado. Max CRAP es la puntuación más alta de cualquier función de un archivo —la peor, no un promedio— y es una columna en la vista Coverage, en el informe HTML y en las exportaciones CSV y Markdown. Es información: no tiene umbral ni peso en la puntuación compuesta. Los informes que no contienen complejidad (lcov, gcov, Istanbul, coverage.py) no tienen CRAP, ni tampoco una columna vacía.

Desde la versión 0.2026.83, C y C++ también la tienen. llvm-cov no informa de ninguna complejidad, así que se cuenta a partir de los datos de ramas que el informe ya contiene: las condiciones escritas en el propio archivo de la función, más uno; es la definición de McCabe, y lo que cuentan las herramientas a nivel de código fuente para .NET y Java. Las condiciones que proceden de una macro de otro archivo —cada assert, por ejemplo— no se cuentan.

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, y qué archivos mostrar

Bajo el árbol de la vista Coverage, Risk hotspots enumera las funciones en las que el código complejo se encuentra con poca cobertura, de peor a mejor, cada una abriendo su archivo en la función. Una función entra por su puntuación CRAP — hotspots.crapThreshold, 30 por defecto, la cifra que propusieron los autores de la métrica — o solo por complejidad ciclomática, hotspots.complexityThreshold, desactivado por defecto; solo los informes que incluyen la complejidad (OpenCover, Cobertura de Coverlet, JaCoCo, llvm-cov) tienen alguno. Community ve el recuento y la peor puntuación; la lista ordenada es Pro. Junto a la ordenación, un segundo desplegable dice qué archivos muestra el árbol — todos, los archivos con huecos, los archivos sin probar o los archivos cambiados desde la última ejecución; las carpetas siguen a sus archivos y conservan sus propios números. Ambos están también en Visual Studio, en la ventana 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).
En Visual Studio: la ventana Coverage, con el filtro junto a la ordenación y los Risk hotspots bajo el árbol.

Espacios de nombres, clases y métodos

Para un informe .NET que nombra sus clases — Cobertura y el coverage.cobertura.xml de Coverlet, OpenCover — un tercer desplegable, Folders / Namespaces, dibuja la misma ejecución como espacios de nombres, clases y métodos: el número de un espacio de nombres es la suma de los de sus clases, el de una clase la suma de los de sus métodos, exactamente como el de una carpeta es la suma de los de sus archivos, con la misma ordenación y el mismo filtro. Una fila de método abre el archivo en el método; una clase declarada sin espacio de nombres está bajo (no namespace). La elección se escribe en coverageView.perspective; una ejecución que no trae nombres de clases no tiene desplegable y muestra sus carpetas. En Visual Studio la ventana Coverage tiene el mismo desplegable.

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 misma ejecución por espacio de nombres, clase y método.
Visual Studio: the Coverage window with the dropdown on Namespaces, the Pricing namespace open on Customer and its methods
En Visual Studio: la ventana Coverage por espacio de nombres, clase y método.

Bajo los botones y los desplegables, un cuadro de búsqueda. Una palabra conserva las filas cuyo nombre o ruta la contiene — cada palabra escrita tiene que estar ahí; una comparación conserva las filas cuya cifra la cumple — < 80% sobre la puntuación, lines >= 90, branches = 0, functions != 100, mcdc < 50 — e invoice < 80 exige ambas cosas. Las filas de método de la perspectiva de espacios de nombres y los risk hotspots se buscan junto con los archivos, de modo que una función se encuentra donde la tiene la ejecución. El árbol se filtra mientras escribe, en la página, sin redibujar; una carpeta que contiene una coincidencia se abre para ella y se vuelve a cerrar cuando el cuadro se vacía; Esc lo limpia. El mismo cuadro, la misma gramática, en 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).
Buscar en el árbol: un nombre, y luego lines < 80.

El árbol sigue al editor

El archivo que está mirando se resalta en la vista Coverage, las carpetas que lo contienen se abren y su fila se desplaza hasta quedar a la vista — ya no hay que buscar en el árbol el archivo que ya está abierto. Por lo demás, el árbol conserva su posición de desplazamiento, y nada se vuelve a dibujar. coverageView.followActiveEditor, activado por defecto, lo desactiva para quienes prefieran dejar el árbol donde lo pusieron.

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).
En Visual Studio: al cambiar de documento, la fila resaltada de la ventana Coverage lo sigue.

11. Control de cumplimiento

El veredicto COMPLIANT / NON-COMPLIANT (que se muestra en la vista de fuente anotada, el informe HTML y ambas ventanas emergentes de la barra de estado) se determina mediante umbrales por métrica y un modo:

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).
ModoCOMPLIANT cuando…
strict (default)cada métrica controlada individualmente alcanza su propio umbral: sin concesiones.
whmla única puntuación compuesta ponderada alcanza threshold.weighted.
bothse cumplen el control ponderado Y el control estricto por métrica.
eitherse cumple el control ponderado O el control estricto por métrica (el más laxo).

Un umbral de 0 desactiva esa puerta, y una métrica que el informe no contiene nunca se juzga. Lo que representa un umbral que usted no ha establecido lo decide el perfil que figura más abajo. Ejecute Fucini Coverage: Check Coverage Thresholds para evaluar bajo demanda.

En Visual Studio. Tools → Coverage Studio → Check Coverage Thresholds juzga la ejecución contra las mismas claves threshold.* y lo dice en la barra de estado y en el panel Output; con compliance.diagnostics, problems.enabled, problems.perLine o deadCode.enabled los hallazgos se sitúan en la Error List junto a los del propio compilador — una entrada por archivo por debajo de una puerta, una por rango sin cubrir, una por función que nunca se ejecutó — cada una abriendo su archivo en la línea.

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).
En Visual Studio: Check Coverage Thresholds, con los hallazgos en la Error List.

Perfiles de umbrales

threshold.profile decide qué valor representa un umbral que usted no ha establecido. standard, el valor predeterminado desde la versión 0.2026.82, es lo que se le puede exigir a un proyecto corriente que no está relacionado con la seguridad funcional. safety pone todas las puertas en 100: lo que pide un caso de seguridad, y exactamente lo que se distribuía hasta la versión 0.2026.81.

Métricastandardsafety
Líneas80100
Funciones80100
Regiones75100
Ramas70100
Puntuación compuesta75100
MC/DC, instanciaciones, llamadas a funciones, código objetosin puerta100
Condicionessin puerta100
Puntuación de mutaciónsin puertasin puerta

Un umbral que usted sí ha establecido prevalece sobre cualquiera de los perfiles. El ejemplo fija la puerta de las ramas en 90 y todo lo demás en 100; para exigir 100 solo a algunas métricas, permanezca en standard y establezca esas usted mismo. Una salvedad se deriva de cómo funcionan los ajustes: un valor igual al predeterminado de fábrica no se puede distinguir de la ausencia de valor, de modo que con safety un umbral escrito exactamente con su cifra estándar —80 para las líneas, por ejemplo— sigue contando como 100.

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

Si confiaba en los valores predeterminados antiguos, se le juzgará con más indulgencia tras actualizar a la versión 0.2026.82 hasta que seleccione safety. A una instalación que ya se había utilizado antes se le indica una sola vez, con un botón Keep 100% (safety) que escribe el perfil en sus ajustes de usuario; en un proyecto compartido, póngalo también en los ajustes del área de trabajo, para que a todos se les juzgue por igual. Configure Coverage Compliance & Thresholds... muestra el perfil encima de la cuadrícula de umbrales, y su vista previa en vivo juzga con las puertas realmente vigentes. En todas las tarjetas e informes, una métrica cuya puerta está desactivada muestra su cifra con un guion neutro en lugar de una marca de verificación o una cruz.

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. Cobertura de código objeto

Todas las demás métricas aquí se miden desde el código fuente: una herramienta instrumenta su código, la compilación instrumentada se ejecuta y los contadores dicen qué sentencias, ramas o condiciones se ejercitaron. La cobertura de código objeto mide otra cosa: cuánto del binario construido se ejecutó realmente, contado en bytes de instrucciones, observando el flujo de instrucciones en lugar de instrumentar el código fuente. Importa porque un compilador emite código del que ninguna línea de su fuente da cuenta: comprobaciones de límites de arrays, tablas de salto de switch, volcados de registros, sondas de pila, llamadas a rutinas auxiliares de ejecución para división o coma flotante en núcleos que carecen de la instrucción. Es además la única métrica aquí que responde a ¿esto cubre el ensamblador? — el ensamblador escrito a mano nunca se instrumenta y una herramienta basada en la fuente no llega a él. DO-178C es explícito sobre el motivo: en el nivel A, cuando un compilador o enlazador genera código que no es directamente trazable a sentencias del código fuente, el objetivo 6.4.4.2b exige verificación adicional exactamente de ese código generado.

Subsume la cobertura de sentencias: toda instrucción ejecutada provino de una sentencia, así que un 100% de cobertura de código objeto implica un 100% de cobertura de sentencias. Lo contrario no se cumple, y esa asimetría es justamente el motivo de medirla. De ahí se siguen dos cosas. No tiene ningún peso en la puntuación compuesta, porque promediar dos medidas de las mismas ejecuciones cuenta la misma evidencia dos veces; en su lugar se controla mediante fuciniCoverage.threshold.objectCode, un requisito en vez de un peso, que es como lo pide la norma. Y la diferencia es el entregable: una ejecución con 100% de cobertura de líneas y menos del 100% de cobertura de código objeto ha localizado exactamente el código generado por el compilador del que su fuente no da cuenta, por lo que la ficha de cumplimiento dice 312 bytes nunca ejecutados, con 100% de cobertura de líneas en lugar de esconderlo como «94%». Lo inverso —un binario entero dado por ejecutado mientras su fuente no lo estaba— es una contradicción y no una puntuación baja: casi siempre un archivo de traza obsoleto en un lado de una fusión, o nombres de módulos que nunca coincidieron con rutas de archivo. Se informa como hallazgo.

La cobertura de código objeto exige que el binario se ejecute donde puedan observarse sus instrucciones. Hay tres vías y difieren enormemente en coste. Solo la tercera produce cobertura de código objeto; las dos primeras aparecen porque resuelven un problema afín que a menudo es el que de verdad conviene resolver.

  1. Una compilación instrumentada, ejecutándose en el destino. Los compiladores cruzados de GCC aceptan -fprofile-arcs -ftest-coverage, así que la instrumentación que funciona en una estación de trabajo funciona en el destino, salvo que un sistema bare-metal no tiene sistema de archivos donde escribir los contadores .gcda, y a menudo no tiene exit() en el que escribirlos. Los contadores viven en RAM de todos modos, así que la solución es volcar esa memoria y reconstruir los archivos fuera del destino; embedded-gcov de la NASA JPL (Apache-2.0) hace exactamente eso, sin sistema de archivos, sistema operativo ni biblioteca C estándar. Esto da cobertura de sentencias, ramas y funciones de una compilación hecha por su compilador cruzado, para su juego de instrucciones, sobre su hardware — no cobertura de código objeto, y el binario medido está instrumentado, por tanto más grande y más lento que el que usted entrega. Cargue el resultado como LCOV, gcovr JSON, gcov JSON o, en una cadena de herramientas anterior a GCC 9, como el listado de texto .gcov.
  2. Un simulador del juego de instrucciones. Ejecute el binario real de destino en un simulador y derive la cobertura de las direcciones ejecutadas: sin hardware, sin instrumentación, sin sonda y, como observa instrucciones, puede producir cobertura de código objeto genuina. El límite es la fidelidad: un simulador modela bien el núcleo y peor los periféricos, así que trate con recelo los resultados de sistema completo salvo que modele su silicio con precisión.
  3. Traza en chip y un depurador. La vía de grado de certificación, y la única realmente no intrusiva: la unidad de traza del núcleo comunica el flujo de instrucciones a un depurador, que lo convierte en cobertura. Nada se instrumenta, el tamaño del código no cambia y la temporización no se altera, que es lo que convierte el resultado en evidencia sobre el binario que realmente entrega. Compruebe el silicio antes de presupuestarlo: en muchas familias de microcontroladores la traza completa solo está disponible en una variante de emulación o desarrollo con un búfer de traza grande y un puerto de traza rápido, mientras que las piezas de producción exponen una unidad de traza reducida cuyo recurso alternativo del fabricante es una traza por software que instrumenta el código y consume tiempo de CPU, eliminando justamente la propiedad por la que se eligió esta vía.

Muchos proyectos embebidos miden la cobertura compilando las mismas fuentes para la máquina de desarrollo y ejecutando allí las pruebas unitarias. Es rápido, no necesita hardware y es la opción por defecto correcta para la mayoría de los equipos — pero conviene ser claro sobre lo que describe esa evidencia: un compilador distinto, un optimizador distinto, un juego de instrucciones distinto y un binario distinto del que se entrega. Para la mayoría del software eso es una concesión aceptable y bien entendida. Para trabajo evaluado según IEC 61508, ISO 26262 o DO-178C es la objeción estándar de host frente a destino, y las vías anteriores son las respuestas estándar a ella: la primera la cierra para la cobertura de fuente, la tercera para el código objeto.

Hoy por hoy, la exportación leída para el código objeto es la de COVerage.EXPORT.ListModule de Lauterbach TRACE32 con metric="object"; cárguela como cualquier otro archivo de traza. La métrica se puntúa y se controla solo con una licencia de pago y durante el período de evaluación. Una instalación Community no la puntúa, pero se le informa cuando un archivo de traza la contiene, porque un veredicto de cumplimiento que omitiera en silencio la evidencia más fuerte del archivo sería peor que uno que dice lo que omitió.

12. Exclusión de líneas sin código

Con excludeComments activado (valor predeterminado), las sentencias que caen íntegramente en líneas solo de comentario o en blanco quedan excluidas de los totales — esto también neutraliza una peculiaridad conocida de llvm-cov/gcov por la que un recuento de aciertos suelto recae en un comentario. También se respetan los marcadores estándar:

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

Las directivas del preprocesador tampoco cuentan como código, en C, C++, Objective-C, CUDA y C#: una línea que empieza por # — #define, #include, #if — y las líneas a las que la prolonga una barra invertida final. gcov imputa cada uso de una macro a la línea en la que está definida, así que un encabezado cuya única línea registrada era #define CHANNEL_COUNT (33U) figuraba como cubierto al 100% porque un bucle del archivo .c llegaba hasta ese valor, y otro cuya constante nadie usaba figuraba al 0%. Un encabezado así ya no tiene nada que medir y no aparece en la lista.

Ponga excluded.includeInTotals en true para contar de todos modos las líneas excluidas.

Dejar fuera un archivo o una carpeta, desde el árbol

Haga clic con el botón derecho en un archivo o una carpeta de la vista Coverage y elija Exclude from Coverage — también está entre las acciones de ruta de la fila — o ejecute Exclude This File from Coverage sobre el archivo abierto: la ruta del archivo relativa al espacio de trabajo, o el /** de la carpeta, va a fuciniCoverage.ignore en la configuración de la carpeta, una vez, y la recarga lo saca de cada total y de cada página; el patrón queda ahí para poder quitarlo de nuevo. En Visual Studio el menú de la fila y Tools → Coverage Studio tienen los mismos dos comandos, que escriben el mismo ajuste en el mismo archivo.

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 sobre una carpeta: el árbol sin ella, el patrón en la configuración.
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
En Visual Studio: Exclude This File from Coverage sobre fees.ts — el árbol sin él, el patrón en .vscode/settings.json.

Atributos y espacios de nombres, para .NET

Dos ajustes leen del código fuente lo que el informe no sabe decir. ignore.attributes — ExcludeFromCodeCoverage por defecto — excluye la clase, el método o la propiedad situados bajo un atributo que nombra, como lo haría LCOV_EXCL_START/STOP, sea cual sea la herramienta que escribió el informe: Coverlet respeta el atributo, OpenCover, dotCover y un lcov convertido no, y ahora todos coinciden. Nombres con o sin el sufijo Attribute, con o sin espacio de nombres; añada GeneratedCode, Obsolete o los suyos. ignore.namespaces deja fuera cada archivo cuya declaración de espacio de nombres coincide con un prefijo, * como comodín — Acme.Generated, Acme.*.Migrations, *Tests — y el panel Output nombra los archivos que quitó. Ambos se leen en la misma pasada que lee los marcadores de comentario, en las dos ediciones.

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

Excluir desde el editor

Seleccione las líneas y tome Exclude Selection from Coverage de la bombilla, del menú contextual del editor o de la Command Palette — en Visual Studio la bombilla (Ctrl+.), el menú del botón derecho de la ventana de código, Tools → Coverage Studio o Ctrl+Shift+U, X — y la exclusión se escribe donde está el código: [ExcludeFromCodeCoverage] sobre una clase, un método o una propiedad de C#, VB o F#, con el nombre corto cuando el archivo ya importa System.Diagnostics.CodeAnalysis y con el nombre completo cuando no, para que no haya que añadir ningún using; LCOV_EXCL_LINE al final de una línea de código; LCOV_EXCL_START y LCOV_EXCL_STOP alrededor de varias, con la sangría de la primera — con el signo de comentario propio del lenguaje, //, #, ', -- o ;. Un solo paso de deshacer. La bombilla también lo ofrece en una línea que las entradas de Problems marcan como sin cubrir. Una línea ya marcada, o un miembro que ya tiene el atributo, se deja como está.

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: los marcadores escritos alrededor de la selección, con el signo de comentario propio del archivo.
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
En Visual Studio: Exclude Selection from Coverage — los marcadores LCOV_EXCL alrededor de una rama, luego [ExcludeFromCodeCoverage] sobre un método.

Solo las ramas, y los marcadores de gcovr

Un else defensivo, un default: al que no llega ningún valor, la rama que un compilador añade para una excepción: la línea se ejecuta y debe contar, y solo su rama no se puede tomar. LCOV_EXCL_BR_LINE y LCOV_EXCL_BR_START … LCOV_EXCL_BR_STOP sacan del recuento las ramas de sus líneas y dejan en él las líneas. LCOV_EXCL_EXCEPTION_BR_LINE y su región sacan aún menos — solo las ramas que toma una excepción, donde el informe dice cuáles son, como hace el JSON de gcov. Cada marcador se lee también con los prefijos de gcovr: GCOVR_EXCL_LINE, GCOVR_EXCL_START, GCOVR_EXCL_BR_LINE, GCOV_EXCL_STOP y los demás significan lo mismo que los LCOV_EXCL_, de modo que un código fuente escrito para gcovr se lee igual aquí, sea cual sea la herramienta que generó el informe. No se lee: GCOVR_EXCL_FUNCTION — nada en esa línea dice dónde termina la función.

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

Decir por qué: exclusiones justificadas

Sacar código del recuento es una afirmación — «esto no se puede probar», «esto es una ayuda para el desarrollador» — y bajo DO-178C, ISO 26262 o IEC 61508 una afirmación que cambia la cifra en la que se apoya un certificado tiene que quedar por escrito y poder revisarse. Por eso una exclusión puede decir por qué, en el lugar donde está escrita: el texto que sigue a LCOV_EXCL_LINE o LCOV_EXCL_START, o la Justification de [ExcludeFromCodeCoverage].

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

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

Los motivos se leen en cada carga y el registro los cuenta. Export Coverage Report… escribe la lista — exclusiones y sus justificaciones, como Markdown o CSV: el archivo, las líneas, cómo se escribió la exclusión, y la justificación o none given. Un archivo al que no le queda nada medible sigue estando en esa lista. Con exclusions.requireReason activado, una exclusión que no da ningún motivo es un hallazgo: una advertencia en Problems en su línea, y un fallo de Check Coverage Thresholds. Exclude Selection from Coverage pide entonces primero el motivo y lo escribe con el marcador o como la Justification del atributo; si la petición se descarta o se deja vacía, no se excluye nada.

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).
En Visual Studio: una exclusión sin motivo como aviso en su línea, y la lista exportada con none given.

12a. ¿Esta cobertura sigue describiendo este archivo?

La cobertura leída de un tracefile describe el código tal como estaba cuando se ejecutaron las pruebas, y la mayoría de los formatos no dicen de qué versión se trataba. Por eso cada archivo del panel de Cobertura está en uno de tres estados:

  • ✓ Verificado: el tracefile registra lo que decía cada línea medida, y sigue coincidiendo con el archivo.
  • Sin marca: no refutado. Nada contradice la cobertura y nada la confirma. Es el estado habitual.
  • ⚠ Refutado: el propio archivo refuta su cobertura. La fila se atenúa y el tooltip dice qué se encontró.

Solo dos formatos pueden ganarse la marca, porque solo dos registran algo del código que midieron: lcov escrito con --checksum (desactivado por defecto en geninfo; su propósito documentado es justamente impedir que se combine la cobertura de dos versiones de un archivo) y GNATcoverage XML, que incrusta el texto de cada línea medida. Vale la pena activar la opción de lcov.

El aviso no necesita ninguno de los dos y funciona con todos los formatos: cobertura registrada más allá del final del archivo, una función con nombre que ya no está donde la sitúa el informe, o líneas ejecutadas que están en blanco en el archivo. Las marcas de tiempo nunca bastan por sí solas — un git checkout las cambia todas sin alterar un byte —, así que una marca de tiempo cambiada es como mucho un motivo para volver a mirar. La comprobación se ejecuta al cargar la cobertura y de nuevo cada vez que un archivo se guarda o cambia en disco, de modo que la marca sigue al archivo: una edición que contradice la ejecución la pone, un checkout que restaura la versión medida la quita. La descripción emergente dice exactamente qué lo demostró. Pon staleWarning.enabled en false para desactivarlo todo.

12b. No medido frente a no cubierto

Un archivo que la ejecución nunca menciona está no medido: ninguna prueba lo cargó, así que ninguna herramienta escribió una línea sobre él. No es lo mismo que no cubierto — medido, con cero aciertos — y la extensión nunca ha puntuado un archivo ausente como 0%. Lo que no hacía, hasta 0.2026.69, era mostrar en absoluto los ausentes: un módulo sin ninguna prueba nunca aparecía en el árbol, en los totales ni en la comprobación de umbrales, y el lector veía «92%» para un proyecto con la mitad de sus archivos jamás ejercitados.

Ahora, con una ejecución cargada, el elemento por archivo de la barra de estado dice no medido para un archivo fuente del tipo de la propia ejecución que la ejecución no contiene — «del tipo de la ejecución» significa que tiene una de las extensiones de archivo que la ejecución midió, de modo que las cabeceras y fuentes de un proyecto en C son candidatas y sus scripts de Python no. Todo lo demás es opcional mediante fuciniCoverage.unmeasured.mode:

  • off (predeterminado) — nada más cambia.
  • list — la vista Coverage recibe al final un grupo No medidos que nombra cada archivo así, y cada fila lo abre; el resultado de la carga los cuenta; las insignias los marcan con ? en el Explorer; y fuciniCoverage.threshold.unmeasuredFiles puede hacer fallar Check Coverage Thresholds cuando hay más de un número que usted fija. Ningún porcentaje se mueve.
  • count — todo lo que hace list, y además cada archivo no medido cuenta contra la ejecución como un archivo sin cubrir de sus propias líneas de código, de modo que la barra de estado, los umbrales, las insignias, el historial, cada exportación y la vista Test Coverage muestran la cifra más baja. El archivo se dibuja como no medido allí donde aparece, sus barras de margen dicen «no medido» en lugar de «nunca se ejecutó», y la comprobación de discrepancias lo deja en paz — no hay ninguna medición que su contenido pueda contradecir.
{
  "fuciniCoverage.unmeasured.mode": "list",
  "fuciniCoverage.threshold.unmeasuredFiles": 0
}

Los archivos de cabecera son el falso positivo conocido en C: tienen la familia de extensiones de la ejecución y ningún archivo de traza nombrará nunca uno, porque por sí solo no compila a nada. Por eso fuciniCoverage.unmeasured.exclude deja fuera de forma predeterminada **/*.h, **/*.hpp, **/*.hh, **/*.inl y **/*.d.ts, con la misma sintaxis glob que fuciniCoverage.ignore; añada un port a otra plataforma que aquí no se compila, o stubs generados, y salen de la lista, del recuento y del estado de la barra de estado. Un archivo que ignore nombra tampoco se considera nunca no medido — dejarlo fuera era justamente la intención. threshold.unmeasuredFiles vale -1 de forma predeterminada, lo que no comprueba; 0 falla en cuanto algún archivo del tipo de la ejecución nunca fue cargado por una prueba, y solo se aplica mientras unmeasured.mode es list o count.

13. Informes HTML

  • Generate Full HTML Report — un informe autorrenderizado, multipágina, por directorio. La salida va a htmlReport.outputDir, o al almacenamiento global de la extensión si no se establece.
  • Open Annotated Source — una vista anotada de un solo archivo. Apunte externalHtmlReport.dir a un directorio llvm-cov show --format=html preconstruido para usar esas páginas en lugar del renderizador integrado.
  • Export Fucini JSON — el modelo normalizado completo para sus propias herramientas.
  • Export Coverage Report... — la ejecución como CSV (por archivo o por función), resumen en Markdown, archivo LCOV, XML de Cobertura, SARIF, o insignia SVG autónoma para su README. También accesible desde el botón junto a Generate Full HTML Report en la vista Covered Files. Todo salvo los CSV pierde información — MC/DC, regiones e instanciaciones no caben en LCOV, Cobertura ni SARIF — así que Fucini JSON y los CSV siguen siendo los formatos que llevan todas las métricas.
  • Copy Uncovered Lines — un resumen en Markdown de cada hueco, listo para pegar en una PR.

En Visual Studio. El grupo Reports de Tools → Coverage Studio: Show Annotated Source abre el documento activo como una página en el área de documentos — cada línea en su color, los hallazgos a su lado — desplazada con el editor en ambos sentidos; Open HTML Report escribe el informe de una página en htmlReport.outputDir (o %LOCALAPPDATA%\Fucini\CoverageStudio\html-report) y abre el navegador; Generate Full HTML Report escribe allí el índice por carpeta y la página por archivo; Export Coverage Report… ofrece los mismos ocho formatos y pregunta dónde guardar; Generate Coverage Badge escribe la insignia donde indica badge.outputPath, tras cada carga con badge.autoUpdate. La página anotada necesita WebView2, como la ventana Coverage; los informes en 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).
En Visual Studio: Show Annotated Source — el archivo como página en el área de documentos, junto al 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).

Fuente anotada frente a fuente normal

Open Annotated Source reemplaza la pestaña activa por una vista web de cobertura codificada por colores para ese archivo, en la misma columna; Open Annotated Source to the Side hace lo mismo pero dividido, de modo que el código fuente y la vista anotada quedan uno junto al otro. Para alternar entre ambos en el mismo lugar —útil en pantallas pequeñas, donde una división deja cada panel demasiado estrecho— use Toggle Annotated Source: alterna la pestaña activa entre los dos, recordando cuál está viendo en ese momento. Desde la propia vista anotada, Show Source vuelve directamente al editor normal de ese archivo.

El HTML que realmente ve depende de externalHtmlReport.dir: cuando está definido y ya existe allí una página que coincide con el archivo activo (llvm-cov organiza las páginas por archivo como <nombre-repo>/<ruta-relativa>.html, por lo que nunca hace falta configurar la carpeta del nombre del repositorio del informe), se muestra esa página generada por la cadena de herramientas en lugar del renderizador integrado — sus enlaces/hoja de estilo locales se reescriben para funcionar dentro de la vista web, y contiene detalles que la vista integrada no reproduce (vistas de expansión MC/DC, resaltado de regiones, resúmenes por directorio). ¿No hay página coincidente para ese archivo, o el ajuste está vacío? Entonces se usa el renderizador integrado. La extensión solo lee este directorio; nunca escribe en él.

Una insignia de cobertura para el README

Generate Coverage Badge escribe un SVG al estilo de shields para la ejecución activa en el espacio de trabajo — badge.outputPath, de forma predeterminada coverage-badge.svg, relativo a la carpeta del espacio de trabajo o absoluto, con las mismas variables que cualquier otro ajuste de ruta — y ofrece abrirlo. Es un archivo corriente en su repositorio, así que un README lo incrusta sin ningún servicio detrás, sin ninguna ida y vuelta a shields.io, y funciona también en un repositorio sin conexión a la red:

![coverage](coverage-badge.svg)

coverage: 83%

badge.metric elige lo que muestra la insignia: lines (etiquetada coverage), branches, mcdc o weighted, la misma puntuación compuesta que muestra la barra de estado, etiquetada score. Una ejecución sin datos para la métrica elegida recibe un n/a gris en lugar de un 0% rojo. El color sigue sus propios niveles de colorScale.*: lowColor por debajo de lowThreshold, midColor hasta highThreshold, highColor a partir de ahí. Con badge.autoUpdate activado, la insignia se reescribe tras cada carga correcta, en silencio, y el canal de salida registra cada escritura como [FUCINI_BADGE] — desactivado de forma predeterminada porque escribe en el espacio de trabajo en cada carga. Confirme el SVG junto con el código y la imagen de la página del repositorio sigue a la cifra del editor.

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

14. Historial y tendencias

Active history.enabled para conservar las ejecuciones localmente (manteniendo history.retention de ellas). Después obtendrá una flecha de tendencia (▲/▼) en la barra de estado, el gráfico de tendencia en la vista Coverage y dos comandos de comparación: Compare with Last Run y Compare Two History Runs, cada uno de los cuales genera una diferencia de regresión/mejora por archivo.

En Visual Studio. Cada carga se compara con la anterior: un triángulo en el margen en cada línea que empezó o dejó de ejecutarse (sinceLastRun.enabled), la tendencia junto a la puntuación en la barra de estado, y Compare with Last Run para los archivos cuyos números se movieron. Con history.enabled las ejecuciones se conservan en %LOCALAPPDATA%\Fucini\CoverageStudio\history, history.retention de ellas, de modo que la comparación sobrevive a un reinicio, el gráfico de tendencia tiene algo que dibujar y Compare Two History Runs… elige dos cualesquiera de ellas.

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

El gráfico de tendencia

Bajo la barra de herramientas de la vista Coverage, con dos o más ejecuciones guardadas, la cobertura de líneas del historial como una línea, de la más antigua a la más reciente, las treinta últimas: un punto por ejecución que dice su fecha y su cifra al pasar el cursor, y la última cifra al lado con una flecha para la dirección desde la primera. La escala vertical es el propio rango de las ejecuciones, así que un equipo al 92–94% ve el movimiento en lugar de una línea plana por debajo de 100. Ambas ediciones lo dibujan a partir del mismo historial.

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 tendencia: un punto por ejecución guardada, la última cifra al lado.
Visual Studio: the trend line under the Coverage window toolbar, the last figure 68.25%
En Visual Studio: la tendencia bajo la barra de herramientas de la ventana Coverage, la última cifra 68.25%.

Sesiones de cobertura

Una sola ejecución de pruebas rara vez cubre todo lo que tocó un cambio: las pruebas unitarias corrieron aquí, el conjunto de integración allí, un recorrido por la interfaz con la cobertura activada en otro sitio. Start Coverage Session convierte las cargas que siguen en una sola suma — cada ejecución se añade a la anterior línea a línea como unión: una línea que cualquiera de ellas ejecutó está cubierta y los recuentos se suman —, de modo que el margen, el árbol y la puntuación muestran lo que alcanzaron todas juntas. La ejecución en pantalla, si la hay, es la primera de la sesión. Una barra sobre el árbol dice cuántas ejecuciones desde cuándo y termina la sesión; End Coverage Session hace lo mismo, y la siguiente carga vuelve a estar sola. En Visual Studio una sola entrada en Tools → Coverage Studio inicia la sesión y, marcada, 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 sesión de dos ejecuciones: la segunda añadida a la primera, la barra sobre el árbol contándolas.
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
En Visual Studio: Start Coverage Session, y una segunda ejecución sumada a la primera — la barra cuenta dos ejecuciones, las líneas suben de 50.79% a 68.25%.

La línea base de CI: ¿dónde estoy respecto a main?

Compare with Last Run responde a qué hizo su último cambio; antes de una pull request la pregunta es dónde está respecto a main, y la respuesta está en el servidor de compilación. baseline.report nombra el informe que publica la compilación de la rama main, y cada carga se compara con él: la tarjeta de la barra de estado lleva el delta en una línea — vs CI baseline: 84.20% → 85.10% (+0.90%), 3 file(s) moved — y Compare with CI Baseline enumera los archivos que se movieron, archivo por archivo, con las mismas palabras que Compare with Last Run. En Visual Studio el comando está en Tools → Coverage Studio y descarga o lee el informe cuando usted lo pide. Tres maneras de nombrarlo, en .vscode/settings.json:

  1. Una URL que sirve la CI. GitLab guarda los artefactos del último trabajo de una rama en una dirección estable; el token queda fuera del archivo de configuración mediante ${env:…} en 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}. La URL se descarga y se guarda en caché exactamente como una URL de coverageFile.paths (ETag, remote.refreshMinutes).
  2. Un archivo que la canalización copió a un recurso compartido — una ruta absoluta como \\build\drops\app\main\coverage.cobertura.xml.
  3. Un artefacto descargado guardado bajo la carpeta, digamos ci/main.lcov.info (ponga la carpeta en .gitignore) — una ruta relativa a la carpeta.
{
  "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}"]
}

Sirve cualquier formato que el lector conozca. Una ruta que la CI escribió relativa a su checkout — src/Billing/Invoice.cs, como la escribe Coverlet en el runner — se sitúa bajo esta carpeta antes del diff, para que coincida con el archivo que resolvió la ejecución local; una ruta absoluta de otra máquina no coincide con nada, así que haga que la canalización escriba rutas relativas. Una línea base que no se puede descargar ni leer es una línea en el panel Output, nunca una carga fallida.

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 línea base de CI: el delta en la tarjeta, y los archivos que se movieron respecto 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
En Visual Studio: Compare with CI Baseline — instrucciones y ramas frente al informe de las pruebas unitarias, y el archivo que cambió.

Un artefacto es un zip, y eso también se lee. GitHub y GitLab entregan un artefacto como un archivo comprimido, se haya puesto en él lo que se haya puesto. Nombre el informe que contiene después de un #: el miembro se encuentra por su ruta o por el final de ella; sin #, es el único archivo del comprimido, o su único archivo que parece un informe, y donde hay varios el panel Output los nombra. Lo mismo vale para un zip que usted descargó (ci/artifact.zip#lcov.info) y, en VS Code, para una URL en coverageFile.paths. El token va al servidor para el que se configuró y no más allá: la redirección al almacenamiento que guarda el archivo comprimido se sigue sin él.

{
  "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. Para agentes de IA: la cobertura en pantalla

Un agente que escribe pruebas puede ejecutarlas y leer un porcentaje. Lo que no puede hacer por sí solo es preguntar lo que sabe el editor: qué líneas de esta función nunca se ejecutaron, qué lado de qué rama, qué pruebas alcanzan una línea, si el diff que acaba de escribir está cubierto. Seis herramientas responden exactamente a eso, con palabras sobre las que un agente puede actuar, a partir de la ejecución cargada — las mismas exclusiones, el mismo remapeo, los mismos números que en pantalla. Así, un agente al que se le pide cubrir los huecos de una función y un revisor que mira el margen hablan de las mismas líneas.

HerramientaQué responde
coverage_summaryLos totales de la ejecución por métrica, y los archivos más lejos de estar cubiertos. Lo primero que hay que preguntar.
coverage_gapsLo que nunca se ejecutó en un archivo, una función o un intervalo de líneas: las líneas sin cubrir, las ramas no tomadas, las condiciones MC/DC sin su pareja, los mutantes que sobrevivieron.
tests_for_lineQué pruebas ejecutaron una línea, donde el informe lo dice — una ejecución por prueba.
patch_coverageLa cobertura de un diff — el árbol de trabajo respecto a una referencia de git, o un parche que se le entrega — y sus líneas que nunca se ejecutaron.
coverage_deltaLo que se movió desde la ejecución anterior: los totales, y los archivos que ganaron o perdieron.
test_run_commandEl comando que ejecuta las pruebas de este espacio de trabajo con la cobertura activada. El agente lo ejecuta; el editor recarga el informe por sí solo.

El propio agente de VS Code las tiene como herramientas sin configurar nada. Todos los demás agentes — cualquier cliente que hable MCP, el Model Context Protocol — acceden a ellas a través de un servidor que el editor ejecuta cuando mcp.enabled está activado, tanto en VS Code como en Visual Studio. Copy MCP Server Configuration pone la entrada del cliente en el portapapeles, tal como VS Code y Visual Studio la leen en un mcp.json; un cliente que llama mcpServers a la clave exterior toma la misma entrada bajo ese nombre.

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).
En Visual Studio: Copy MCP Server Configuration y su mensaje; el token tapado.
{
  "servers": {
    "fucini-coverage": {
      "type": "http",
      "url": "http://127.0.0.1:39217/mcp",
      "headers": { "Authorization": "Bearer …" }
    }
  }
  }
  • Está desactivado mientras usted no lo active, y solo escucha en 127.0.0.1: nada de fuera de esta máquina llega a él.
  • Una llamada tiene que llevar el token de usted, creado una vez y guardado para usted; sin él, la respuesta es 401. La configuración copiada lleva el token: manténgala fuera del repositorio.
  • Una llamada enviada por una página web — lo dice en su Origin — se rechaza, lleve lo que lleve.
  • Lee la ejecución cargada y no escribe nada. La ejecución de pruebas se nombra, no se inicia: el agente ejecuta el comando en su propio terminal.

El puerto es mcp.port, 39217 si no se indica otro. Donde ese está ocupado — una segunda ventana, la otra edición junto a esta — se usa el siguiente libre, y la configuración copiada nombra el que funciona. El panel Output dice dónde escucha el servidor ([FUCINI_MCP]) y por qué no pudo hacerlo ([FUCINI_MCP_001]). Lo que un plan no incluye — los nombres de las pruebas, el detalle de MC/DC — las herramientas lo cuentan sin detallarlo, como hace la información al pasar el cursor.

15. Referencia de comandos

En Visual Studio. Todos los comandos están en Tools → Coverage Studio, con el nombre de la tabla sin el prefijo Fucini Coverage:; la barra de herramientas de la ventana Coverage y el menú del botón derecho de una fila tienen los que les corresponden, y el menú del botón derecho de la ventana de código tiene los tres que actúan sobre el editor: Run This Test with Coverage, Show Tests That Ran This Line y Exclude Selection from Coverage. Los que tienen teclas son acordes de dos pulsaciones tras Ctrl+Shift+U: R recarga, N y P van a la siguiente y anterior línea sin cubrir, B a la siguiente decisión parcialmente probada, T enumera las pruebas que ejecutaron la línea, X excluye la selección — no el Alt+N de VS Code, porque en Visual Studio Alt y una letra abren un menú. Cámbielos en Tools → Options → Keyboard, donde figuran como Coverage Studio: …. No en esta edición: el panel Test Coverage es una API de VS Code — la ejecución está en su lugar en la ventana Coverage — y el Explorador de soluciones no puede mostrar insignias. Solo en esta edición: Run Native Project with Coverage, para un proyecto de inicio C++.

En Visual Studio: dónde está cada cosa. La ventana Coverage está en View → Other Windows → Coverage, y en primer lugar en Tools → Coverage Studio, donde están todos los comandos de esta edición, por grupos: cargar y recargar, vigilar el archivo, las dos copias y las tarjetas; Run Tests with Coverage, Run Native Project with Coverage y Collect Coverage in Test Explorer…; Next y Previous Uncovered y las decisiones parcialmente probadas; el coloreado, los contadores de ejecuciones y los modos del margen; la fuente de cobertura de un archivo, las pruebas que ejecutaron una línea, una prueba con cobertura, las dos maneras de excluir; Compare with Last Run, Compare Two History Runs…, Compare with CI Baseline, la sesión de cobertura y Check Coverage Thresholds; el grupo Reports — Show Annotated Source, Open HTML Report, Generate Full HTML Report, Export Coverage Report… y Generate Coverage Badge; después Getting Started, los umbrales de cumplimiento y Licence…. La barra de herramientas de la ventana tiene los cinco que más se usan: Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary y los umbrales de cumplimiento; debajo, la perspectiva, el filtro y la ordenación, y el cuadro de búsqueda; debajo de esos, la tendencia. Deje el puntero sobre una fila del árbol y pulse su ⋯ para el menú de la fila: abrir el archivo, abrir su carpeta, copiar su ruta, absoluta o relativa, con cualquiera de los dos tipos de barra, excluirlo de la cobertura. En el extremo derecho de la barra de estado están la puntuación de la ejecución y la del archivo abierto, con la tendencia desde la última ejecución; Show Coverage Card y Show Coverage Card for This File abren las tarjetas que hay detrás, las mismas que VS Code muestra cuando el puntero se detiene sobre su elemento de la barra de estado.

Visual Studio: Tools → Coverage Studio, open, with every command of the edition
En Visual Studio: Tools → Coverage Studio, con todos los comandos de esta edición.
Visual Studio: View → Other Windows, where the Coverage window is
En Visual Studio: View → Other Windows, donde está la ventana Coverage.
Visual Studio: the Coverage window's toolbar — Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary, compliance thresholds
En Visual Studio: la barra de herramientas de la ventana Coverage — Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary y los umbrales de cumplimiento.
Visual Studio: a row's menu in the Coverage window — Open, Open Containing Folder, and the four Copy Path entries
En Visual Studio: el menú ⋯ de una fila — abrir el archivo, abrir su carpeta, copiar su ruta en cuatro formas.
Visual Studio: the status bar's two items, the run's score and the open file's
En Visual Studio: los dos elementos de la barra de estado, la puntuación de la ejecución y la del archivo abierto.
Visual Studio: the run's coverage card, opened by Show Coverage Card
En Visual Studio: la tarjeta de cobertura de la ejecución, desde Show Coverage Card.
Visual Studio: the open file's coverage card, opened by Show Coverage Card for This File
En Visual Studio: la tarjeta del archivo abierto, desde 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).
En VS Code: las tarjetas emergentes de la barra de estado para la ejecución y el archivo, luego la barra de herramientas de la vista Coverage, terminando en el informe generado.
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).
En VS Code: el menú de la barra de estado — elegir un archivo de cobertura, ejecutar pruebas con cobertura, recargar, abrir el informe, elegir el modo del margen.
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).
En VS Code: Show Worst-Covered Functions, menor cobertura primero, con la puntuación CRAP donde el informe incluye complejidad.
ComandoQué hace
Load CoverageDescubrir y cargar la cobertura del espacio de trabajo. Alt+Shift+R por defecto (Ctrl+Alt+R en macOS).
Pick Coverage FileElegir tracefiles — uno, varios, o uno más cada vez; las elecciones se suman, se fusionan y se escriben en coverageFile.paths, de modo que a partir de entonces se cargan solas.
Show Loaded Coverage FilesListar los tracefiles de la ejecución activa. La vista Cobertura también los lista, cada uno con un botón de descarga y un botón de elección al lado.
Toggle Tracefile WatchVigilar cambios en el/los archivo(s) de traza y recargar automáticamente.
Run Tests with CoverageReconocer el ejecutor de pruebas, ejecutarlo con cobertura en una tarea de terminal, cargar lo que escribe y ofrecer añadir la ruta a la configuración.
Run This Test with CoverageLa prueba bajo el cursor — el método, la clase o el bloque describe, o el archivo — ejecutada por la receta acotada a ella, y luego cargada como cualquier ejecución. También en el menú contextual del editor.
Show Tests That Ran This LineDonde el informe dice qué pruebas ejecutaron qué, enumera las pruebas que ejecutaron la línea bajo el cursor, las más activas primero, y abre la que elija donde está escrita.
Run Tests Affected by My Changes…Enumerar las pruebas que ejecutaron una línea que el árbol de trabajo cambia respecto a testImpact.baseRef, abrir la que usted elija, o ejecutar solo esas cuando los informes proceden de una ejecución por prueba.
Show Minimal Test Set…El menor número de pruebas que siguen ejecutando todas las líneas que ejecuta la suite, y después las pruebas que no añaden ninguna línea propia.
Run App with Coverage…Iniciar la aplicación .NET de la carpeta bajo dotnet-coverage, y cargar lo que usted recorrió cuando se cierra.
Run Mutation Tests HereMutar la función en la que está el cursor — o la selección, o el archivo — con Stryker.NET, StrykerJS o PIT, y cargar el informe junto a la cobertura en pantalla.
Exclude This File from Coverage / Exclude from CoveragePone el archivo abierto — o, en una fila de la vista Coverage, el archivo o el /** de la carpeta — en fuciniCoverage.ignore de la configuración de la carpeta, una vez.
Exclude Selection from CoverageEscribe la exclusión donde está el código: [ExcludeFromCodeCoverage] sobre un miembro .NET, LCOV_EXCL_LINE en una línea, LCOV_EXCL_START/STOP alrededor de varias, con el signo de comentario propio del archivo. También la bombilla y el menú contextual del editor.
Start Coverage Session / End Coverage SessionMientras una sesión está activa, cada carga se suma a la anterior como unión; una barra sobre el árbol cuenta las ejecuciones y la termina.
Next / Previous UncoveredSaltar entre regiones sin cubrir. Alt+N / Alt+P por defecto (Ctrl+Alt+N / Ctrl+Alt+P en macOS).
Choose Editor Gutter Mode...Desactivado, barras solo en las líneas sin cubrir, barras rojo-ámbar-verde, o un mapa de calor de recuentos de aciertos en el margen del editor.
Cycle Editor Gutter ModeUn paso adelante por off, uncovered, coverage y heatmap — Alt+G, o el botón de modo de la barra de estado.
Choose Coverage Source for This File...Cuando más de un informe cargado mide el archivo abierto, elegir de cuál proceden sus números, para el archivo, su carpeta o un patrón — escribe una regla de coverageFile.sources.
Clear Coverage Source for This File...Quitar las reglas de coverageFile.sources que se aplican al archivo abierto.
Toggle Inline Hit CountsMostrar u ocultar los recuentos de ejecución ×N tras cada línea — alterna hitCounts.inline.
Show in Test Coverage ViewPublicar la ejecución activa en el propio panel Test Coverage de VS Code (incluso con testCoverage.publish desactivado) y abrirlo.
Suggest Path Remap RuleInferir la regla de pathRemap que haría coincidir con el espacio de trabajo los archivos sin coincidencia de la ejecución activa, y ofrecer añadirla.
What Community IncludesCada límite y cada función retenida del nivel gratuito en una sola lista, con cuánto de cada límite se ha usado.
Open HTML ReportAbrir el informe estático generado.
Generate Full HTML ReportGenerar el informe de varias páginas.
Open Annotated Source / …to the SideVista anotada de la cobertura de un archivo.
Toggle Annotated SourceAlternar entre el código y la vista anotada. Alt+A por defecto (Ctrl+Alt+A en macOS).
Show Worst-Covered Files / Folders / FunctionsQuick Pick ordenado de menor a mayor.
Copy Uncovered LinesResumen en Markdown de cada rango sin cubrir.
Compare Two History Runs / with Last RunDiff de regresión por archivo — dos ejecuciones que guardó el historial, o la ejecución en pantalla contra la que sustituyó.
Compare with CI BaselineLa ejecución cargada contra el informe que nombra baseline.report — el de la rama main en CI, una URL o un artefacto descargado — archivo por archivo.
Show Indirect Coverage Changes…Las líneas cuya cobertura se movió aunque nadie las editó, respecto a la línea base de CI o a la ejecución anterior, por archivo.
Check Coverage ThresholdsEvaluar los controles de conformidad.
Export Fucini JSONExportar la ejecución actual como Fucini JSON.
Export Coverage Report...Elija un formato — CSV, Markdown, LCOV, XML de Cobertura, SARIF o una insignia SVG — y un destino.
Generate Coverage BadgeEscribir la insignia SVG de la ejecución activa en badge.outputPath, mostrando badge.metric, y ofrecer abrirla.
Copy MCP Server ConfigurationPoner en el portapapeles lo que un cliente MCP necesita para preguntar por la cobertura en pantalla — la dirección del servidor y el token de usted; con el servidor desactivado, ofrecer activarlo.
Show Status Bar MenuAbrir el menú de acciones rápidas.
Browse for External HTML Report / Full Report Output Dir…Establecer los directorios de informes mediante un selector.

16. Referencia de configuración

La tabla completa y categorizada de ajustes — cada opción con su valor predeterminado — se encuentra en la página Features & Settings. Todas las claves tienen el prefijo fuciniCoverage..

Cabe destacar: fuciniCoverage.language fija la propia interfaz en tiempo de ejecución de esta extensión (barra de estado, notificaciones, información sobre herramientas, vistas web) a un idioma concreto, independientemente del idioma de visualización de VS Code — por defecto es auto e incluye paquetes para los 18 idiomas admitidos. No cambia las entradas de la paleta de comandos ni las etiquetas de la configuración, que VS Code resuelve a partir de su propio idioma de visualización.

En Visual Studio. Las mismas claves fuciniCoverage.*, leídas de hasta cuatro archivos, ganando el posterior: la configuración de usuario propia de VS Code si VS Code está en la máquina — leída, nunca escrita, para que sus colores y umbrales le acompañen; %APPDATA%\Fucini\CoverageStudio\settings.json, la configuración de usuario de esta edición; .vscode\settings.json en la carpeta o junto a la solución, de modo que un repositorio configurado para VS Code está configurado para Visual Studio; y fucini-coverage.json en la raíz de la solución, para un equipo que prefiera no tener una carpeta .vscode en un repositorio .NET — la edición de VS Code también lo lee. El engranaje de la barra de herramientas de la ventana Coverage abre una ventana de configuración que escribe el archivo de usuario o el archivo de la carpeta que exista, según diga su selector Write changes to, y conserva los comentarios de un archivo que edita. fuciniCoverage.language funciona allí igual; los menús siguen el idioma propio de Visual Studio.

17. Códigos de error

Los diagnósticos se envían al canal de salida Fucini Coverage (View → Output → Fucini Coverage), cada uno con un código estable FUCINI_*.

En Visual Studio. Los mismos códigos van al panel Fucini Coverage de la ventana Output (View → Output) y se guardan en %LOCALAPPDATA%\Fucini\CoverageStudio\coverage-studio.log, para la pregunta que llega después de cerrar el IDE. Tres que aparecen: no hay nada marcado aunque el panel dice que se cargaron archivos — el modo de margen es off, elija Show Coverage in Editor; FUCINI_REMAP_001 y una barra de información — el informe nombra rutas que no existen aquí, y el panel sugiere la regla pathRemap; la ventana Coverage dice que necesita WebView2 — instale el Microsoft Edge WebView2 Runtime, las marcas en el editor no lo necesitan.

CódigoSignificado
FUCINI_PARSE_001Formato de cobertura no admitido o no reconocido: ningún analizador coincidió con el archivo.
FUCINI_PARSE_010El archivo lcov no contenía registros SF.
FUCINI_PARSE_020JSON de llvm-cov no válido, sin data[] o sin archivos.
FUCINI_PARSE_030Falta la raíz <coverage> de Cobertura o el XML no es válido.
FUCINI_PARSE_040Falta la raíz <report> de JaCoCo o no hay archivos fuente.
FUCINI_PARSE_050JSON de Istanbul/SimpleCov no válido o sin archivos.
FUCINI_PARSE_060JSON de SimpleCov no válido o sin el array files de nivel superior.
FUCINI_PARSE_070Perfil de Go sin encabezado mode:, o sin bloques de cobertura.
FUCINI_PARSE_080Falta la raíz <coverage> o <project> de Clover, o no contiene archivos.
FUCINI_PARSE_090Falta la raíz <CoverageSession> de OpenCover, o no contiene archivos.
FUCINI_PARSE_100JSON de coverage.py no válido o sin un objeto files de nivel superior.
FUCINI_PARSE_110JSON de gcov/gcovr no válido o sin un arreglo files de nivel superior.
FUCINI_PARSE_120XML de GNATcoverage sin elemento <source>, o un index.xml cuyos xi:include nunca se resolvieron: carga en su lugar los archivos *.xml por fuente.
FUCINI_PARSE_130Falta la raíz <BullseyeCoverage>, o no contiene elementos <src>.
FUCINI_PARSE_140Falta la raíz <CoverageDSPriv>, no hay tabla <SourceFileNames> con la que resolver las filas de líneas, o no hay datos de líneas.
FUCINI_PARSE_150JSON de cobertura de Xcode no válido, o falta el array targets de nivel superior.
FUCINI_PARSE_160Falta la raíz <coverage> de SonarQube, o no contiene elementos <file>.
FUCINI_PARSE_170JSON de Coveralls no válido, o falta el array source_files de nivel superior.
FUCINI_LOADUna carga se canceló desde su notificación de progreso; la ejecución anterior, si la había, sigue cargada.
FUCINI_REMOTE_001No se pudo descargar una URL de coverageFile.paths, con el motivo; se carga en su lugar la última copia descargada. Las líneas [FUCINI_REMOTE] normales registran cada descarga y cada comprobación sin cambios (304).
FUCINI_REMOTE_002Una URL de coverageFile.paths no dio una respuesta completa en 30 segundos — casi siempre un proxy o VPN que acepta la conexión y luego calla; se carga en su lugar la última copia descargada.
FUCINI_REMOTE_003Una URL de coverageFile.paths respondió con una página HTML en lugar de un archivo de trazas — una página de inicio de sesión, lo más probable. La página no se guarda en caché y se carga en su lugar la última copia descargada; compruebe el token en remote.headers.
FUCINI_REMAP_002Se sugirió una regla de pathRemap para las rutas que una carga dejó sin coincidencia, con cuántas de ellas explica — o no se pudo inferir ninguna, o la regla inferida ya está en el ajuste y no las resolvió.
FUCINI_REMAP_003La regla sugerida se añadió a fuciniCoverage.pathRemap mediante Apply Suggested Remap y la cobertura se está recargando.
FUCINI_GITDIFF_001La extensión Git no está disponible; se omite la cobertura del diff y se muestra la ejecución completa.
FUCINI_GITDIFF_002gitDiff.baseRef empieza por -, con lo que ninguna referencia de git puede empezar (git lo leería como una opción); se omite la cobertura del diff y se muestra la ejecución completa.
FUCINI_IGNORECuántos archivos dejó fuera de la ejecución fuciniCoverage.ignore, y cuáles.
FUCINI_UNMEASURED_001Los archivos del tipo de la ejecución que ninguna prueba cargó, uno por línea.
FUCINI_UNMEASURED_002Más de 5.000 archivos del espacio de trabajo coincidieron con una de las extensiones de la ejecución; solo los primeros 5.000 se tuvieron en cuenta para la lista de no medidos.
FUCINI_UNMEASURED_003En el modo count, algunos archivos no medidos se listan pero no se cuentan: se alcanzó el límite de lectura (2.000 archivos o 50 MB por carga).
FUCINI_UNMEASURED_004Un archivo no medido no se pudo leer; se lista pero no se cuenta.
FUCINI_TESTCOVERAGECuántos archivos se publicaron en la vista Test Coverage de VS Code.
FUCINI_BADGELa insignia se escribió, con su ruta, etiqueta y valor.
FUCINI_BADGE_001La insignia no se pudo escribir, con el motivo.
FUCINI_WORKSPACESe añadió o se quitó una carpeta del espacio de trabajo; la cobertura se detecta de nuevo.
FUCINI_VARIABLESQué respondió cada ${command:…} de los ajustes de ruta, o por qué quedó tal como estaba escrito: el comando falló, no devolvió nada utilizable o el área de trabajo no es de confianza.
FUCINI_WATCHQué está haciendo el observador: las rutas vigiladas, un archivo configurado que ha aparecido, una tarea nombrada en watch.reloadAfterTasks que terminó (con su código de salida) y desencadenó una recarga, o una ruta bajo files.watcherExclude que se sondea en su lugar.

18. Privacidad

La telemetría se controla mediante el ajuste telemetry.enabled de ámbito window. Está desactivada de forma predeterminada. El resumen diario y el aviso de eliminación requieren además que el telemetry.telemetryLevel global de VS Code permita la telemetría; el aviso de instalación y algunos eventos pequeños se envían en cualquier caso, al igual que la entrada en el libro de uso de una instalación en el periodo de prueba o en el nivel gratuito Community. En Community, Unlock Full Features canjea esta telemetría por todas las funciones Pro, MC/DC incluida, durante 30 días, una vez por máquina; desactívala de nuevo y se aplica el conjunto estándar de Community. Una licencia de pago no se ve afectada en ningún caso. Consulta la política de privacidad para saber qué se envía.

Dos cosas conviene conocer, porque puedes actuar sobre ellas. La primera es tu ID del libro de uso: en la prueba y en Community, la extensión lo muestra en Show License / Activation y al final de What Community Includes, donde al seleccionar la fila se copia y se abre la política de privacidad. El libro conoce tu máquina por un hash y por nada más, así que ese ID es la única manera de preguntar qué guarda sobre ti, pedir que se elimine u oponerte a él: cítalo y encontraremos tu fila; sin él no podemos. La segunda es el registro de instalación: una fila escrita la primera vez que una instalación informa y conservada en lugar de eliminarse a los 90 días, con el identificador de instalación, el día, el lugar al que se resolvió su dirección, las versiones y el sistema operativo; no la dirección en sí, ni nada sobre tu código. Es lo que nos permite decir cuántas instalaciones ha habido a lo largo de los años. Ambos se describen por completo en la política de privacidad, y ambos se eliminan si lo pides.

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
El final de What Community Includes: cómo se cuentan los límites y la fila que te entrega tu ID del libro de uso.

19. Evaluación y activación

Fucini Coverage Studio se distribuye como preversión de evaluación. En la primera ejecución se te pide aceptar evaluarla y comienza la prueba: todas las funciones están disponibles durante una prueba de 14 días, contados desde la primera vez que la usas en esa instalación. No hay una fecha fija tras la cual deje de funcionar algo.

A partir de la versión 2.2026.2, la prueba de una instalación nueva comienza en cuanto la extensión ha contactado una vez con el servidor de licencias; hasta entonces funciona en el nivel Community y lo indica. En un contenedor de desarrollo o un Codespace no comienza ninguna prueba: un código de suscripción, una clave o el pase de 7 días desbloquea allí el conjunto completo.

Cuando termina la prueba no se bloquea nada: la extensión pasa al nivel gratuito Community. Para recuperar el conjunto completo, actívala: la activación se conecta al servidor de licencias y aplica la clave devuelta automáticamente, sin correo y sin ninguna clave que copiar 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. Ejecuta Fucini Coverage: Show License / Activation (también accesible desde la barra de estado una vez caducada la prueba o la clave) y haz clic en Request License… (o Request Renewed Key… si ya activaste antes).
  2. Confirma la solicitud. La clave se emite automáticamente y se reutilizan tus datos de contacto de cualquier solicitud anterior en lugar de volver a pedirlos.
  3. Ya está. La clave de activación se genera y se escribe automáticamente en fuciniCoverage.license.key. La barra de estado pasa de la prueba a una licencia activada en un momento.

La vía manual en una imagen: abra el panel de licencia, elija Enter Key, pegue la clave de su correo y el banner pasa 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).

Si la solicitud automatizada llegara a fallar (sin conexión, problema del servidor): ejecute Fucini Coverage: Copy Activation Request Code, envíelo a través de la página de contacto o a info@fucini.consulting, y pegue la clave FCK1.… que reciba con Fucini Coverage: Enter Activation Key (o directamente en settings.json):

{ "fuciniCoverage.license.key": "FCK1.…pegue aquí la clave completa…" }

El nombre del ajuste es fuciniCoverage.license.key (ámbito user/global). La clave está vinculada a su máquina y a su usuario del sistema operativo, puede tener una caducidad y puede activar o limitar funciones individuales y limitar el número de cargas de cobertura por día. Si aparece «invalid for this machine», solicite una clave nueva desde esta instalación: una clave emitida para otra máquina nunca será válida aquí.

En Visual Studio. En esa edición no hay nivel gratuito: sin una suscripción no se lee nada. Con una, el plan decide allí lo mismo que decide en VS Code — una función que el plan no incluye queda retenida, y su comando lo dice en lugar de ejecutarse. La versión más antigua que el servidor de licencias aún admite rige allí también: a una build anterior a ella se le avisa una vez al día, con la fecha en que deja de funcionar, y sigue funcionando hasta entonces. Estar sin conexión nunca detiene una build.

El nivel gratuito Community: una cuota semanal

Community nunca deja de mostrar la cobertura. Los márgenes, la regla de vista general, los hovers, CodeLens, la vista Coverage, el modo watch, la cobertura de diff y el historial no se cuentan en absoluto, y cargar un tracefile mediante un comando solo está limitado a 25 al día. Lo que se mide es la salida: cinco a la semana de cada una de estas acciones: abrir el informe HTML, exportar, comparar dos ejecuciones, comprobar los umbrales y ver el código fuente anotado en el sitio.

La semana es suya, no del calendario: empieza con el primer uso y termina siete días después. Cuando una cuota se agota, el mensaje nombra la acción y el día en que vuelve, y después de ese único mensaje solo la barra de estado lo menciona. Fucini Coverage: What Community Includes enumera cada cuota, con cuánto se ha usado y cuándo se restablece, antes de que llegue a alcanzar alguna.

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

Tres detalles pertenecen a los planes de pago, mientras que sus hallazgos siguen siendo gratuitos: Community marca cada línea que tiene mutantes supervivientes y dice cuántos, pero no qué cambió cada mutante; dice cuántas pruebas ejecutaron una línea, pero no sus nombres; y muestra el Max CRAP de una ejecución, pero no la lista clasificada Riskiest Methods.

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

Si ya usaba Community cuando llegó la cuota semanal (0.2026.83), sus límites anteriores se mantienen durante 30 días; se le avisa una sola vez, con la fecha. Los contadores se guardan en su equipo —en el almacenamiento propio de VS Code y en ~/.fucini-coverage/, de modo que un perfil nuevo de VS Code continúa la misma semana— y nunca se envían a ningún sitio.

El pase de 7 días

¿No está listo para una suscripción? Un pase de 7 días es todo lo de Pro durante una semana, pagado una sola vez: nada se renueva y no hay nada que cancelar. Cómprelo en la página de precios (el mensaje que aparece al alcanzar un límite de Community tiene un botón para ello), y el código de activación llega por correo electrónico.

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. Ejecute Fucini Coverage: Enter Subscription Code: el comando existe tanto en la edición Community como en Pro.
  2. Elija Pro y pegue el código FCB1-… del correo.
  3. Eso es todo. La clave se emite y se aplica por usted, y funciona sin conexión. La semana cuenta desde el pago, así que active en cuanto compre. Cuando termina, la extensión vuelve por sí sola a Community y sigue mostrando la cobertura.
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).

En Visual Studio. El mismo código activa Fucini Coverage Studio para Visual Studio, 2022 y 2026: abra Tools → Coverage Studio → Licence…, pegue el código, elija el plan al que corresponde y pulse Activate. La ventana Coverage muestra entonces Activated sobre el árbol; desplegada con su flecha, la fila muestra la fecha hasta la que es válida la clave y un botón a su cuenta. Una máquina es un puesto: active VS Code o Visual Studio, y el otro editor en la misma máquina lo sigue por sí solo — Visual Studio lee la clave de VS Code y VS Code la de Visual Studio —, así que nada se introduce dos veces y no se ocupa un segundo puesto. Ambos mantienen viva una clave del mismo modo: Pro Plus, Business y Enterprise se registran dos veces al día, y una clave Pro se renueva en la semana anterior a su vencimiento.

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

Cambiar de ordenador y gestionar los puestos

Una clave está ligada a una máquina, así que un ordenador nuevo necesita una nueva — y tu suscripción no paga más máquinas de las que indica. Libera la anterior tú mismo: entra en gestionar tu suscripción, busca el puesto que ya no usas, elige Free up y activa la máquina nueva con el mismo código. Comprar Pro no te envía ninguna contraseña: tu cuenta existe, simplemente aún no tiene una, así que la primera vez usa establecer o restablecer tu contraseña con la dirección con la que te suscribiste.

En Business y Enterprise invitas a cada compañero por correo desde esa misma página. Cada uno recibe un código de activación que es solo suyo, y en cuanto lo usa su dirección aparece junto a su puesto: cuando alguien se va, ves cuál era el suyo y lo liberas para el siguiente. Una invitación ocupa un puesto desde que la envías y caduca a los 14 días si no se usa; retírala para recuperar la plaza al instante.

Probar versiones preliminares

Las novedades llegan a fucini.software antes que al Marketplace, y puede pedir que se las ofrezcamos. Abra la vista Coverage, despliegue el panel de licencia y pulse Probar versiones preliminares… — o active fuciniCoverage.update.preRelease. A partir de ahí, la extensión consulta aquí un canal preliminar aparte además del habitual, y ofrece la más reciente de las dos.

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

Las versiones preliminares están probadas, pero son las compilaciones de las que menos seguros estamos: estaría ofreciéndose voluntario para encontrar lo que se nos escapó. Al unirse nos dice que esta instalación está en el canal, de modo que sabemos cuántas personas están probando y podemos contarle qué ha cambiado; al salir, la siguiente versión estable le devuelve al camino habitual. No siempre hay una versión preliminar disponible, y unirse cuando no la hay no cuesta nada: la extensión encuentra un canal vacío, no dice nada al respecto y sigue ofreciendo versiones estables hasta que se publique 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. Contacto y licencia

Preguntas, informes de errores o condiciones de licencia alternativas — consulte la página de contacto o escriba a info@fucini.consulting. Con licencia MIT con una condición de atribución en las notas de la versión; véase también el Notice.

21. En la línea de comandos

El lector también funciona sin editor: npm install -g fucini-coverage, gratis, en Windows, Linux, WSL y macOS. fucini-coverage check coverage/lcov.info --lines 80 es la puerta con la que falla una canalización; summary, export, report, badge y compare hacen lo que hacen los comandos de los editores con esos nombres, y mcp sirve las seis herramientas de la sección anterior a un agente, en un servidor. Lee fucini-coverage.json, el archivo de configuración que lee la edición para Visual Studio, así que los umbrales se fijan una sola vez. fucini-coverage help <command> explica cada uno; la página completa es fucini-coverage en 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).