1. Introdução
O Fucini Coverage Studio transforma os ficheiros de rastreio de cobertura que a sua build já produz em cobertura de primeira classe dentro do editor — no VS Code e no Visual Studio. Lê vinte e cinco formatos, normaliza-os num único modelo canónico Fucini, funde várias execuções de forma determinista e mostra tudo no próprio editor — margens, CodeLens, hover e uma vista Covered Files — pelo que não há um visualizador à parte pelo qual sair do seu editor. As duas edições partilham um leitor: o mesmo relatório dá os mesmos números, ao dígito, nas duas. Este guia está escrito a partir do VS Code; onde o Visual Studio difere, uma caixa In Visual Studio diz como.
Foi criado a pensar em fluxos de trabalho de segurança funcional: cobertura MC/DC, cobertura de regiões e instanciações C++, uma pontuação composta ponderada pela segurança e um veredito COMPLIANT / NON-COMPLIANT configurável, alinhado com o pensamento da IEC 61508, ISO 26262 e DO-178C.
Screenshot pending — add assets/img/marketplace-demo.gif (see SCREENSHOTS.md).2. Instalação e requisitos
- VS Code ≥ 1.88 — a versão mínima que esta extensão suporta — ou Visual Studio 2022 ou 2026, Community, Professional ou Enterprise (veja a caixa abaixo).
- Um ficheiro de rastreio de cobertura que o seu projeto já produz (veja §4).
Instale a partir do Marketplace, ou de um ficheiro .vsix através de Extensions → ⋯ → Install from VSIX…. A extensão ativa-se no arranque e adiciona um ícone Coverage à barra de atividades.
No Visual Studio. O mesmo produto é distribuído como uma segunda extensão, Fucini Coverage Studio para Visual Studio, para Visual Studio 2022 e 2026 — Community, Professional e Enterprise. Não usa a cobertura de código própria do Visual Studio: no Visual Studio 2022 é uma funcionalidade Enterprise, por isso no Community e no Professional esta é a única cobertura que o IDE mostrará. Instale o .vsix abrindo-o — o VSIX Installer pergunta qual Visual Studio — ou através de Extensions → Manage Extensions; a extensão carrega quando se abre uma solução ou uma pasta. A janela Coverage precisa do Microsoft Edge WebView2 Runtime, que o Windows 11 e o Visual Studio 2026 já trazem; as marcas no editor funcionam sem ele.
3. Início rápido
Quer ver como funciona antes de ligar o seu próprio projeto? Transfira o projeto de demonstração (~6 KB — um pequeno projeto em C com um lcov.info já pronto):
- Descompacte-o onde quiser e depois abra
coverage-studio-demo.code-workspaceno VS Code (File → Open Workspace from File…). - Instale o Fucini Coverage Studio se ainda não o fez (ver §2 acima).
- O próprio
.vscode/settings.jsondo workspace já aponta para ocoverage/lcov.infoincluído, pelo que os indicadores e a vista Covered Files aparecem assim que a extensão é ativada — não é necessário o passoLoad Coverage. - Quer regenerar o ficheiro de rastreio você mesmo (por exemplo, com outro compilador)? Execute
scripts/gen-coverage.sh(ou.ps1no Windows) — consulte o próprioREADME.mddo workspace para ver os compiladores disponíveis.
No Visual Studio. Abra uma solução, ou uma pasta (File → Open → Folder, que é como se abre um projeto CMake) — a demo acima abre-se como pasta, e o seu .vscode/settings.json também é lido aí. Um relatório no local que as definições indicam é carregado sozinho e o painel Fucini Coverage da janela Output diz quais ficheiros; caso contrário, Tools → Coverage Studio → Load Coverage File…, uma vez — fica memorizado. Abra um ficheiro de código e escolha Show Coverage in Editor: vermelho é uma linha que nunca correu, âmbar uma decisão tomada num só sentido, e Ctrl+Shift+U, N vai à próxima linha não coberta. View → Other Windows → Coverage é a árvore com os números de cada ficheiro e uma pontuação sobre todos, que a barra de estado mostra para a execução e para o ficheiro em que está. Tools → Coverage Studio → Getting Started abre estes passos como uma página com um botão para cada um; da primeira vez abre-se sozinho.
- Gere um ficheiro de trace de cobertura com o seu fluxo de teste normal.
- Paleta de Comandos (
Ctrl+Shift+P) →Fucini Coverage: Load Coverage. Comwatch.enabledativo (predefinição), um ficheiro correspondente carrega automaticamente. - Abra um ficheiro fonte coberto: a barra de estado mostra a sua percentagem, a vista Cobertura preenche-se, passar o cursor sobre uma linha mostra a sua contagem de acertos, e a execução aparece no painel Test Coverage nativo. Barras nas linhas não cobertas, um mapa de calor de contagens de acertos e contagens
×Nem linha estão a uma definição de distância (editorGutter.mode,hitCounts.inline).
Screenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).4. Produzir ficheiros de trace
Qualquer um dos seguintes é detetado automaticamente ao carregar:
Receitas completas para copiar e colar por compilador — incluindo Swift, Rust, Go, Python, .NET, PHP e mais — na página Receitas 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
O llvm-cov JSON é a entrada mais rica — transporta regiões, MC/DC e instanciações de templates C++ para além de linhas, ramos e funções.
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
| Formato | Ficheiro típico | Métricas adicionais |
|---|---|---|
| LCOV | lcov.info | linhas, ramos, funções |
| llvm-cov JSON | coverage.json | + regiões, MC/DC, instanciações |
| Cobertura XML | coverage.xml | linhas, ramos |
| JaCoCo XML | jacoco.xml | linhas, ramos, funções |
| Istanbul / nyc | coverage-final.json | instruções, ramos, funções |
| SimpleCov | .resultset.json | linhas |
| Clover XML | clover.xml | linhas, ramos, funções |
| OpenCover XML | coverage.opencover.xml | linhas, ramos, funções |
| coverage.py JSON | coverage.json | linhas, ramos |
| gcov / gcovr JSON | coverage.json | linhas, ramos, funções |
| Go coverage profile | coverage.out | linhas |
| SonarQube generic | coverage.xml | linhas, ramos |
| GNATcoverage XML (Ada) | *.xml | linhas, ramos, MC/DC |
| BullseyeCoverage XML | coverage.xml | linhas, condição/decisão |
| Visual Studio | *.coveragexml | linhas, ramos |
| Coveralls JSON | coveralls.json | linhas, ramos |
| Xcode xccov JSON | coverage.json | funções e totais por ficheiro — sem dados por linha |
| gcov plain text | *.gcov | linhas, ramos, chamadas de função |
| VectorCAST | coverage.xml | linhas, ramos, pares MC/DC, funções, chamadas de função |
| Testwell CTC++ | *.txt | linhas, condição/decisão |
| Lauterbach TRACE32 | *.xml | instruções, decisões, condições, MC/DC, funções, chamadas, código objeto |
| EMMA XML (Java) | coverage.xml | linhas |
| UCIS / Aldec UCDB | *.xml | instruções, ramos de decisão |
| NCover XML | Coverage.xml | linhas, funções |
| dotCover DetailedXML | dotCover.xml | linhas, funções |
| PIT (mutation) | mutations.xml | pontuação de mutação — sem cobertura |
| Stryker (mutation) | mutation-report.json | pontuação de mutação — sem cobertura |
Um projeto C++ nativo, medido a partir do Visual Studio
No Visual Studio. A cobertura de um projeto C++ do próprio Visual Studio era só para Enterprise, e o plugin gratuito OpenCppCoverage que preenchia a lacuna foi retirado. Tools → Coverage Studio → Run Native Project with Coverage pega no projeto de arranque — um .vcxproj — pergunta ao MSBuild para onde ele compila e com que toolset, e mede-o de uma de duas maneiras. Com o toolset ClangCL, havendo na máquina o llvm-profdata e o llvm-cov do LLVM (o componente C++ Clang tools for Windows do Visual Studio traz ambos), compila o projeto de novo para coverage\native\ com -fprofile-instr-generate -fcoverage-mapping, através de um ficheiro props que o MSBuild é instruído a importar primeiro — nada muda no projeto — corre o programa com LLVM_PROFILE_FILE definido, funde o perfil e exporta coverage\native\lcov.info, exato à região. Com qualquer outro toolset, estando o OpenCppCoverage instalado, compila o projeto tal como está — uma compilação Debug tem os PDB — e corre-o sob o OpenCppCoverage, que escreve coverage\native\opencppcoverage.xml. Cada comando vai para o painel Fucini Coverage, e o relatório é carregado e lembrado como o de uma execução de testes. A um projeto que não pode ser medido é dito porquê e o que instalar. MSBuild 17.8 (Visual Studio 2022 17.8) ou posterior, para a pergunta que lhe faz.
Screenshot pending — add assets/img/vs-native-run.gif (see SCREENSHOTS.md).5. Carregamento e deteção
Por predefinição, a extensão pesquisa a partir da raiz do espaço de trabalho. Especifique com mais precisão através de duas definições:
{
"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é relativa adefaultLocation(ou à raiz do espaço de trabalho quando não definida). - Uma entrada contendo
*é pesquisada recursivamente; um nome de ficheiro simples corresponde apenas diretamente na pasta base. - Quando
pathsestá vazio, a extensão procuracoverage.json, depoislcov.info, carregando o que encontrar primeiro. - Pick Coverage File usa os ficheiros que escolher em vez destes caminhos — cada escolha acrescenta-se ao conjunto e todos são combinados — até os descarregar ou editar estas definições.
- Variáveis — todas as definições de caminho expandem
${workspaceFolder},${workspaceFolderBasename},${userHome},${env:NAME},${command:id}e${config:section.key}. Uma variável que a extensão não conhece fica tal como foi escrita, pelo que uma gralha aparece no registo de deteção como o caminho que procurou, em vez de desaparecer.${command:id}executa primeiro esse comando — apenas numa área de trabalho fidedigna e no máximo cinco segundos —, pelo que${command:cmake.buildDirectory}acompanha o kit CMake selecionado. - Entradas URL — uma entrada
http(s)://é descarregada para o armazenamento da extensão em cada carregamento e carregada a partir daí; a vista Cobertura mostra o URL. Cada descarga é condicional (ETag / Last-Modified), pelo que um artefacto inalterado não descarrega nada, e quando uma descarga falha é carregada a última cópia descarregada, com o motivo na saída.remote.headersacrescenta cabeçalhosName: valuecom as variáveis expandidas,remote.refreshMinutesvolta a descarregar por temporizador, e um fragmento#lcov.infoindica o formato quando o próprio URL não termina num nome de ficheiro. - Globs de exclusão —
fuciniCoverage.ignoreretira ficheiros inteiros (vendorizados, gerados, de terceiros) da execução ao carregá-la, pelo que cada vista, gate e exportação conta sem eles; o resultado do carregamento diz quantos ficaram de fora e a saída nomeia-os. Os padrões comparam-se com o caminho relativo ao espaço de trabalho e com o absoluto, e um padrão sem/corresponde a um nome de pasta ou de ficheiro a qualquer profundidade, como no.gitignore. - Espaços de trabalho multi-raiz — cada pasta é detetada nos seus próprios termos:
defaultLocation,paths,pathRemap,ignore,watch.*eremote.*são lidos por pasta, pelo que o.vscode/settings.jsonda própria pasta ou a sua entrada no.code-workspacese aplica, e${workspaceFolder}numa entrada significa a pasta dessa entrada. Os ficheiros de cobertura de todas as pastas fundem-se numa só execução, a vista Cobertura agrupa os ficheiros por pasta, e uma pasta adicionada ao espaço de trabalho ou dele removida recarrega a cobertura por si. - Recarregar após uma tarefa —
watch.reloadAfterTasksnomeia tarefas (umlabeldo tasks.json, ousource: nametal como a lista Run Task o mostra) cujo fim recarrega a cobertura, esteja ou nãowatch.enabledligado — para compilações que o observador não consegue seguir. Uma entrada absoluta depathsfora do espaço de trabalho é sondada também, pelo que um ficheiro que aí apareça é carregado. - Progresso que pode cancelar — um carregamento de dez ou mais ficheiros de cobertura, ou de 8 MB ou mais deles, corre sob uma notificação de progresso com um botão Cancelar que indica o ficheiro a ser lido e a fase; um mais pequeno apenas faz girar a barra de estado. Cancelar deixa a execução anterior carregada e di-lo.
Desde a 1.2026.6 uma entrada absoluta também pode conter um wildcard: ${workspaceFolder}/build/coverage-merged/*.lcov.info carrega todos os ficheiros assim nessa pasta, e ** vale por qualquer profundidade. As pastas antes do primeiro wildcard são onde procura, e são observadas, pelo que um relatório que uma compilação aí escreva carrega-se por si. A edição para Visual Studio lê uma entrada destas da mesma maneira, e desde a 1.2026.5 um wildcard relativo é também aí pesquisado a qualquer profundidade, como sempre foi aqui.
Sem paths configurado, é carregado o primeiro dos nomes de relatório mais conhecidos que for encontrado sob a pasta base. Primeiro os quatro que a extensão sempre procurou — coverage.json, lcov.info, coverage.out, clover.xml — depois, desde a versão 0.2026.83, jacoco.xml, coverage.xml, cobertura.xml, coverage.cobertura.xml, coverage.opencover.xml e coverage-final.json, e por fim os locais onde as configurações predefinidas escrevem: coverage/ (nyc, Jest, vitest, PHPUnit, SimpleCov), target/site/jacoco/jacoco.xml (Maven), build/reports/jacoco/test/jacocoTestReport.xml (Gradle) e TestResults/*/coverage.cobertura.xml (dotnet test). Assim, um projeto Java ou .NET mostra a sua cobertura logo na primeira abertura, como um projeto lcov sempre fez.
Desde a 1.2026.3 uma solução .NET precisa de ainda menos: a pasta TestResults/<run>/ de cada projeto de testes está entre os locais conhecidos, não só a da própria pasta do espaço de trabalho, e o <user>_<machine>_<date>.cobertura.xml do coletor da Microsoft é encontrado ao lado do coverage.cobertura.xml do Coverlet — por isso uma solução cujos testes foram executados no Test Explorer do Visual Studio mostra a sua cobertura logo na primeira abertura, cada pasta de execução é carregada, e a fusão mantém para cada ficheiro o que diz a execução mais recente. E fuciniCoverage.ignore.generated, ativo por predefinição, deixa os ficheiros de designer e os gerados — *.Designer.cs, *.g.cs, *.generated.cs, *.razor.g.cs, AssemblyInfo, os usings globais, Migrations/ e obj/ — fora de cada total, página e exportação antes de ignore ser aplicado, pelo que uma tabela gerada que ninguém testa não custa à solução o seu gate.
No Visual Studio: cobertura após cada execução de testes. Execute os testes como sempre. Tools → Coverage Studio → Collect Coverage in Test Explorer… coloca um .runsettings com o coletor Cobertura da Microsoft ao lado da solução. O Visual Studio apanha-o quando Tools → Options → Test → Auto detect runsettings files está ativo; caso contrário, selecione-o uma vez em Test → Configure Run Settings. A partir daí cada execução escreve um relatório sob o projeto de testes, e a vigilância da solução carrega-o no momento em que aparece, fundido com o que quer que as definições nomeiem — quer venha do Test Explorer, de um terminal ou de um script. Nada se liga ao Test Explorer, por isso o Visual Studio 2026 e o Microsoft.Testing.Platform funcionam tal como estão. Run Tests with Coverage é o comando do VS Code: reconhece dotnet test, vitest, jest, pytest, go, cargo, maven, gradle, phpunit e ctest, executa os testes com a cobertura ativa na janela Output e carrega o que eles escreveram; um projeto de testes sem coverlet.collector é executado com o coletor que o SDK de testes inclui, e testRun.skipWhenTestsFail mantém no ecrã a última cobertura boa quando uma execução termina a vermelho.
Um artefacto de CI atrás de um token, reverificado a cada quarto de hora — o token fica no ambiente, nunca em 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
}
Screenshot pending — add assets/img/remote-tracefile.png (see SCREENSHOTS.md).Um recarregamento é silencioso de propósito — uma caixa de diálogo após cada compilação é uma pergunta com uma só resposta. O que não é silencioso é o ícone Coverage: enquanto a vista não estiver à sua frente, leva o número de tracefiles relidos, e a sua dica nomeia-os. Abra a vista e a contagem desaparece.
Screenshot pending — add assets/img/coverage-badge.gif (see SCREENSHOTS.md).Ficheiros que nunca devem contar, diga o ficheiro de cobertura o que disser sobre eles:
{
"fuciniCoverage.ignore": ["vendor/**", "**/*.generated.ts", "build/**"]
}
Um recarregamento quando a tarefa de testes termina, para uma compilação que o observador de ficheiros não consegue seguir — uma execução que substitui uma árvore de saída com ligações simbólicas, um relatório numa partilha de rede, um passo de cobertura que pós-processa o seu ficheiro:
{
"fuciniCoverage.watch.reloadAfterTasks": ["npm: test", "coverage-report"]
}
6. Combinar execuções
Cada entrada paths existente é carregada e fundida numa única execução. A fusão é determinística — o resultado não depende da ordem de carregamento — e um ficheiro medido por mais de um tracefile toma os seus números do que tiver a mtime mais recente no disco: a repetição própria de um módulo substitui o que uma execução mais ampla e antiga dizia dele, em vez de se somar. A vista de Cobertura mostra o que isso fez: cada linha de ficheiro nomeia o tracefile de onde vêm os seus números, o distintivo tem contorno onde esses números sobrepuseram um relatório mais antigo, cada linha de tracefile acima da árvore conta quantos dos seus ficheiros foram sobrepostos ou sobrepuseram outros, e clicar numa linha de tracefile realça os seus ficheiros na árvore até novo clique (coverageView.mergedMarks desliga o contorno e o realce).
Uma execução combinada pode conter mais do que as seis métricas clássicas, cada uma proveniente do relatório que a mede: chamadas de funções, código-objeto e uma pontuação de mutação a par de linhas, funções, regiões, ramos, MC/DC e instanciações. A vista Coverage mostra uma coluna por cada métrica que a execução contém — e nenhuma para as que não contém — ordenadas pelo peso que cada métrica tem na sua pontuação, a mais pesada primeiro, com qualquer largura — o que não cabe desliza para o lado em vez de desaparecer. Arraste-a para o painel inferior e passa a ser uma tabela. Os cartões da barra de estado, o relatório HTML e as exportações CSV e Markdown seguem a mesma regra: o que um relatório contém é mostrado, o que não contém é omitido em vez de ser impresso como um zero.
Screenshot pending — add assets/img/coverage-view-editor.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/coverage-view-columns.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/workspace-overview.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-workspace-overview.gif (see SCREENSHOTS.md).De que relatório vem um ficheiro
Quando vários relatórios carregados medem o mesmo ficheiro, o mais recente fica com ele por inteiro — o certo quando a nova execução de um módulo substitui o que uma execução mais antiga e mais ampla dizia. É errado quando os relatórios medem o mesmo código de propósito: o editor salta então entre eles a cada build, e cada um conta só parte da história. coverageFile.sources diz o que fazer em vez disso, por ficheiro. Três situações pedem-no:
- Um relatório é o melhor. O
coverage.jsondo llvm-cov traz MC/DC, umgcov.infodo GCC da mesma build só linhas e ramos: escolhacoverage.jsone guarde o outro para os poucos ficheiros que só o GCC compila. - Várias suites de testes de uma build. Os testes unitários, os de integração e os de hardware-in-the-loop escrevem cada um o seu relatório; cada um, sozinho, deixa de fora linhas que os outros executaram. Combinar, union: uma linha está coberta onde qualquer relatório a executou, e as contagens somam-se.
- Uma base de código, dois compiladores. As mesmas fontes compiladas pelo clang e pelo GCC seguem caminhos diferentes pelo código específico de cada toolchain — um intrínseco aqui, uma alternativa portável ali — e cada relatório diz que a outra metade nunca correu. Combinar, agree: uma linha só está coberta onde todos os relatórios que a medem a executaram, e as linhas em que divergem são marcadas a azul-petróleo. É essa a pergunta de uma verificação cruzada entre compiladores: o que exercitou de facto cada build que entrego?
Raramente escreve as regras à mão. Clique com o botão direito num ficheiro na vista Cobertura e escolha Choose Coverage Source... (ou execute Choose Coverage Source for This File... no ficheiro aberto): a lista mostra todos os relatórios que medem o ficheiro, cada um com as suas próprias linhas, ramos e MC/DC, e depois Combine them — agree e Combine them — union; escolha um e indique se vale para o ficheiro, a sua pasta ou um padrão. Clear Coverage Source for This File... retira a regra de novo. Nas definições, cada regra é um glob sobre os ficheiros, um glob sobre o relatório (um padrão sem / corresponde ao nome de ficheiro do relatório, {a,b} indica vários) e, para combinar, "combine": "agree" ou "union". Decide a primeira regra cujos ficheiros correspondem e cujo relatório mede o ficheiro; um ficheiro que só um relatório mede nunca lhe é retirado. Os ramos, o MC/DC e as regiões de um ficheiro combinado vêm do relatório mais rico neles. coverageFile.mergeStrategy: "order" decide os ficheiros sobre os quais nenhuma regra se pronuncia pela ordem de coverageFile.paths em vez das 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" }
]
}
O que vê: a linha do ficheiro na vista Cobertura indica o relatório de onde vêm os seus números ou, se combinado, todos os relatórios e o modo, com ≠ n para as linhas em disputa. A margem e o Annotated Source marcam essas linhas a azul-petróleo e dizem que relatório as executou e quantas vezes. O cartão que surge ao passar o rato sobre a barra de estado indica a fonte do ficheiro aberto e, para toda a execução, as regras em vigor e como foram decididos os restantes ficheiros. O samples/c-cross-check da demonstração é o caso dos dois compiladores, pronto a abrir. O Visual Studio também faz tudo isto: Choose Coverage Source... numa linha da vista Cobertura, e Choose e Clear Coverage Source for This File... em Tools > Coverage Studio.
Escolher e combinar fontes faz parte dos planos pagos. No Community o relatório mais recente ganha todos os ficheiros, tal como sem regra, e uma regra nas definições é indicada como não utilizada em vez de ser ignorada em silêncio.

bits.c a partir da vista Cobertura — o relatório do clang, o do GCC, ou ambos combinados.


bits.c, clang e GCC combinados por agree — a linha indica ≠ 4, e as quatro linhas que só uma build executou estão a azul-petróleo.
bits.c atinge 100% das suas linhas — e as linhas em que as builds divergem continuam a azul-petróleo.


7. Remapeamento de caminhos
O CI frequentemente regista caminhos absolutos da máquina de compilação que não existem na sua estação de trabalho. Reescreva-os com regras ordenadas:
{
"fuciniCoverage.pathRemap": [
{ "from": "/builds/ci/project", "to": "${workspaceFolder}" },
{ "from": "\\\\", "to": "/" }
]
}
As regras aplicam-se por ordem; a primeira correspondência vence por prefixo. Use isto para uniformizar diferenças de separadores Windows/Unix ou mapear um caminho de contentor para o seu checkout.
Raramente tem de escrever a regra você mesmo. O mais comum “carregou mas nada se acende” é um ficheiro de cobertura cujos caminhos vêm de um contentor ou de um checkout de CI (/build/src/a.c, /home/runner/work/repo/repo/src/a.c, C:\agent\_work\1\s\src\a.c) enquanto o espaço de trabalho tem src/a.c. Quando um carregamento deixa ficheiros sem correspondência, a extensão procura os nomes dos ficheiros no espaço de trabalho, infere a regra de prefixo que explica o maior número deles, regista-a como [FUCINI_REMAP_002], e o resultado do carregamento oferece Apply Suggested Remap — um clique acrescenta a regra a fuciniCoverage.pathRemap e recarrega. Suggest Path Remap Rule corre a mesma análise a pedido a partir da paleta. Nada é escrito sem o clique.
Um to pode usar ${workspaceRoot}, que representa a pasta do espaço de trabalho onde o ficheiro de cobertura está; num espaço de trabalho multi-raiz tenta primeiro essa pasta, depois cada uma das outras pastas que se verifique terem o ficheiro. As próprias regras são lidas por pasta, pelo que cada raiz de um espaço de trabalho multi-raiz pode ter as suas.
8. Cobertura no editor
- Margem e régua — por predefinição, a própria margem do editor mostra apenas constatações: barras MC/DC, triângulos de desde-a-última-execução, pontos de linhas editadas.
editorGutter.modeacrescenta barras só nas linhas não cobertas ou um mapa de calor de contagens de acertos (abaixo); a vista a cores de um ficheiro inteiro é o Annotated Source. - CodeLens de função — % de cobertura acima de cada função; clique para saltar para a sua primeira linha não coberta. Alterne com
codeLens.enabled. - Informação de ramos e MC/DC ao passar o cursor — passe o cursor sobre uma linha de decisão para ver contagens tomadas/não tomadas por ramo e uma tabela de vetores por condição. Ative uma barra de margem colorida com
mcdcGutter.enabled. - Avisos de código morto — funções com linhas mensuráveis e cobertura zero são assinaladas no painel Problems (
deadCode.enabled). - Next / Previous Uncovered — salte entre lacunas.
- Barra de estado — um item
$(dashboard) NN%global e um item por ficheiro, ambos coloridos de acordo com a pontuação composta; passe o cursor para ver uma tabela completa de métricas. - Distintivos do Explorador — distintivos de cobertura por ficheiro e por pasta, com a discriminação por métrica ao passar o rato. Desligados por predefinição: ligue-os com
explorerBadges.enabled. - Desde a última execução — um triângulo vermelho em cada linha executada na execução anterior e não nesta, um verde para o inverso, com a régua de visão geral e as contagens ao passar o rato.
- Buffers editados — cada marca, dica e CodeLens acompanha o texto enquanto edita, e retira-se de uma linha reescrita, onde um ponto cinzento diz porquê.
- Contagens de acertos em linha —
hitCounts.inlineescreve×12a seguir a cada linha em que começa uma instrução,×0incluído: o número que sempre esteve na dica ao passar o rato, sem passar o rato. Toggle Inline Hit Counts alterna-o; o menu da barra de estado oferece-o como Mostrar ou Ocultar, consoante o que se aplique. - Entradas por linha no painel Problems —
problems.perLinepõe um diagnóstico de informação, com um sublinhado ondulado no editor, em cada bloco contíguo de linhas que nunca correram num documento aberto (uma função morta de quarenta linhas é uma entrada, não quarenta) e, comouncoveredAndPartial, em cada linha cujo ramo nunca foi tomado. As entradas acompanham as suas linhas enquanto edita e desaparecem quando o documento fecha; a entrada por ficheiro atrás deproblems.enablednão muda. - Tom da linha —
lineHighlightcoloca um tom translúcido atrás das próprias linhas, para o que a margem marca (uncovered, ouheatmaptambém para as linhas executadas). Uma opção própria, para que a margem possa ficar limpa enquanto as lacunas são tingidas, ou o contrário. - Régua de visão geral —
overviewRulerdecide a faixa na barra de deslocamento independentemente da margem:follow(com as barras, como antes),uncovered(sempre, pelo que a margem pode estar desligada enquanto a barra de deslocamento continua a mapear as lacunas) ouoff. - Qual tracefile cobriu uma linha — com vários relatórios combinados, a dica com a contagem de execuções termina com Coberto por: e cada relatório que cobriu essa linha, incluindo o nome da suíte do
TN:do lcov; clicar numa linha de tracefile na vista Coverage ilumina as linhas que ele contribuiu em cada editor aberto.
Screenshot pending — add assets/img/codelens-hover.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/codelens-crap.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/jump-between-gaps.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/explorer-badges.png (see SCREENSHOTS.md).Modos de margem do editor
editorGutter.mode decide o que a própria margem do editor mostra sobre a cobertura, além das constatações que mostra sempre. off (a predefinição) é só essas. uncovered põe uma barra em cada linha que nunca correu e uma âmbar em cada linha com um ramo nunca tomado, e nada nas linhas cobertas, para que uma parede verde não esconda as três vermelhas. coverage acrescenta uma barra verde em cada linha coberta, para que o ficheiro inteiro se leia a vermelho, âmbar e verde nas cores da escala de cores. heatmap acrescenta antes um tom quente a cada linha executada, tanto mais quente quanto mais vezes correu — mostra quantas vezes uma linha correu, não se está coberta, pelo que um ficheiro a 100% fica aí entre o amarelo e o castanho, nunca verde. Choose Editor Gutter Mode... escolhe um a partir da paleta ou do menu da barra de estado; o botão de modo à direita da barra de estado, ou Alt+G, passa ao seguinte com um só toque (statusBar.showModeToggle esconde o botão). Ambos escrevem a definição. O exemplo liga em conjunto as barras nas linhas não cobertas e as contagens em linha:
{
"fuciniCoverage.editorGutter.mode": "uncovered",
"fuciniCoverage.hitCounts.inline": true
}
Screenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).
coverage — verde onde uma linha correu por inteiro, âmbar onde um ramo nunca foi tomado, vermelho onde nada correu. O item da barra de estado do ficheiro indica o relatório de onde vêm os seus números; o botão de modo ao lado diz Coverage.
Alt+G quatro vezes — heatmap, off, uncovered e de volta a coverage.
Quote.cs.O mapa de calor é relativo ao ficheiro. O tom de uma linha compara a sua contagem com a da linha mais quente do mesmo ficheiro, numa escala logarítmica, em cinco degraus — assim, o corpo de um ciclo que foi executado mil vezes e uma função que foi executada duas vezes são ambos visíveis, em vez de um abafar o outro, e um ficheiro em que tudo foi executado exatamente uma vez fica uniformemente quente em vez de uniformemente pálido. Num tema escuro a gama vai do verde-azeitona esbatido ao laranja vivo, num tema claro do amarelo pálido ao castanho: em ambos os casos mais cor significa mais execuções, e o vermelho fica reservado para as linhas que nunca foram executadas. lineHighlight: "heatmap" coloca os mesmos tons por trás do código como fundo, e hitCounts.inline escreve a contagem exata a seguir à linha.
{
"fuciniCoverage.editorGutter.mode": "heatmap",
"fuciniCoverage.lineHighlight": "heatmap",
"fuciniCoverage.hitCounts.inline": true
}
Screenshot pending — add assets/img/heatmap-dark.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/heatmap-light.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/heatmap.gif (see SCREENSHOTS.md).As cores são suas. colorScale.lowColor, midColor e highColor dão o vermelho, o âmbar e o verde da margem, dos tons de linha e de cada percentagem; heatmap.colors e heatmap.colorsDark guardam os cinco tons do mapa de calor para um tema claro e um escuro, da linha que correu menos vezes à que correu mais. A página de definições mostra o resultado antes de algo ser guardado: em Colour scale, uma pré-visualização fica à vista enquanto as linhas passam — o gradiente com os seus dois pontos de viragem, algumas percentagens nas suas cores, e um pequeno editor claro e um pequeno editor escuro pintados no modo coverage e no mapa de calor — e volta a ser pintada assim que uma cor é escolhida.
{
"fuciniCoverage.heatmap.colors": ["#e3f2fd", "#90caf9", "#42a5f5", "#1e88e5", "#0d47a1"]
}


A parte de uma linha que nunca foi executada
Uma linha está coberta ou não está, e a verdade fica muitas vezes a meio: return x > hi ? hi : x; foi executada, o seu ramo hi nunca foi. Com lineHighlight ativo, a parte nunca executada de uma linha executada é colorida no editor, para todos os formatos que trazem intervalos de colunas (llvm-cov, Istanbul, Go, dotnet-coverage) — os mesmos intervalos que o Annotated Source assinala. Apenas em linhas que foram executadas: uma linha que nunca foi executada já está assinalada por inteiro. Um template C++ conta como executado onde qualquer instanciação o tenha executado; o que cada instanciação fez é o que a métrica de instanciações indica.
Screenshot pending — add assets/img/partial-line.png (see SCREENSHOTS.md).Que testes executaram esta linha
Alguns relatórios dizem não só que uma linha foi executada, mas também que testes a executaram: coverage.py escrito com coverage json --show-contexts e dynamic_context = test_function em .coveragerc, OpenCover recolhido com -coverbytest, e um tracefile lcov escrito com uma secção por teste (TN:), cujas secções são somadas num só registo com um teste por linha. Passe o cursor sobre o início de uma linha, onde está a contagem de execuções, e os testes são indicados — abreviados para classe e método, os cinco primeiros pelo nome e os restantes como um número; o CodeLens da função diz quantos testes a executaram. Show Tests That Ran This Line — na Command Palette, no menu de contexto do editor, no Visual Studio em Tools → Coverage Studio ou com Ctrl+Shift+U, T — lista-os, do mais ativo para o menos, e abre o que escolher onde ele está escrito no espaço de trabalho. Uma execução dotnet test não sabe dizer que teste executou o quê; defina testRun.perTest e Run Tests with Coverage lista as classes de testes e corre-as uma de cada vez, cada relatório marcado com a sua classe, para que o hover, a lens e o comando possam responder também para .NET. A informação é guardada por ficheiro, pelo que sobrevive a uma fusão com um relatório que nada sabe sobre testes.
{
"fuciniCoverage.testRun.perTest": true
}
# .coveragerc
[run]
dynamic_context = test_function
coverage run -m pytest && coverage json --show-contexts
Screenshot pending — add assets/img/tests-per-line.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/tests-for-line.gif (see SCREENSHOTS.md).
Quote.cs — o teste que a executou, e Go to Test a abri-lo.Passou ou falhou, nas marcas
Uma linha coberta tem o mesmo aspeto quer o seu teste tenha passado quer não. Onde o relatório diz que testes executaram uma linha e o ficheiro de resultados do executor diz como terminaram, uma linha executada por um teste que falhou leva uma barra vermelha no início e uma faixa na régua de visão geral; a dica ao passar o cursor nomeia os testes que falharam, e Show Tests That Ran This Line escreve falhou ao lado de cada um. Quando um teste está vermelho, o sítio onde procurar é o código por onde ele passou. Os resultados são lidos em cada carregamento a partir da pasta de cada relatório — qualquer .trx, e os nomes que as ferramentas que escrevem o formato JUnit usam (TEST-*.xml, junit*.xml, test-results*.xml) — e de testResults.paths, como caminhos ou globs relativos à pasta. Run Tests with Coverage pede ao dotnet test um test-results.trx ao lado do relatório, pelo que com testRun.perTest ligado nada tem de ser configurado. testResults.enabled desliga a leitura.
{
"fuciniCoverage.testResults.paths": ["build/test-results/**/*.xml", "reports/junit.xml"]
}
Screenshot pending — add assets/img/pass-fail.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-pass-fail.gif (see SCREENSHOTS.md).Os testes que uma alteração toca
Uma execução completa responde devagar ao que Run Tests Affected by My Changes… responde de imediato: de todos os testes, quais passaram pelo código que acabei de editar? Pede-se ao git o diff da árvore de trabalho em relação a testImpact.baseRef — HEAD por predefinição, que é o que ainda não está em nenhum commit; origin/main para tudo o que o ramo altera — e os testes que executaram uma linha alterada são listados, primeiro o que executou a maior parte da alteração. Escolher um teste abre-o. Onde os relatórios vieram de uma execução por teste (testRun.perTest), a primeira entrada corre só esses testes, cada classe para o seu próprio relatório, pelo que os relatórios de todas as outras classes se mantêm e os totais continuam a ser os da suite inteira. Um teste que só executou linhas abaixo de uma inserção ou de uma remoção também é listado: de outro modo, o seu relatório nomearia as linhas erradas.
Screenshot pending — add assets/img/test-impact.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-test-impact.gif (see SCREENSHOTS.md).O menor número de testes que ainda executa todas as linhas
Show Minimal Test Set… responde a duas perguntas a partir das mesmas linhas por teste: que poucos testes continuariam a executar todas as linhas que a suite executa — para a execução rápida antes de um commit — e que testes não executam nenhuma linha que outro não execute já. Os testes escolhidos vêm primeiro, cada um com as linhas que acrescenta e as linhas que só ele executa; depois os restantes, cada um marcado como não acrescentando nada. A escolha é a gulosa — o teste que mais executa, depois o que mais acrescenta a esse — pelo que fica perto do conjunto mais pequeno e é a mesma de todas as vezes. Redundante por linhas não é redundante pelo que um teste verifica: um teste que não acrescenta nenhuma linha pode ainda ser o único que verifica um valor nessas linhas. A lista diz onde olhar quando se poda uma suite, nunca o que apagar.
Screenshot pending — add assets/img/minimal-test-set.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-minimal-test-set.png (see SCREENSHOTS.md).Correr este teste, com cobertura
Ponha o cursor num teste e corra Run This Test with Coverage — na Command Palette, no menu de contexto do editor, no Visual Studio em Tools → Coverage Studio ou com Ctrl+Shift+U, R — e só esse teste corre com cobertura ligada: o método de teste em que o cursor está, ou a classe de teste ou o bloco describe quando está entre métodos, ou o ficheiro quando está acima de todas as classes. O que está sob o cursor é lido a partir do texto, pelo que funciona para C#, VB e F# ([Fact], [Test], [TestMethod] e afins), JavaScript e TypeScript (it, test, describe) e Python (def test_…), seja qual for o serviço de linguagem instalado. A receita da pasta é restringida a ele — dotnet test --filter "FullyQualifiedName~…", jest ou vitest <file> -t "…", um node id do pytest — e o que ela escreveu é carregado como qualquer execução; um executor que não pode ser restringido di-lo, e Run Tests with Coverage corre-os todos.
Screenshot pending — add assets/img/run-this-test.gif (see SCREENSHOTS.md).
[Fact] — a execução na lista Tracefiles, as linhas por cima dos métodos a dizer que um teste executou o código.Go e Rust. Num ficheiro Go, o func TestXxx (ou Fuzz…, Example…) em que o cursor está corre sozinho, no seu próprio pacote e pelo seu nome exato — go test ./pkg/calc -run "^TestTotal$" — e fora de um teste corre o pacote do ficheiro. Num ficheiro Rust, a função #[test] corre pelo seu caminho na crate com --exact; com o cursor num mod e fora de qualquer teste, correm os testes desse módulo; um teste de integração em tests/ corre no seu próprio binário (--test api). A um executor só são entregues ficheiros da sua própria linguagem: um ficheiro TypeScript numa pasta Go recebe uma frase, não uma execução de coisa nenhuma.
Cobertura depois de cada guardar
Com testRun.onSave ligado, guardar um ficheiro de código corre os testes que o cobrem, com cobertura, um instante depois de guardar, e a margem acompanha. Numa solução .NET o projeto do ficheiro guardado é encontrado através do grafo dos .csproj e só correm os projetos de teste que o referenciam — diretamente, ou através de outros projetos — um dotnet test <project> cada; qualquer outro executor corre a sua receita inteira; um ficheiro que nenhum projeto possui e nenhum relatório mede não corre nada. Vários guardares seguidos são uma só execução, e uma execução já a decorrer não é interrompida. O resto é como Run Tests with Coverage o faz: o terminal, o painel Output, o relatório carregado. Desligado por predefinição — é um hábito a escolher, não uma predefinição a descobrir.
{
"fuciniCoverage.testRun.onSave": true
}
Screenshot pending — add assets/img/coverage-on-save.gif (see SCREENSHOTS.md).
testRun.onSave ligado — Quote.cs guardado, os testes correm sozinhos, a linha por cima do método muda.A própria aplicação, com cobertura
Uma execução de testes diz o que os testes percorrem. O que uma pessoa percorre — a clicar pelos ecrãs antes de um lançamento, a repetir os passos de um cliente — também é cobertura, e Run App with Coverage… recolhe-a. A aplicação .NET da pasta — um Exe, um WinExe, um projeto web ou worker, nunca um projeto de testes; uma escolha onde houver várias — é iniciada sob o dotnet-coverage da Microsoft numa consola própria, para que se possa escrever numa aplicação de consola, e corre até a fechar. O que percorreu é então carregado como qualquer execução, e numa sessão de cobertura é somado ao que os testes executaram. A forma como a aplicação terminou não conta contra a execução. A ferramenta é precisa uma vez: dotnet tool install --global dotnet-coverage.
Screenshot pending — add assets/img/run-app.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-run-app.gif (see SCREENSHOTS.md).Mutantes, e onde estão
Uma ferramenta de testes de mutação — PIT para Java, Stryker para JavaScript, C# e Scala, Mull para C e C++ — altera o código em pequenos pontos e executa os testes contra cada alteração. Uma alteração em que nenhum teste repara é um mutante sobrevivente: o código foi executado, e nada verificou o que ele fez. A pontuação de mutação diz quantos foram apanhados; desde a versão 0.2026.83 o editor diz onde estão os outros. Uma linha com um mutante leva uma nota no fim (⚑ 2 mutants survived), o texto alterado fica sublinhado quando o relatório indica que texto foi (o Stryker e o Mull fazem-no), a régua de visão geral tem uma faixa, e ao passar o cursor vê-se o que foi alterado, quantos testes o executaram e, para os mutantes que foram apanhados, que teste os apanhou.
Screenshot pending — add assets/img/mutant-hover.png (see SCREENSHOTS.md).Sobreviveu significa que os testes executaram o código alterado e todos passaram. Não testado (o no coverage do relatório) significa que nenhum teste executa esse código, pelo que nada poderia ter reparado. Os mutantes apanhados são contados ao passar o cursor e nunca assinalados, e os mutantes que nunca foram uma prova justa — um que não compilaria — ficam fora da pontuação. O Annotated Source tem uma linha por baixo de cada uma destas linhas e um botão Next Mutant (U), e os relatórios HTML têm uma secção Surviving Mutants com ligação à linha. Não é preciso ativar nada, e um projeto sem relatório de mutação não vê nada disto.
Screenshot pending — add assets/img/mutants.gif (see SCREENSHOTS.md).Um teste daria por isso? Uma execução de mutação no cursor
A execução de mutação de um projeto demora uma hora; a de uma função demora um minuto. Run Mutation Tests Here corre esse minuto: a função em que o cursor está — ou as linhas selecionadas, ou o ficheiro — é o que se manda o executor de mutação da pasta mutar, e o relatório dele é carregado ao lado da cobertura no ecrã, onde os mutantes sobreviventes são assinalados. Para C# é o Stryker.NET (dotnet tool install --global dotnet-stryker), a quem se indicam o intervalo de carateres e o projeto de testes que referencia o projeto do ficheiro; para JavaScript e TypeScript o StrykerJS, a quem se indicam as linhas; para Java o PIT com Maven, a quem se indica a classe. A forma como o executor terminou não conta contra a execução: uma pontuação abaixo do seu limiar é um código de saída, e continua a haver relatório. Um executor que não escreveu nada é indicado, com o que precisa de ter instalado.
Screenshot pending — add assets/img/mutation-here.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-mutation-here.gif (see SCREENSHOTS.md).A própria vista Test Coverage do VS Code
Com testCoverage.publish ligado (a predefinição), cada execução carregada vai também para a vista Test Coverage nativa do editor — o painel de cobertura do Test Explorer, as percentagens por ficheiro que ele põe no Explorador, e o próprio botão Show Inline Coverage do editor — como linhas, ramos e funções, com os detalhes carregados a pedido, venham de que ficheiro de cobertura vierem e sem nenhum adaptador de testes envolvido. Show in Test Coverage View publica a execução ativa e abre o painel, diga a definição o que disser; o menu da barra de estado oferece-o atrás de quickActions.showTestCoverage. Desligado, não aparece de todo nenhuma entrada Fucini Coverage no Test Explorer. Quando um ficheiro de trace nomeia os seus testes (as secções TN: do lcov), cada teste aparece em Fucini Coverage no Test Explorer e a vista pode filtrar a cobertura de um ficheiro por teste.
Screenshot pending — add assets/img/test-coverage-view.png (see SCREENSHOTS.md).Linhas não cobertas no painel Problems
Desligado por predefinição porque é ruidoso por natureza, e só para os documentos que estão abertos — uma execução de dois mil ficheiros não consegue inundar o painel. Independente de problems.enabled, que se fica por uma entrada por ficheiro:
{
"fuciniCoverage.problems.perLine": "uncoveredAndPartial"
}
Screenshot pending — add assets/img/problems-panel.png (see SCREENSHOTS.md).9. Cobertura diferencial
Restrinja as decorações às linhas alteradas em relação a uma referência base do git — ideal para rever exatamente o que um PR cobriu ou não:
{
"fuciniCoverage.gitDiff.enabled": true,
"fuciniCoverage.gitDiff.baseRef": "origin/main"
}
Screenshot pending — add assets/img/diff-coverage.png (see SCREENSHOTS.md).No Visual Studio. As mesmas duas definições, lidas dos mesmos ficheiros: a extensão executa ela própria git diff <baseRef> para cada ficheiro da execução e reduz a execução às linhas que o seu ramo alterou — na margem, na janela Coverage e nos gates. O painel Output diz o que o git respondeu quando não responde nada.
Um gate sobre o código novo
threshold.newCode é um gate próprio, ao lado dos que incidem sobre a execução inteira: das linhas alteradas em relação a gitDiff.baseRef que podem ser medidas, a percentagem mínima que tem de ter corrido. Um projeto a 62% no total pode, ainda assim, exigir que o que se escreve hoje seja testado. É contado em cada carregamento sobre a execução inteira, que continua no ecrã — gitDiff.enabled é outra coisa: as linhas alteradas no lugar da execução. Check Coverage Thresholds e as entradas de conformidade no painel Problems dão-no como falhado numa frase própria: New code 72.00% < 80% (18 of 25 line(s) changed against origin/main ran). Uma alteração sem nenhuma linha que possa ser medida — comentários, um README — não faz falhar nada.
{
"fuciniCoverage.threshold.newCode": 80,
"fuciniCoverage.gitDiff.baseRef": "origin/main"
}
Screenshot pending — add assets/img/new-code-gate.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-new-code-gate.png (see SCREENSHOTS.md).Código novo por tag, por autor, por data
Código novo são, por predefinição, as linhas que a árvore de trabalho altera em relação a gitDiff.baseRef — um ramo, um commit ou uma tag: "v1.4.0" é tudo desde essa versão. Duas definições perguntam o que uma ref não consegue. gitDiff.author recebe parte do nome de um autor, e código novo passa a ser as linhas que o git atribui a esse autor; gitDiff.since recebe um dia, e são as linhas alteradas pela última vez nesse dia ou depois, seja qual for o ramo por onde entraram; as duas juntas, as linhas desse autor desde esse dia. São lidas do git blame, um ficheiro de cada vez — o que uma execução grande vai sentir em cada carregamento — e tomam o lugar do diff na cobertura de diff e no gate acima. Uma linha ainda sem commit conta em qualquer dos casos.
{
"fuciniCoverage.gitDiff.author": "Ada",
"fuciniCoverage.gitDiff.since": "2026-09-01"
}
Screenshot pending — add assets/img/new-code-author.png (see SCREENSHOTS.md).Alterações indiretas: o que mudou sem que ninguém lhe tocasse
Um diff diz que linhas mudaram; duas execuções dizem que linhas deixaram de correr ou começaram a correr. As linhas que merecem atenção são aquelas em que os dois discordam: código que ninguém editou e que já não corre, porque um teste foi apagado, porque um ramo mais acima regressa agora mais cedo, porque uma fixture mudou. Uma revisão do diff não as consegue ver — estão fora dele por definição. Show Indirect Coverage Changes… lista-as por ficheiro, primeiro o ficheiro que mais perdeu, e abre o que escolher na primeira dessas linhas. A execução é comparada com a baseline de CI onde baseline.report nomeia uma — que é aquilo por que um pull request é julgado — e, caso contrário, com a execução anterior; as linhas que a árvore de trabalho altera em relação a gitDiff.baseRef, e tudo o que está abaixo de um ponto em que essa alteração desloca as linhas do ficheiro, ficam de fora.
Screenshot pending — add assets/img/indirect-changes.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-indirect-changes.png (see SCREENSHOTS.md).10. A pontuação composta
Em vez de reportar seis números, a extensão combina-os numa única Média Harmónica Ponderada (WHM). Para métricas com percentagens pᵢ e pesos wᵢ:
WHM = ( Σ wᵢ ) / ( Σ wᵢ / pᵢ )
Uma média harmónica é dominada pelo seu termo mais pequeno, pelo que uma métrica fraca não pode ser mascarada por uma perfeita — exatamente a propriedade que se deseja de um gate de segurança. Pesos predefinidos:
| Métrica | Peso | Justificação |
|---|---|---|
| MC/DC | 4 | IEC 61508 SIL 3–4 / ISO 26262 ASIL C–D / DO-178C DAL A–B. |
| Ramos | 2 | IEC 61508 SIL 2+ / ISO 26262 ASIL B+. |
| Condições | 3 | Entre os ramos e MC/DC (DO-178C, ISO 26262). |
| Regiões | 1.5 | Caminhos dentro de uma instrução (p. ex. curto-circuito parcial). |
| Linhas | 1 | IEC 61508 SIL 1+ / ISO 26262 ASIL A+. |
| Funções | 1 | Verificação de código morto. |
| Instanciações | 0.5 | Cobertura de modelos C++; o âmbito mais estreito. |
| Chamadas de funções | 1 | Locais de chamada que foram executados (gcov, VectorCAST, Testwell CTC++, TRACE32). |
| Código-objeto | 0 | Desativado a menos que lhe atribua um peso: engloba a cobertura de instruções. |
| Pontuação de mutação | 0 | Desativada a menos que lhe atribua um peso: não é cobertura. |
Defina qualquer peso como 0 para excluir essa métrica da pontuação. As métricas ausentes dos dados (por exemplo, MC/DC numa execução lcov simples) são simplesmente omitidas.
O código-objeto e a pontuação de mutação pesam 0 até que decida o contrário (whmWeights.objectCode, whmWeights.mutation). A cobertura de código-objeto engloba a cobertura de instruções, pelo que ponderar ambas conta duas vezes a mesma evidência; uma pontuação de mutação não é de todo cobertura — um conjunto de testes pode executar todas as linhas e não detetar nada. Ainda assim, ambas têm uma coluna própria e um limiar próprio.
Cobertura de condições
a && b é uma decisão — dois ramos — e duas condições com quatro resultados. Um conjunto de testes pode percorrer ambos os ramos e nunca ver b falso: a cobertura de ramos está completa e a cobertura de condições é de três em quatro. Este nível situa-se entre a cobertura de ramos e MC/DC na DO-178C e na ISO 26262, e desde a versão 0.2026.83 é uma métrica própria em vez de estar diluída nos ramos: uma linha nos cartões da barra de estado, uma coluna na vista Coverage, nos relatórios e nas exportações, um peso de 3 na pontuação (whmWeights.conditions) e um gate (threshold.conditions; sem gate no perfil standard, 100 no perfil safety).
Lidas a partir das sondas condition do BullseyeCoverage, de uma exportação cond do TRACE32 e do GCC 14 compilado com -fcondition-coverage. Um relatório que não distingue condições de decisões não tem essa linha, coluna nem peso. Se utiliza o Bullseye ou o TRACE32: as condições contavam até agora como ramos, pelo que a sua percentagem de ramos muda com esta versão e, com o novo peso, também a sua pontuação composta; defina whmWeights.conditions como 0 para obter a pontuação tal como era.
GCC 14, linha a linha. -fcondition-coverage faz o gcov dizer que resultado de que condição falta — a condição 1 nunca verdadeira, a condição 0 nunca num sentido nem no outro — e cada condição é assinalada na sua linha e nomeada na dica ao passar o cursor, a partir do JSON do gcov e da sua listagem em texto (condition outcomes covered 3/6). A métrica está onde estão as outras: threshold.conditions serve-lhe de gate e fica sem avaliação onde uma execução não tem esse valor, Copy Coverage Summary tem uma coluna de condições, badge.metric aceita conditions, e a caixa de pesquisa aceita conditions < 80. O valor de ramos de uma função deixa de fora os resultados das suas condições, tal como o do ficheiro e o da execução.
Screenshot pending — add assets/img/gcc-conditions.png (see SCREENSHOTS.md).Complexidade e CRAP
Alguns relatórios contêm a complexidade ciclomática de cada função: OpenCover (que é o que o Coverlet escreve), JaCoCo, Clover e Cobertura. Quando assim é, a extensão calcula uma pontuação CRAP — Change Risk Anti-Patterns — para a função, a partir dessa complexidade e da cobertura que ela própria mediu:
CRAP = complexity² × (1 − coverage)³ + complexity
Uma função simples e totalmente testada obtém a sua própria complexidade e nada mais; uma função complexa e mal testada obtém uma pontuação na ordem das centenas. No exemplo em C# do projeto de demonstração, Price() tem complexidade 22 e cerca de 37% das suas linhas cobertas, o que dá 142.2, enquanto Shipping() tem complexidade 12 e está totalmente coberta, o que dá 12. O limite habitual é 30: uma função que o atinja ou ultrapasse é listada em Riskiest Methods no relatório HTML, começando pela pior.
A complexidade e a pontuação aparecem no CodeLens da função e junto à função no código-fonte anotado. Max CRAP é a pontuação mais alta de qualquer função de um ficheiro — a pior, não uma média — e é uma coluna na vista Coverage, no relatório HTML e nas exportações CSV e Markdown. É informação: não tem limiar nem peso na pontuação composta. Os relatórios que não contêm complexidade (lcov, gcov, Istanbul, coverage.py) não têm CRAP, nem tão-pouco uma coluna vazia.
Desde a versão 0.2026.83, C e C++ também a têm. O llvm-cov não indica qualquer complexidade, pelo que esta é contada a partir dos dados de ramos que o relatório já contém: as condições escritas no próprio ficheiro da função, mais um — a definição de McCabe, e o que as ferramentas ao nível do código-fonte contam para .NET e Java. As condições que resultaram de uma macro de outro ficheiro, cada assert por exemplo, não são contadas.
Screenshot pending — add assets/img/riskiest-methods.png (see SCREENSHOTS.md).Risk hotspots, e que ficheiros mostrar
Sob a árvore da vista Coverage, Risk hotspots lista as funções onde código complexo se encontra com pouca cobertura, da pior para a melhor, cada uma abrindo o seu ficheiro na função. Uma função qualifica-se pela pontuação CRAP — hotspots.crapThreshold, 30 por predefinição, o valor que os autores da métrica propuseram — ou só pela complexidade ciclomática, hotspots.complexityThreshold, desligado por predefinição; só os relatórios que trazem a complexidade (OpenCover, Cobertura do Coverlet, JaCoCo, llvm-cov) têm algum. A Community vê a contagem e a pior pontuação; a lista ordenada é Pro. Ao lado da ordenação, uma segunda lista pendente diz que ficheiros a árvore mostra — todos, os ficheiros com lacunas, os ficheiros não testados, ou os ficheiros alterados desde a última execução; as pastas seguem os seus ficheiros e mantêm os seus próprios números. Ambos estão também no Visual Studio, na janela Coverage.
Screenshot pending — add assets/img/vs-hotspots.png (see SCREENSHOTS.md).Namespaces, classes e métodos
Para um relatório .NET que nomeia as suas classes — Cobertura e o coverage.cobertura.xml do Coverlet, OpenCover — um terceiro menu pendente, Folders / Namespaces, desenha a mesma execução como namespaces, classes e métodos: o número de um namespace é a soma dos das suas classes, o de uma classe o dos seus métodos, exatamente como o de uma pasta é o dos seus ficheiros, com a mesma ordenação e o mesmo filtro. Uma linha de método abre o ficheiro no método; uma classe declarada sem namespace fica sob (no namespace). A escolha é escrita em coverageView.perspective; uma execução que não traz nomes de classes não tem menu pendente e mostra as suas pastas. No Visual Studio a janela Coverage tem o mesmo menu pendente.
Screenshot pending — add assets/img/namespace-perspective.png (see SCREENSHOTS.md).
Pesquisar na árvore
Por baixo dos botões e dos menus pendentes, uma caixa de pesquisa. Uma palavra mantém as linhas cujo nome ou caminho a contém — todas as palavras escritas têm de lá estar; uma comparação mantém as linhas cujo valor a satisfaz — < 80% sobre a pontuação, lines >= 90, branches = 0, functions != 100, mcdc < 50 — e invoice < 80 exige ambas. As linhas de método da perspetiva por namespace e os risk hotspots são pesquisados juntamente com os ficheiros, pelo que uma função é encontrada onde a execução a tem. A árvore é filtrada à medida que escreve, na página, sem redesenhar; uma pasta que contém uma correspondência abre-se por ela e volta a fechar-se quando a caixa fica vazia; Esc limpa-a. A mesma caixa, a mesma gramática, no Visual Studio.
Screenshot pending — add assets/img/tree-search.gif (see SCREENSHOTS.md).lines < 80.A árvore acompanha o editor
O ficheiro que está a ver é destacado na vista Coverage, as pastas acima dele são abertas e a sua linha é deslocada para ficar à vista — já não é preciso procurar na árvore o ficheiro que já está aberto. De resto, a árvore mantém a sua posição de deslocamento, e nada é redesenhado. coverageView.followActiveEditor, ligado por predefinição, desliga-o para quem prefira deixar a árvore onde a pôs.
Screenshot pending — add assets/img/follow-editor.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-follow-editor.gif (see SCREENSHOTS.md).11. Controlo de conformidade
O veredito COMPLIANT / NON-COMPLIANT (mostrado na vista de código-fonte anotado, no relatório HTML e em ambos os popups da barra de estado) é determinado por limiares por métrica e um modo:
Screenshot pending — add assets/img/statusbar.png (see SCREENSHOTS.md).| Modo | COMPLIANT quando… |
|---|---|
strict (default) | cada métrica verificada individualmente atinge o seu próprio limiar — sem cedências. |
whm | a única pontuação composta ponderada atinge threshold.weighted. |
both | são cumpridos tanto o controlo ponderado COMO o controlo estrito por métrica. |
either | é cumprido o controlo ponderado OU o controlo estrito por métrica (o mais permissivo). |
Um limiar de 0 desativa esse gate, e uma métrica que o relatório não contém nunca é avaliada. O que vale um limiar que não definiu é decidido pelo perfil descrito mais abaixo. Execute Fucini Coverage: Check Coverage Thresholds para avaliar sob pedido.
No Visual Studio. Tools → Coverage Studio → Check Coverage Thresholds julga a execução contra as mesmas chaves threshold.* e di-lo na barra de estado e no painel Output; com compliance.diagnostics, problems.enabled, problems.perLine ou deadCode.enabled as ocorrências ficam na Error List ao lado das do próprio compilador — uma entrada por ficheiro abaixo de um gate, uma por intervalo não coberto, uma por função que nunca correu — cada uma abrindo o seu ficheiro na linha.
Screenshot pending — add assets/img/vs-error-list.png (see SCREENSHOTS.md).Perfis de limiares
threshold.profile decide o que vale um limiar que não definiu. standard, a predefinição desde a versão 0.2026.82, é o que se pode exigir a um projeto comum que não esteja relacionado com a segurança funcional. safety coloca todos os gates em 100 — o que um safety case exige, e exatamente o que era distribuído até à versão 0.2026.81.
| Métrica | standard | safety |
|---|---|---|
| Linhas | 80 | 100 |
| Funções | 80 | 100 |
| Regiões | 75 | 100 |
| Ramos | 70 | 100 |
| Pontuação composta | 75 | 100 |
| MC/DC, instanciações, chamadas de funções, código-objeto | sem gate | 100 |
| Condições | sem gate | 100 |
| Pontuação de mutação | sem gate | sem gate |
Um limiar que tenha definido prevalece sobre qualquer dos perfis. O exemplo fixa o gate dos ramos em 90 e tudo o resto em 100; para exigir 100 apenas a algumas métricas, mantenha standard e defina essas manualmente. Uma ressalva decorre do modo como as definições funcionam: um valor igual à predefinição de fábrica não se distingue da ausência de valor, pelo que com safety um limiar escrito exatamente com o seu valor padrão — 80 para as linhas, por exemplo — continua a contar como 100.
{
"fuciniCoverage.threshold.profile": "safety",
"fuciniCoverage.threshold.branch": 90
}
Screenshot pending — add assets/img/threshold-profile.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/threshold-profiles.gif (see SCREENSHOTS.md).Se contava com as predefinições antigas, será avaliado com mais indulgência depois de atualizar para a versão 0.2026.82 até selecionar safety. Uma instalação que já tenha sido utilizada antes é informada disso uma única vez, com um botão Keep 100% (safety) que escreve o perfil nas suas definições de utilizador; num projeto partilhado, coloque-o também nas definições da área de trabalho, para que todos sejam avaliados da mesma forma. Configure Coverage Compliance & Thresholds... apresenta o perfil acima da grelha de limiares, e a sua pré-visualização em tempo real avalia com os gates efetivamente em vigor. Em todos os cartões e relatórios, uma métrica cujo gate esteja desativado mostra o seu valor com um traço neutro em vez de um visto ou de uma cruz.
Screenshot pending — add assets/img/statusbar-metrics.png (see SCREENSHOTS.md).11a. Cobertura de código objeto
Todas as outras métricas aqui são medidas a partir do código-fonte: uma ferramenta instrumenta o seu código, a compilação instrumentada corre, e os contadores dizem que instruções, ramos ou condições foram exercitados. A cobertura de código objeto mede outra coisa — quanto do binário construído foi realmente executado, contado em bytes de instruções, observando o fluxo de instruções em vez de instrumentar o código-fonte. Isso importa porque um compilador emite código que nenhuma linha do seu código-fonte justifica: verificações de limites de arrays, tabelas de salto de switch, despejos de registos, sondas de pilha, chamadas a rotinas auxiliares de execução para divisão ou vírgula flutuante em núcleos sem a instrução. É também a única métrica aqui que responde a isto cobre assembly? — o assembly escrito à mão nunca é instrumentado e uma ferramenta baseada no código-fonte não lhe chega. A DO-178C é explícita quanto ao motivo: no nível A, onde um compilador ou linker gera código que não é diretamente rastreável até instruções do código-fonte, o objetivo 6.4.4.2b exige verificação adicional exatamente desse código gerado.
Subsume a cobertura de instruções: toda instrução executada veio de uma instrução do código-fonte, logo 100% de cobertura de código objeto implica 100% de cobertura de instruções. O inverso não se verifica, e é justamente essa assimetria que justifica medi-la. Daí decorrem duas coisas. Não tem qualquer peso na pontuação composta, porque calcular a média de duas medidas das mesmas execuções conta a mesma prova duas vezes; em vez disso é controlada por fuciniCoverage.threshold.objectCode — um requisito e não um peso, que é como a norma o pede. E a diferença é o que interessa: uma execução com 100% de cobertura de linhas e menos de 100% de cobertura de código objeto localizou exatamente o código gerado pelo compilador que o seu código-fonte não justifica, pelo que o cartão de conformidade diz 312 bytes nunca executados, com 100% de cobertura de linhas em vez de o esconder como «94%». O inverso — um binário inteiro dado como executado enquanto o seu código-fonte não o foi — é uma contradição e não uma pontuação baixa: quase sempre um ficheiro de trace desatualizado de um dos lados de uma fusão, ou nomes de módulos que nunca corresponderam a caminhos de ficheiros. É comunicado como constatação.
A cobertura de código objeto exige que o binário corra onde as suas instruções possam ser observadas. Há três caminhos e diferem enormemente em custo. Só o terceiro produz cobertura de código objeto; os dois primeiros estão aqui porque resolvem um problema afim, que muitas vezes é o que vale realmente a pena resolver.
- Uma compilação instrumentada, a correr no alvo. Os compiladores cruzados GCC aceitam
-fprofile-arcs -ftest-coverage, pelo que a instrumentação que funciona numa estação de trabalho funciona no alvo — exceto que um sistema bare-metal não tem sistema de ficheiros onde escrever os contadores.gcda, e muitas vezes não temexit()em que os escrever. Os contadores vivem na RAM de qualquer forma, por isso a solução é despejar essa memória e reconstruir os ficheiros fora do alvo; oembedded-gcovdo JPL da NASA (Apache-2.0) faz exatamente isso, sem sistema de ficheiros, sistema operativo ou biblioteca C padrão. Isto dá cobertura de instruções, ramos e funções de uma compilação feita pelo seu compilador cruzado, para o seu conjunto de instruções, no seu hardware — não cobertura de código objeto, e o binário medido está instrumentado, logo maior e mais lento do que o que envia. Carregue o resultado como LCOV, gcovr JSON, gcov JSON ou, numa toolchain anterior ao GCC 9, como a listagem em texto simples.gcov. - Um simulador do conjunto de instruções. Execute o binário real do alvo num simulador e derive a cobertura dos endereços executados: sem hardware, sem instrumentação, sem sonda e, porque observa instruções, pode produzir cobertura de código objeto genuína. O limite é a fidelidade: um simulador modela bem o núcleo e menos bem os periféricos, pelo que deve tratar com desconfiança os resultados de sistema completo, a menos que ele modele de perto o seu silício.
- Trace no chip e um depurador. A via de grau de certificação, e a única verdadeiramente não intrusiva: a unidade de trace do núcleo comunica o fluxo de instruções a um depurador, que o converte em cobertura. Nada é instrumentado, o tamanho do código não muda e a temporização não é afetada — e é isso que faz do resultado prova sobre o binário que realmente envia. Verifique o silício antes de o orçamentar: em muitas famílias de microcontroladores o trace completo só existe numa variante de emulação ou desenvolvimento, com um grande buffer de trace e uma porta rápida, ao passo que as peças de produção expõem uma unidade de trace reduzida, cujo recurso do fabricante é um trace por software que instrumenta o código e consome tempo de CPU — eliminando precisamente a propriedade pela qual essa via foi escolhida.
Muitos projetos embutidos medem a cobertura compilando os mesmos códigos-fonte para a máquina de desenvolvimento e correndo ali os testes unitários. É rápido, não precisa de hardware, e é a opção predefinida certa para a maioria das equipas — mas vale a pena ser claro sobre o que essa evidência realmente descreve: um compilador diferente, um otimizador diferente, um conjunto de instruções diferente e um binário diferente daquele que é entregue. Para a maior parte do software isso é um compromisso aceitável e bem compreendido. Para trabalho avaliado segundo a IEC 61508, ISO 26262 ou DO-178C, esta é a objeção padrão de anfitrião contra alvo, e os caminhos acima são as respostas padrão a ela — o primeiro fecha-a para a cobertura de código-fonte, o terceiro para o código objeto.
Hoje, a exportação lida para código objeto é a do COVerage.EXPORT.ListModule do Lauterbach TRACE32 com metric="object"; carregue-a como qualquer outro ficheiro de trace. Esta métrica é pontuada e controlada apenas com uma licença paga e durante o período de avaliação. Uma instalação Community não a pontua — mas é informada quando um ficheiro de trace a contém, porque um veredito de conformidade que omitisse silenciosamente a evidência mais forte do ficheiro seria pior do que um que diz o que omitiu.
12. Excluir linhas que não são código
Com excludeComments ativo (predefinição), as instruções que caem inteiramente em linhas apenas de comentário ou em branco são excluídas dos totais — isto também neutraliza uma particularidade conhecida do llvm-cov/gcov em que uma contagem de acertos aleatória cai num comentário. Os marcadores padrão também são respeitados:
x = risky(); // LCOV_EXCL_LINE
// LCOV_EXCL_START
debug_only_block();
// LCOV_EXCL_STOP
As diretivas do pré-processador também não contam como código, em C, C++, Objective-C, CUDA e C#: uma linha que começa com # — #define, #include, #if — e as linhas para as quais uma barra invertida final a prolonga. O gcov atribui cada utilização de uma macro à linha em que está definida, pelo que um cabeçalho cuja única linha reportada era #define CHANNEL_COUNT (33U) aparecia como 100% coberto porque um ciclo no ficheiro .c corria até esse valor, e um cuja constante ninguém usava aparecia a 0%. Um cabeçalho assim já não tem nada para medir e não é listado.
Defina excluded.includeInTotals como true para contar as linhas excluídas de qualquer forma.
Deixar de fora um ficheiro ou uma pasta, a partir da árvore
Clique com o botão direito num ficheiro ou numa pasta da vista Coverage e escolha Exclude from Coverage — está também entre as ações de caminho da linha — ou corra Exclude This File from Coverage sobre o ficheiro aberto: o caminho do ficheiro relativo ao espaço de trabalho, ou o /** da pasta, vai para fuciniCoverage.ignore nas definições da pasta, uma só vez, e o recarregamento tira-o de cada total e de cada página; o padrão fica lá para poder ser retirado de novo. No Visual Studio o menu da linha e Tools → Coverage Studio têm os mesmos dois comandos, que escrevem a mesma definição no mesmo ficheiro.
Screenshot pending — add assets/img/exclude-from-tree.gif (see SCREENSHOTS.md).
fees.ts — a árvore sem ele, o padrão em .vscode/settings.json.Atributos e namespaces, para .NET
Duas definições leem a partir da fonte o que o relatório não sabe dizer. ignore.attributes — ExcludeFromCodeCoverage por predefinição — exclui a classe, o método ou a propriedade por baixo de um atributo que ela nomeia, como LCOV_EXCL_START/STOP o fariam, seja qual for a ferramenta que escreveu o relatório: o Coverlet respeita o atributo, o OpenCover, o dotCover e um lcov convertido não, e agora todos concordam. Nomes com ou sem o sufixo Attribute, com ou sem namespace; acrescente GeneratedCode, Obsolete ou os seus. ignore.namespaces deixa fora cada ficheiro cuja declaração de namespace corresponde a um prefixo, com * como caráter universal — Acme.Generated, Acme.*.Migrations, *Tests — e o painel Output nomeia os ficheiros que retirou. Ambas são lidas na mesma passagem que lê os marcadores nos comentários, em ambas as edições.
{
"fuciniCoverage.ignore.attributes": ["ExcludeFromCodeCoverage", "GeneratedCode"],
"fuciniCoverage.ignore.namespaces": ["Acme.Generated", "*.Migrations"]
}
Excluir a partir do editor
Selecione as linhas e escolha Exclude Selection from Coverage na lâmpada, no menu de contexto do editor ou na Command Palette — no Visual Studio na lâmpada (Ctrl+.), no menu do botão direito da janela de código, em Tools → Coverage Studio ou com Ctrl+Shift+U, X — e a exclusão é escrita onde está o código: [ExcludeFromCodeCoverage] por cima de uma classe, um método ou uma propriedade C#, VB ou F#, com o nome curto quando o ficheiro já importa System.Diagnostics.CodeAnalysis e com o nome completo quando não importa, para que nenhum using tenha de ser acrescentado; LCOV_EXCL_LINE no fim de uma só linha de código; LCOV_EXCL_START e LCOV_EXCL_STOP à volta de várias, com a indentação da primeira — com o sinal de comentário da própria linguagem, //, #, ', -- ou ;. Um só passo de anular. A lâmpada oferece-o também numa linha que as entradas do Problems marcam como não coberta. Uma linha já marcada, ou um membro que já tem o atributo, fica como está.
Screenshot pending — add assets/img/exclude-selection.gif (see SCREENSHOTS.md).
LCOV_EXCL à volta de um ramo, depois [ExcludeFromCodeCoverage] por cima de um método.Só os ramos, e os marcadores do gcovr
Um else defensivo, um default: a que nenhum valor chega, o braço que um compilador acrescenta para uma exceção: a linha corre e deve contar, e só o seu ramo não pode ser tomado. LCOV_EXCL_BR_LINE e LCOV_EXCL_BR_START … LCOV_EXCL_BR_STOP retiram da contagem os ramos das suas linhas e deixam lá as linhas. LCOV_EXCL_EXCEPTION_BR_LINE e a sua região retiram ainda menos — só os braços a que uma exceção leva, onde o relatório diz quais são, como faz o JSON do gcov. Cada marcador é lido também com os prefixos do gcovr: GCOVR_EXCL_LINE, GCOVR_EXCL_START, GCOVR_EXCL_BR_LINE, GCOV_EXCL_STOP e os restantes significam o que significam os LCOV_EXCL_, pelo que uma fonte escrita para o gcovr se lê aqui da mesma maneira, seja qual for a ferramenta que fez o relatório. Não é lido: GCOVR_EXCL_FUNCTION — nada nessa linha diz onde a função acaba.
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
Screenshot pending — add assets/img/branch-markers.png (see SCREENSHOTS.md).Dizer porquê: exclusões justificadas
Retirar código da contagem é uma afirmação — "isto não pode ser testado", "isto é um auxiliar de desenvolvimento" — e, ao abrigo da DO-178C, da ISO 26262 ou da IEC 61508, uma afirmação que altera o número em que um certificado assenta tem de ficar escrita e poder ser revista. Por isso uma exclusão pode dizer porquê, no sítio onde é escrita: o texto a seguir a LCOV_EXCL_LINE ou LCOV_EXCL_START, ou a 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) { /* … */ }
As razões são lidas em cada carregamento e o log conta-as. Export Coverage Report… escreve a lista — exclusões e as suas justificações, em Markdown ou CSV: o ficheiro, as linhas, a forma como foi escrita, e a justificação ou none given. Um ficheiro que ficou sem nada mensurável continua nessa lista. Com exclusions.requireReason ligado, uma exclusão que não dá razão é uma constatação: um aviso no painel Problems na sua linha, e uma falha de Check Coverage Thresholds. Exclude Selection from Coverage pede então primeiro a razão e escreve-a com o marcador ou como a Justification do atributo; se o pedido for dispensado ou deixado vazio, nada é excluído.
Screenshot pending — add assets/img/justified-exclusions.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-justified-exclusions.png (see SCREENSHOTS.md).12a. Esta cobertura ainda descreve este ficheiro?
A cobertura lida de um tracefile descreve o código tal como estava quando os testes correram, e a maioria dos formatos nada diz sobre qual versão era essa. Por isso, cada ficheiro no painel de Cobertura está num de três estados:
- ✓ Verificado — o tracefile regista o que dizia cada linha medida, e continua a corresponder ao ficheiro.
- Sem marca — não refutado. Nada contradiz a cobertura e nada a confirma. É o estado normal.
- ⚠ Refutado — o próprio ficheiro refuta a sua cobertura. A linha fica esbatida e a dica diz o que foi encontrado.
Só dois formatos podem merecer a marca, porque só dois registam algo sobre o código que mediram: lcov escrito com --checksum (desligado por predefinição no geninfo; o seu propósito documentado é precisamente impedir que se combine a cobertura de duas versões de um ficheiro) e GNATcoverage XML, que inclui o texto de cada linha medida. Vale a pena ligar a opção do lcov.
O aviso não precisa de nenhum dos dois e funciona com todos os formatos: cobertura registada para lá do fim do ficheiro, uma função com nome que já não está onde o relatório a coloca, ou linhas executadas que estão em branco no ficheiro. Os carimbos de data/hora nunca chegam por si sós — um git checkout altera todos sem mudar um byte —, pelo que um carimbo alterado é, no máximo, um motivo para olhar de novo. A verificação corre ao carregar a cobertura e de novo sempre que um ficheiro é guardado ou muda no disco, pelo que a marca segue o ficheiro: uma edição que contradiz a execução coloca-a, um checkout que repõe a versão medida retira-a. A dica diz exatamente o que o provou. Defina staleWarning.enabled como false para desligar tudo isto.
12b. Não medido versus não coberto
Um ficheiro que a execução nunca menciona está não medido: nenhum teste o carregou, pelo que nenhuma ferramenta escreveu uma linha sobre ele. Não é o mesmo que não coberto — medido, com zero acertos — e a extensão nunca pontuou um ficheiro ausente como 0%. O que não fazia, até à 0.2026.69, era mostrar de todo os ausentes: um módulo sem qualquer teste nunca aparecia na árvore, nos totais ou na verificação de limiares, e um leitor via “92%” para um projeto com metade dos ficheiros nunca exercitados.
Agora, com uma execução carregada, o item por ficheiro da barra de estado diz not measured para um ficheiro fonte do tipo da própria execução que a execução não contém — “do tipo da execução” significando que tem uma das extensões de ficheiro que a execução mediu, pelo que os cabeçalhos e as fontes de um projeto em C são candidatos e os seus scripts Python não. Tudo o resto é opcional através de fuciniCoverage.unmeasured.mode:
off(predefinição) — nada mais muda.list— a vista Cobertura recebe um grupo Não medidos no fundo que nomeia cada ficheiro desses, cada linha abrindo-o; o resultado do carregamento conta-os; os distintivos marcam-nos com?no Explorador; efuciniCoverage.threshold.unmeasuredFilespode fazer falhar o Check Coverage Thresholds quando há mais do que um número que define. Nenhuma percentagem se move.count— tudo o quelistfaz, e cada ficheiro não medido conta também contra a execução como um ficheiro não coberto com as suas linhas de código, pelo que a barra de estado, os limiares, os emblemas, o histórico, cada exportação e a vista Test Coverage mostram o número mais baixo. O ficheiro é desenhado como não medido onde quer que apareça, as suas barras na margem dizem “não medido” em vez de “nunca correu”, e a verificação de discrepância deixa-o em paz — não há medição que o seu conteúdo possa contradizer.
{
"fuciniCoverage.unmeasured.mode": "list",
"fuciniCoverage.threshold.unmeasuredFiles": 0
}
Os ficheiros de cabeçalho são o falso positivo conhecido em C: têm a família de extensões da execução e nenhum ficheiro de cobertura alguma vez nomeará um, porque por si só compila para nada. fuciniCoverage.unmeasured.exclude deixa portanto de fora **/*.h, **/*.hpp, **/*.hh, **/*.inl e **/*.d.ts por predefinição, na mesma sintaxe glob de fuciniCoverage.ignore; acrescente um port de plataforma que não é compilado aqui, ou stubs gerados, e saem da lista, da contagem e do estado da barra de estado. Um ficheiro que ignore nomeia também nunca é considerado não medido — deixá-lo de fora era o objetivo. threshold.unmeasuredFiles tem por predefinição -1, que não verifica; 0 falha no momento em que qualquer ficheiro do tipo da execução nunca foi carregado por um teste, e só se aplica enquanto unmeasured.mode for list ou count.
13. Relatórios HTML
- Generate Full HTML Report — um relatório auto-gerado, de várias páginas, por diretório. A saída vai para
htmlReport.outputDir, ou para o armazenamento global da extensão quando não definido. - Open Annotated Source — uma vista anotada de um único ficheiro. Aponte
externalHtmlReport.dirpara um diretóriollvm-cov show --format=htmlpré-construído para usar essas páginas em vez do renderizador integrado. - Export Fucini JSON — o modelo normalizado completo para as suas próprias ferramentas.
- Export Coverage Report... — a execução como CSV (por ficheiro ou por função), resumo em Markdown, ficheiro de rastreio LCOV, XML do Cobertura, SARIF, ou emblema SVG autónomo para o seu README. Também acessível pelo botão ao lado de Generate Full HTML Report na vista Covered Files. Tudo exceto os CSV perde informação — MC/DC, regiões e instanciações não têm lugar em LCOV, Cobertura ou SARIF — por isso o Fucini JSON e os CSV continuam a ser os formatos que transportam todas as métricas.
- Copy Uncovered Lines — um resumo em Markdown de cada lacuna, pronto a colar num PR.
No Visual Studio. O grupo Reports de Tools → Coverage Studio: Show Annotated Source abre o documento ativo como uma página na área de documentos — cada linha na sua cor, as ocorrências ao lado — deslocada com o editor em ambos os sentidos; Open HTML Report escreve o relatório de uma página em htmlReport.outputDir (ou %LOCALAPPDATA%\Fucini\CoverageStudio\html-report) e abre o browser; Generate Full HTML Report escreve aí o índice por pasta e a página por ficheiro; Export Coverage Report… oferece os mesmos oito formatos e pergunta onde guardar; Generate Coverage Badge escreve o distintivo onde badge.outputPath indica, após cada carregamento com badge.autoUpdate. A página anotada precisa do WebView2, como a janela Coverage; os relatórios em disco não.
Screenshot pending — add assets/img/vs-annotated-source.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/report.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/report-directory-summary.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/report-file-summary.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/report-coverage-gaps.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/report-mcdc-detail.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/export-picker.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/annotated-source.png (see SCREENSHOTS.md).Código-fonte anotado vs. código-fonte simples
Open Annotated Source substitui o separador ativo por uma webview de cobertura a cores para esse ficheiro, na mesma coluna; Open Annotated Source to the Side faz o mesmo, mas dividido, para que o código-fonte e a vista anotada fiquem lado a lado. Para alternar no mesmo local — útil num ecrã pequeno onde a divisão torna cada painel demasiado estreito — use Toggle Annotated Source: alterna o separador ativo entre as duas vistas, memorizando qual está a ver no momento. A partir da própria vista anotada, Show Source regressa diretamente ao editor normal desse ficheiro.
O HTML que realmente vê depende de externalHtmlReport.dir: quando está definido e já existe aí uma página correspondente ao ficheiro ativo (o llvm-cov organiza as páginas por ficheiro como <nome-repo>/<caminho-relativo>.html, pelo que a pasta com o nome do repositório do relatório nunca precisa de configuração), essa página gerada pela toolchain é mostrada em vez do renderizador incorporado — as suas ligações/folha de estilo locais são reescritas para funcionar dentro da webview, e contém detalhes que a vista incorporada não reproduz (vistas de expansão MC/DC, destaque de regiões, resumos por diretório). Sem página correspondente para esse ficheiro, ou definição deixada em branco? É então usado o renderizador incorporado. A extensão apenas lê este diretório — nunca escreve nele.
Um emblema de cobertura para o README
Generate Coverage Badge escreve um SVG ao estilo shields para a execução ativa no espaço de trabalho — badge.outputPath, por predefinição coverage-badge.svg, relativo à pasta do espaço de trabalho ou absoluto, com as mesmas variáveis de todas as outras definições de caminho — e propõe abri-lo. É um ficheiro simples no seu repositório, pelo que um README o incorpora sem nenhum serviço por trás, sem ida e volta ao shields.io, e funciona também num repositório isolado da rede:

badge.metric escolhe o que o emblema mostra: lines (com a etiqueta coverage), branches, mcdc ou weighted, a mesma pontuação composta que a barra de estado mostra, com a etiqueta score. Uma execução sem dados para a métrica escolhida recebe um n/a cinzento em vez de um 0% vermelho. A cor segue os seus próprios patamares de colorScale.*: lowColor abaixo de lowThreshold, midColor até highThreshold, highColor a partir daí. Com badge.autoUpdate ligado, o emblema é reescrito após cada carregamento bem-sucedido, silenciosamente, e o canal de saída regista cada escrita como [FUCINI_BADGE] — desligado por predefinição porque escreve no espaço de trabalho a cada carregamento. Confirme o SVG juntamente com o código e a imagem na página do repositório acompanha o número no editor.
{
"fuciniCoverage.badge.outputPath": "docs/coverage-badge.svg",
"fuciniCoverage.badge.metric": "weighted",
"fuciniCoverage.badge.autoUpdate": true
}
14. Histórico e tendências
Ative history.enabled para persistir execuções localmente (mantendo history.retention delas). Obtém então uma seta de tendência (▲/▼) na barra de estado, o gráfico de tendência na vista Coverage e dois comandos de comparação: Compare with Last Run e Compare Two History Runs, cada um produzindo uma diferença de regressão/melhoria por ficheiro.
No Visual Studio. Cada carregamento é comparado com o anterior: um triângulo na margem em cada linha que começou ou deixou de correr (sinceLastRun.enabled), a tendência ao lado da pontuação na barra de estado, e Compare with Last Run para os ficheiros cujos números mudaram. Com history.enabled as execuções são guardadas em %LOCALAPPDATA%\Fucini\CoverageStudio\history, history.retention delas, pelo que a comparação sobrevive a um reinício, o gráfico de tendência tem algo para desenhar, e Compare Two History Runs… escolhe quaisquer duas delas.
Screenshot pending — add assets/img/history-compare.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/since-last-run.png (see SCREENSHOTS.md).O gráfico de tendência
Por baixo da barra de ferramentas da vista Coverage, com duas ou mais execuções guardadas, a cobertura de linhas do histórico como uma linha, da mais antiga à mais recente, as trinta mais recentes: um ponto por execução que diz a sua data e o seu valor ao passar o cursor, e o último valor ao lado com uma seta para a direção desde a primeira. A escala vertical é o intervalo das próprias execuções, pelo que uma equipa a 92–94% vê o movimento em vez de uma linha plana abaixo de 100. Ambas as edições desenham-no a partir do mesmo histórico.
Screenshot pending — add assets/img/trend-chart.png (see SCREENSHOTS.md).
Sessões de cobertura
Uma só execução de testes raramente cobre tudo o que uma alteração tocou: os testes unitários correram aqui, a suite de integração ali, um percurso pela interface com cobertura ligada noutro lado. Start Coverage Session transforma os carregamentos que se seguem numa só soma — cada execução é somada à anterior linha a linha como união, uma linha que qualquer delas executou está coberta e as contagens somam-se — para que a margem, a árvore e a pontuação mostrem o que todas juntas alcançaram. A execução no ecrã, se houver uma, é a primeira da sessão. Uma barra sobre a árvore diz quantas execuções desde quando e termina a sessão; End Coverage Session faz o mesmo, e o carregamento seguinte volta a estar sozinho. No Visual Studio uma só entrada em Tools → Coverage Studio inicia a sessão e, marcada, termina-a.
Screenshot pending — add assets/img/coverage-session.gif (see SCREENSHOTS.md).
A baseline de CI: onde estou em relação ao main?
Compare with Last Run responde ao que a sua última alteração fez; antes de um pull request a pergunta é onde está em relação ao main, e a resposta está no servidor de build. baseline.report nomeia o relatório que a compilação do ramo main publica, e cada carregamento é comparado com ele: o cartão da barra de estado traz o delta numa linha — vs CI baseline: 84.20% → 85.10% (+0.90%), 3 file(s) moved — e Compare with CI Baseline lista os ficheiros que mudaram, ficheiro a ficheiro, com as mesmas palavras de Compare with Last Run. No Visual Studio o comando está em Tools → Coverage Studio e descarrega ou lê o relatório quando o pedir. Três maneiras de o nomear, em .vscode/settings.json:
- Um URL que a CI serve. O GitLab guarda os artefactos do último job de um ramo num endereço estável; o token fica fora do ficheiro de definições através de
${env:…}emremote.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.infocomAuthorization: Bearer ${env:TC_TOKEN}. O URL é descarregado e guardado em cache exatamente como um URL decoverageFile.paths(ETag,remote.refreshMinutes). - Um ficheiro que o pipeline copiou para uma partilha — um caminho absoluto como
\\build\drops\app\main\coverage.cobertura.xml. - Um artefacto descarregado guardado dentro da pasta, digamos
ci/main.lcov.info(ponha a pasta no.gitignore) — um caminho relativo à pasta.
{
"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}"]
}
Serve qualquer formato que o leitor conheça. Um caminho que a CI escreveu relativo ao seu checkout — src/Billing/Invoice.cs, como o Coverlet o escreve no runner — é colocado sob esta pasta antes do diff, para que encontre o ficheiro que a execução local resolveu; um caminho absoluto de outra máquina não corresponde a nada, por isso faça o pipeline escrever caminhos relativos. Uma baseline que não pode ser descarregada ou lida é uma linha no painel Output, nunca um carregamento falhado.
Screenshot pending — add assets/img/ci-baseline.gif (see SCREENSHOTS.md).main.
Um artefacto é um zip, e isso também é lido. O GitHub e o GitLab entregam um artefacto como um arquivo, seja o que for que lá se tenha posto. Indique o relatório dentro dele a seguir a um #: o membro é encontrado pelo seu caminho ou pelo fim dele; sem #, é o único ficheiro do arquivo, ou o único que parece um relatório, e onde houver vários o painel Output nomeia-os. O mesmo vale para um zip que descarregou (ci/artifact.zip#lcov.info) e, no VS Code, para um URL em coverageFile.paths. O token vai para o servidor para o qual foi definido e não mais longe: o redirecionamento para o armazenamento que guarda o arquivo é seguido sem ele.
{
"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: a cobertura no ecrã
Um agente que escreve testes consegue executá-los e ler uma percentagem. O que não consegue fazer sozinho é perguntar o que o editor sabe: que linhas desta função nunca correram, que lado de que ramo, que testes executam uma linha, se o diff que acabou de escrever está coberto. Seis ferramentas respondem exatamente a isso, em palavras com que um agente pode trabalhar, a partir da execução que está carregada — as mesmas exclusões, o mesmo remapeamento, os mesmos números que no ecrã. Assim, um agente a quem se pede que cubra as lacunas de uma função e um revisor que olha para a margem estão a falar das mesmas linhas.
| Ferramenta | A que responde |
|---|---|
coverage_summary | Os totais da execução por métrica, e os ficheiros mais longe de estarem cobertos. A primeira coisa a perguntar. |
coverage_gaps | O que nunca correu num ficheiro, numa função ou num intervalo de linhas: as linhas não cobertas, os braços de ramo não tomados, as condições MC/DC sem o seu par, os mutantes que sobreviveram. |
tests_for_line | Que testes executaram uma linha, onde o relatório o diz — uma execução por teste. |
patch_coverage | A cobertura de um diff — a árvore de trabalho em relação a uma ref, ou um patch que lhe é entregue — e as linhas dele que nunca correram. |
coverage_delta | O que mudou desde a execução anterior: os totais, e os ficheiros que ganharam ou perderam. |
test_run_command | O comando que corre os testes deste espaço de trabalho com a cobertura ligada. O agente executa-o; o editor recarrega o relatório sozinho. |
O agente do próprio VS Code tem-nas como ferramentas, sem nada para configurar. Todos os outros agentes — qualquer cliente que fale MCP, o Model Context Protocol — acedem-lhes através de um servidor que o editor executa quando mcp.enabled está ligado, tanto no VS Code como no Visual Studio. Copy MCP Server Configuration põe a entrada do cliente na área de transferência, tal como o VS Code e o Visual Studio a leem num mcp.json; um cliente que chame mcpServers à chave exterior recebe a mesma entrada sob esse nome.
Screenshot pending — add assets/img/mcp-config.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-mcp-config.png (see SCREENSHOTS.md).{
"servers": {
"fucini-coverage": {
"type": "http",
"url": "http://127.0.0.1:39217/mcp",
"headers": { "Authorization": "Bearer …" }
}
}
}
- Está desligado a não ser que o ligue, e escuta apenas em
127.0.0.1: nada de fora desta máquina lhe chega. - Uma chamada tem de trazer o seu token, criado uma vez e guardado para si; sem ele a resposta é 401. A configuração copiada traz o token: mantenha-a fora do repositório.
- Uma chamada enviada por uma página web — di-lo no seu
Origin— é recusada, traga o que trouxer. - Lê a execução que está carregada e não escreve nada. A execução de testes é nomeada, não iniciada: o agente corre o comando no seu próprio terminal.
A porta é mcp.port, 39217 se não for definida. Onde essa estiver ocupada — uma segunda janela, a outra edição ao lado desta — é usada a próxima que esteja livre, e a configuração copiada indica a que funciona. O painel Output diz onde o servidor escuta ([FUCINI_MCP]) e por que não conseguiu ([FUCINI_MCP_001]). O que um plano não inclui — os nomes dos testes, o detalhe MC/DC — as ferramentas contam sem o discriminar, como faz a dica ao passar o cursor.
15. Referência de comandos
No Visual Studio. Todos os comandos estão em Tools → Coverage Studio, com o nome da tabela sem o prefixo Fucini Coverage:; a barra de ferramentas da janela Coverage e o menu do botão direito numa linha têm os que lá pertencem, e o menu do botão direito da janela de código tem os três que atuam sobre o editor: Run This Test with Coverage, Show Tests That Ran This Line e Exclude Selection from Coverage. Os que têm teclas são acordes de duas teclas após Ctrl+Shift+U: R recarrega, N e P vão à linha não coberta seguinte e anterior, B à próxima decisão parcialmente testada, T lista os testes que executaram a linha, X exclui a seleção — não o Alt+N do VS Code, porque no Visual Studio Alt e uma letra abrem um menu. Altere-os em Tools → Options → Keyboard, onde estão listados como Coverage Studio: …. Não nesta edição: o painel Test Coverage é uma API do VS Code — a execução está, em vez disso, na janela Coverage — e o Solution Explorer não consegue mostrar distintivos. Só nesta edição: Run Native Project with Coverage, para um projeto de arranque C++.
No Visual Studio: onde está cada coisa. A janela Coverage está em View → Other Windows → Coverage, e em primeiro lugar em Tools → Coverage Studio, onde estão todos os comandos desta edição, por grupos: carregar e recarregar, vigiar o ficheiro, as duas cópias e os cartões; Run Tests with Coverage, Run Native Project with Coverage e Collect Coverage in Test Explorer…; Next e Previous Uncovered e as decisões parcialmente testadas; a pintura, os contadores de execuções e os modos da margem; a fonte de cobertura de um ficheiro, os testes que executaram uma linha, um só teste com cobertura, as duas maneiras de excluir; Compare with Last Run, Compare Two History Runs…, Compare with CI Baseline, a sessão de cobertura e Check Coverage Thresholds; o grupo Reports — Show Annotated Source, Open HTML Report, Generate Full HTML Report, Export Coverage Report… e Generate Coverage Badge; depois Getting Started, os limiares de conformidade e Licence…. A barra de ferramentas da janela tem os cinco mais usados: Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary e os limiares de conformidade; por baixo deles a perspetiva, o filtro e a ordenação, e a caixa de pesquisa; por baixo destes a tendência. Deixe o ponteiro sobre uma linha da árvore e prima o seu ⋯ para o menu da linha — abrir o ficheiro, abrir a sua pasta, copiar o caminho, absoluto ou relativo, com qualquer dos dois tipos de barra, excluí-lo da cobertura. No canto direito da barra de estado estão a pontuação da execução e a do ficheiro aberto, com a tendência desde a última execução; Show Coverage Card e Show Coverage Card for This File abrem os cartões por trás delas, os mesmos que o VS Code mostra quando o ponteiro pára sobre o seu item da barra de estado.







Screenshot pending — add assets/img/statusbar-and-toolbar.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/statusbar-menu.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/worst-functions.png (see SCREENSHOTS.md).| Comando | O que faz |
|---|---|
| Load Coverage | Descobrir e carregar a cobertura do espaço de trabalho. Alt+Shift+R por predefinição (Ctrl+Alt+R no macOS). |
| Pick Coverage File | Escolher tracefiles — um, vários, ou mais um de cada vez; as escolhas somam-se, são fundidas e escritas em coverageFile.paths, pelo que a partir daí carregam sozinhas. |
| Show Loaded Coverage Files | Listar os tracefiles da execução ativa. A vista Cobertura também os lista, cada um com um botão de descarga e um botão de escolha ao lado. |
| Toggle Tracefile Watch | Monitorizar alterações no(s) ficheiro(s) de rastreio e recarregar automaticamente. |
| Run Tests with Coverage | Reconhecer o executor de testes, executá-lo com cobertura numa tarefa de terminal, carregar o que escreve e propor adicionar o caminho às definições. |
| Run This Test with Coverage | O teste sob o cursor — o método, a classe ou o bloco describe, ou o ficheiro — corrido pela receita restringida a ele, e depois carregado como qualquer execução. Também no menu de contexto do editor. |
| Show Tests That Ran This Line | Onde o relatório diz que testes executaram o quê, lista os testes que executaram a linha sob o cursor, do mais ativo para o menos, e abre o que escolher onde ele está escrito. |
| Run Tests Affected by My Changes… | Listar os testes que executaram uma linha que a árvore de trabalho altera em relação a testImpact.baseRef, abrir o que escolher, ou correr só esses onde os relatórios vieram de uma execução por teste. |
| Show Minimal Test Set… | O menor número de testes que ainda executa todas as linhas que a suite executa, e depois os testes que não acrescentam nenhuma linha própria. |
| Run App with Coverage… | Iniciar a aplicação .NET da pasta sob o dotnet-coverage, e carregar o que percorreu quando ela fechar. |
| Run Mutation Tests Here | Mutar a função em que o cursor está — ou a seleção, ou o ficheiro — com o Stryker.NET, o StrykerJS ou o PIT, e carregar o relatório ao lado da cobertura no ecrã. |
| Exclude This File from Coverage / Exclude from Coverage | Põe o ficheiro aberto — ou, numa linha da vista Coverage, o ficheiro ou o /** da pasta — em fuciniCoverage.ignore nas definições da pasta, uma só vez. |
| Exclude Selection from Coverage | Escreve a exclusão onde está o código: [ExcludeFromCodeCoverage] por cima de um membro .NET, LCOV_EXCL_LINE numa só linha, LCOV_EXCL_START/STOP à volta de várias, com o sinal de comentário do próprio ficheiro. Também na lâmpada e no menu de contexto do editor. |
| Start Coverage Session / End Coverage Session | Enquanto uma sessão está ativa, cada carregamento é somado ao anterior como união; uma barra sobre a árvore conta as execuções e termina-a. |
| Next / Previous Uncovered | Saltar entre regiões não cobertas. Alt+N / Alt+P por predefinição (Ctrl+Alt+N / Ctrl+Alt+P no macOS). |
| Choose Editor Gutter Mode... | Desligado, barras só nas linhas não cobertas, barras vermelho-âmbar-verde, ou um mapa de calor de contagens de acertos na margem do editor. |
| Cycle Editor Gutter Mode | Um passo em frente por off, uncovered, coverage e heatmap — Alt+G, ou o botão de modo na barra de estado. |
| Choose Coverage Source for This File... | Quando mais do que um relatório carregado mede o ficheiro aberto, escolher de qual vêm os seus números, para o ficheiro, a sua pasta ou um padrão — escreve uma regra coverageFile.sources. |
| Clear Coverage Source for This File... | Retirar as regras coverageFile.sources que se aplicam ao ficheiro aberto. |
| Toggle Inline Hit Counts | Mostrar ou ocultar as contagens de execução ×N a seguir a cada linha — alterna hitCounts.inline. |
| Show in Test Coverage View | Publicar a execução ativa no próprio painel Test Coverage do VS Code (mesmo com testCoverage.publish desligado) e abri-lo. |
| Suggest Path Remap Rule | Inferir a regra de pathRemap que faria corresponder ao espaço de trabalho os ficheiros sem correspondência da execução ativa, e propor adicioná-la. |
| What Community Includes | Cada limite e cada funcionalidade retida do nível gratuito numa só lista, com quanto de cada limite foi usado. |
| Open HTML Report | Abrir o relatório estático gerado. |
| Generate Full HTML Report | Criar o relatório de várias páginas. |
| Open Annotated Source / …to the Side | Vista anotada da cobertura de um ficheiro. |
| Toggle Annotated Source | Alternar entre a fonte e a vista anotada. Alt+A por predefinição (Ctrl+Alt+A no macOS). |
| Show Worst-Covered Files / Folders / Functions | Quick Pick ordenado do mais baixo. |
| Copy Uncovered Lines | Resumo em Markdown de cada intervalo não coberto. |
| Compare Two History Runs / with Last Run | Diff de regressão por ficheiro — duas execuções guardadas no histórico, ou a execução no ecrã contra a que ela substituiu. |
| Compare with CI Baseline | A execução carregada contra o relatório que baseline.report nomeia — o do ramo main vindo da CI, um URL ou um artefacto descarregado — ficheiro a ficheiro. |
| Show Indirect Coverage Changes… | As linhas cuja cobertura mudou sem que ninguém as editasse, em relação à baseline de CI ou à execução anterior, por ficheiro. |
| Check Coverage Thresholds | Avaliar as verificações de conformidade. |
| Export Fucini JSON | Exportar a execução atual como Fucini JSON. |
| Export Coverage Report... | Escolha um formato — CSV, Markdown, LCOV, XML do Cobertura, SARIF ou um emblema SVG — e um destino. |
| Generate Coverage Badge | Escrever o emblema SVG da execução ativa em badge.outputPath, mostrando badge.metric, e propor abri-lo. |
| Copy MCP Server Configuration | Pôr na área de transferência o que um cliente MCP precisa para perguntar pela cobertura no ecrã — o endereço do servidor e o seu token; com o servidor desligado, propor ligá-lo. |
| Show Status Bar Menu | Abrir o menu de ações rápidas. |
| Browse for External HTML Report / Full Report Output Dir… | Definir os diretórios de relatório através de um seletor. |
16. Referência de definições
A tabela completa e categorizada de definições — cada opção com o seu valor predefinido — está disponível na página Funcionalidades e Definições. Todas as chaves têm o prefixo fuciniCoverage..
Vale destacar: fuciniCoverage.language fixa a própria interface em tempo de execução desta extensão (barra de estado, notificações, dicas, webviews) num idioma específico, independentemente do idioma de visualização do VS Code — por predefinição é auto e inclui pacotes para os 18 idiomas suportados. Não altera as entradas da paleta de comandos nem os rótulos das definições, que o VS Code continua a resolver a partir do seu próprio idioma de visualização.
No Visual Studio. As mesmas chaves fuciniCoverage.*, lidas de até quatro ficheiros, ganhando o posterior: as definições de utilizador do próprio VS Code se o VS Code estiver na máquina — lidas, nunca escritas, para que as suas cores e limiares o acompanhem; %APPDATA%\Fucini\CoverageStudio\settings.json, as definições de utilizador desta edição; .vscode\settings.json na pasta ou ao lado da solução, por isso um repositório configurado para VS Code está configurado para Visual Studio; e fucini-coverage.json na raiz da solução, para uma equipa que prefira não manter uma pasta .vscode num repositório .NET — a edição para VS Code também o lê. A engrenagem na barra de ferramentas da janela Coverage abre uma janela de definições que escreve o ficheiro de utilizador ou o ficheiro da pasta que existir, conforme diz o seu seletor Write changes to, e mantém os comentários de um ficheiro que edita. fuciniCoverage.language funciona aí da mesma forma; os menus seguem o idioma do próprio Visual Studio.
17. Códigos de erro
Os diagnósticos são enviados para o canal de saída Fucini Coverage (View → Output → Fucini Coverage), cada um com um código estável FUCINI_*.
No Visual Studio. Os mesmos códigos vão para o painel Fucini Coverage da janela Output (View → Output) e ficam guardados em %LOCALAPPDATA%\Fucini\CoverageStudio\coverage-studio.log, para a pergunta que chega depois de o IDE estar fechado. Três que aparecem: nada está marcado embora o painel diga que ficheiros foram carregados — o modo da margem é off, escolha Show Coverage in Editor; FUCINI_REMAP_001 e uma barra de informação — o relatório nomeia caminhos que aqui não existem, e o painel sugere a regra pathRemap; a janela Coverage diz que precisa do WebView2 — instale o Microsoft Edge WebView2 Runtime, as marcas no editor não precisam dele.
| Código | Significado |
|---|---|
FUCINI_PARSE_001 | Formato de cobertura não suportado/não reconhecido — nenhum analisador correspondeu ao ficheiro. |
FUCINI_PARSE_010 | O ficheiro lcov não tinha registos SF. |
FUCINI_PARSE_020 | JSON do llvm-cov inválido, sem data[] ou sem ficheiros. |
FUCINI_PARSE_030 | Raiz <coverage> do Cobertura em falta ou XML inválido. |
FUCINI_PARSE_040 | Raiz <report> do JaCoCo em falta ou sem ficheiros de origem. |
FUCINI_PARSE_050 | JSON do Istanbul/SimpleCov inválido ou sem ficheiros. |
FUCINI_PARSE_060 | JSON do SimpleCov inválido ou sem a matriz files de nível superior. |
FUCINI_PARSE_070 | Perfil Go sem cabeçalho mode:, ou sem blocos de cobertura. |
FUCINI_PARSE_080 | Raiz Clover <coverage> ou <project> em falta, ou sem ficheiros dentro. |
FUCINI_PARSE_090 | Raiz OpenCover <CoverageSession> em falta, ou sem ficheiros dentro. |
FUCINI_PARSE_100 | JSON do coverage.py inválido ou sem um objeto files de nível superior. |
FUCINI_PARSE_110 | JSON do gcov/gcovr inválido ou sem um array files de nível superior. |
FUCINI_PARSE_120 | XML do GNATcoverage sem elemento <source>, ou um index.xml cujos xi:include nunca foram resolvidos — carregue antes os ficheiros *.xml por fonte. |
FUCINI_PARSE_130 | Falta a raiz <BullseyeCoverage>, ou não contém elementos <src>. |
FUCINI_PARSE_140 | Falta a raiz <CoverageDSPriv>, não há tabela <SourceFileNames> para resolver as linhas, ou não há dados de linha. |
FUCINI_PARSE_150 | JSON de cobertura do Xcode inválido, ou sem o array targets de nível superior. |
FUCINI_PARSE_160 | Falta a raiz <coverage> do SonarQube, ou não contém elementos <file>. |
FUCINI_PARSE_170 | JSON do Coveralls inválido, ou sem o array source_files de nível superior. |
FUCINI_LOAD | Um carregamento foi cancelado a partir da sua notificação de progresso; a execução anterior, se existir, continua carregada. |
FUCINI_REMOTE_001 | Um URL de coverageFile.paths não pôde ser descarregado, com o motivo; é carregada a última cópia descarregada. Linhas [FUCINI_REMOTE] simples registam cada descarga e cada verificação sem alterações (304). |
FUCINI_REMOTE_002 | Um URL de coverageFile.paths não deu uma resposta completa em 30 segundos — quase sempre um proxy ou VPN que aceita a ligação e depois se cala; é carregada a última cópia descarregada. |
FUCINI_REMOTE_003 | Um URL de coverageFile.paths respondeu com uma página HTML em vez de um ficheiro de rastreio — uma página de início de sessão, muito provavelmente. A página não é guardada em cache e é carregada a última cópia descarregada; verifique o token em remote.headers. |
FUCINI_REMAP_002 | Foi sugerida uma regra de pathRemap para os caminhos que um carregamento deixou sem correspondência, com quantos deles explica — ou não foi possível inferir nenhuma, ou a regra inferida já está na definição e não os resolveu. |
FUCINI_REMAP_003 | A regra sugerida foi acrescentada a fuciniCoverage.pathRemap por Apply Suggested Remap e a cobertura está a ser recarregada. |
FUCINI_GITDIFF_001 | A extensão Git não está disponível; a cobertura do diff é ignorada e é mostrada a execução completa. |
FUCINI_GITDIFF_002 | gitDiff.baseRef começa por -, o que nenhuma referência git pode fazer (o git lê-lo-ia como uma opção); a cobertura do diff é ignorada e é mostrada a execução completa. |
FUCINI_IGNORE | Quantos ficheiros fuciniCoverage.ignore deixou fora da execução, e quais. |
FUCINI_UNMEASURED_001 | Os ficheiros do tipo da execução que nenhum teste carregou, um por linha. |
FUCINI_UNMEASURED_002 | Mais de 5 000 ficheiros do espaço de trabalho correspondiam a uma das extensões da execução; só os primeiros 5 000 foram considerados para a lista Não medidos. |
FUCINI_UNMEASURED_003 | No modo count, alguns ficheiros não medidos são listados mas não contados: o limite de leitura (2 000 ficheiros ou 50 MB por carregamento) foi atingido. |
FUCINI_UNMEASURED_004 | Um ficheiro não medido não pôde ser lido; é listado mas não contado. |
FUCINI_TESTCOVERAGE | Quantos ficheiros foram publicados na vista Test Coverage do VS Code. |
FUCINI_BADGE | O emblema foi escrito, com o seu caminho, etiqueta e valor. |
FUCINI_BADGE_001 | O emblema não pôde ser escrito, com o motivo. |
FUCINI_WORKSPACE | Uma pasta foi adicionada ao espaço de trabalho ou dele removida; a cobertura é detetada de novo. |
FUCINI_VARIABLES | O que cada ${command:…} nas definições de caminho respondeu, ou porque ficou tal como está escrito: o comando falhou, não devolveu nada utilizável ou a área de trabalho não é fidedigna. |
FUCINI_WATCH | O que o observador está a fazer: os caminhos observados, um ficheiro configurado que apareceu, uma tarefa nomeada em watch.reloadAfterTasks que terminou (com o seu código de saída) e desencadeou um recarregamento, ou um caminho sob files.watcherExclude que é sondado em vez disso. |
18. Privacidade
A telemetria é controlada pela definição telemetry.enabled de âmbito window. Está desativada por predefinição. O resumo diário e o aviso de remoção exigem ainda que o telemetry.telemetryLevel global do VS Code permita telemetria; o aviso de instalação e alguns eventos pequenos são enviados em qualquer caso, tal como a entrada no registo de utilização de uma instalação no período de avaliação ou no nível gratuito Community. No Community, Unlock Full Features troca esta telemetria por todas as funcionalidades Pro, MC/DC incluída, durante 30 dias, uma vez por máquina — desative-a novamente e aplica-se o conjunto padrão do Community; uma licença paga não é afetada em nenhum dos casos. Consulte a política de privacidade para saber o que é enviado.
Vale a pena conhecer duas coisas, porque pode agir sobre elas. A primeira é o seu ID do registo de utilização: em avaliação e no Community, a extensão mostra-o em Show License / Activation e no fim de What Community Includes, onde selecionar a linha o copia e abre a política de privacidade. O registo conhece a sua máquina por um hash e por mais nada, pelo que esse ID é a única forma de perguntar o que ele guarda a seu respeito, de o mandar apagar ou de se lhe opor — indique-o e encontramos a sua linha; sem ele, não conseguimos. A segunda é o registo de instalação: uma linha escrita na primeira vez que uma instalação comunica e conservada em vez de apagada ao fim de 90 dias, com o identificador de instalação, o dia, o lugar para onde o endereço foi resolvido, as versões e o sistema operativo — não o endereço em si, nem nada sobre o seu código. É o que nos permite dizer quantas instalações houve ao longo dos anos. Ambos são descritos na íntegra na política de privacidade, e ambos são apagados se o pedir.

19. Avaliação e ativação
O Fucini Coverage Studio é distribuído como pré-versão de avaliação. Na primeira execução pedimos que aceite avaliá-lo e o período experimental começa — todas as funcionalidades estão disponíveis durante um período experimental de 14 dias, contados a partir da primeira utilização nessa instalação. Não há uma data fixa após a qual algo deixe de funcionar.
A partir da versão 2.2026.2, a avaliação de uma nova instalação começa assim que a extensão tiver contactado uma vez o servidor de licenças; até lá funciona no nível Community e indica-o. Num contentor de desenvolvimento ou num Codespace não começa nenhuma avaliação — um código de subscrição, uma chave ou o passe de 7 dias desbloqueia aí o conjunto completo.
Quando o período experimental termina nada fica bloqueado: a extensão passa para o nível gratuito Community. Para recuperar o conjunto completo, ative — a ativação liga-se ao servidor de licenças e aplica a chave devolvida automaticamente, sem e-mail e sem qualquer chave para copiar à mão:
Screenshot pending — add assets/img/licence-dialog.png (see SCREENSHOTS.md).- Execute
Fucini Coverage: Show License / Activation(também acessível a partir da barra de estado assim que o período experimental ou a chave expirar) e clique em Request License… (ou Request Renewed Key… se já ativou antes). - Confirme o pedido. A chave é emitida automaticamente e os seus dados de contacto de um pedido anterior são reutilizados em vez de pedidos de novo.
- É tudo. A chave de ativação é gerada e escrita automaticamente em
fuciniCoverage.license.key. A barra de estado passa do período experimental para uma licença ativada num instante.
A via manual numa imagem: abra o painel da licença, escolha Enter Key, cole a chave do seu e-mail e o banner passa a «Activated».
Screenshot pending — add assets/img/activate-key.gif (see SCREENSHOTS.md).Se o pedido automático falhar (sem ligação, problema no servidor): execute Fucini Coverage: Copy Activation Request Code, envie-o através da página de contacto ou de info@fucini.consulting, e cole a chave FCK1.… que receber em resposta com Fucini Coverage: Enter Activation Key (ou diretamente no settings.json):
{ "fuciniCoverage.license.key": "FCK1.…cole aqui a chave completa…" }O nome da definição é fuciniCoverage.license.key (âmbito utilizador/global). A chave está vinculada à sua máquina e utilizador do sistema operativo, pode ter uma data de expiração e pode ativar ou limitar funcionalidades individuais e limitar carregamentos de cobertura por dia. Se mostrar “invalid for this machine”, peça uma chave nova a partir desta instalação — uma chave emitida para outra máquina nunca será válida aqui.
No Visual Studio. Não há nível gratuito nessa edição: sem subscrição nada é lido. Com uma, o plano decide aí o que decide no VS Code — uma funcionalidade que o plano deixa de fora é retida, e o seu comando di-lo em vez de correr. A versão mais antiga que o servidor de licenças ainda suporta aplica-se aí também: uma build abaixo dela é avisada uma vez por dia, com a data em que deixa de funcionar, e continua a funcionar até lá. Estar offline nunca faz parar uma build.
O nível gratuito Community: um limite semanal
O Community nunca deixa de mostrar a cobertura. As margens, a régua de visão geral, os hovers, o CodeLens, a vista Coverage, o modo watch, a cobertura de diff e o histórico não são contabilizados de todo, e carregar um tracefile por comando está limitado apenas a 25 por dia. O que é medido é a saída: cinco por semana cada para abrir o relatório HTML, exportar, comparar duas execuções, verificar os limiares e ver o código-fonte anotado no local.
A semana é sua, não do calendário: começa com a primeira utilização e termina sete dias depois. Quando um limite se esgota, a mensagem indica a ação e o dia em que volta a estar disponível, e depois dessa única mensagem só a barra de estado o menciona. Fucini Coverage: What Community Includes lista todos os limites com o que já foi usado e quando são repostos, antes mesmo de chegar a algum deles.
Screenshot pending — add assets/img/weekly-allowance.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/community-limit-prompt.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/community-includes-weekly.png (see SCREENSHOTS.md).Três detalhes pertencem aos planos pagos, enquanto as respetivas constatações continuam gratuitas: o Community marca cada linha que tem mutantes sobreviventes e diz quantos são, mas não o que cada mutante alterou; diz quantos testes executaram uma linha, mas não os seus nomes; e mostra o Max CRAP de uma execução, mas não a lista ordenada Riskiest Methods.
Screenshot pending — add assets/img/mutant-hover-community.png (see SCREENSHOTS.md).Se já usava o Community quando o limite semanal chegou (0.2026.83), os seus limites anteriores mantêm-se durante 30 dias; é informado uma única vez, com a data. Os contadores ficam guardados na sua máquina — no armazenamento próprio do VS Code e em ~/.fucini-coverage/, pelo que um novo perfil do VS Code continua a mesma semana — e nunca são enviados para lado nenhum.
O passe de 7 dias
Ainda não quer uma subscrição? Um passe de 7 dias é tudo o que o Pro inclui durante uma semana, pago uma vez: nada se renova e não há nada para cancelar. Compre-o na página de preços (a mensagem de um limite do Community tem um botão para isso), e o código de ativação chega por email.
Screenshot pending — add assets/img/pricing-week-pass.png (see SCREENSHOTS.md).- Execute
Fucini Coverage: Enter Subscription Code— existe tanto na edição Community como no Pro. - Escolha Pro e cole o código
FCB1-…do email. - É tudo. A chave é emitida e aplicada por si, e funciona offline. A semana conta a partir do pagamento, por isso ative quando comprar. Quando terminar, a extensão regressa sozinha ao Community e continua a mostrar a cobertura.
Screenshot pending — add assets/img/pass-step-plan.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/pass-step-code.png (see SCREENSHOTS.md).No Visual Studio. O mesmo código ativa o Fucini Coverage Studio para Visual Studio, 2022 e 2026: abra Tools → Coverage Studio → Licence…, cole o código, escolha o plano a que se destina e prima Activate. A janela Coverage mostra então Activated acima da árvore; aberta com a sua seta, a linha mostra a data até à qual a chave é válida e um botão para a sua conta. Uma máquina é um lugar: ative o VS Code ou o Visual Studio, e o outro editor na mesma máquina segue por si — o Visual Studio lê a chave do VS Code e o VS Code a do Visual Studio —, pelo que nada é introduzido duas vezes e nenhum segundo lugar é ocupado. Ambos mantêm uma chave viva da mesma forma: Pro Plus, Business e Enterprise apresentam-se duas vezes por dia, e uma chave Pro é renovada na semana anterior ao seu termo.


Mudar para um computador novo e gerir os lugares
Uma chave está ligada a uma máquina, por isso um computador novo precisa de uma nova — e a sua subscrição só paga as máquinas que indica. Liberte a antiga você mesmo: inicie sessão em gerir a sua subscrição, encontre o lugar que já não usa, escolha Free up e ative a máquina nova com o mesmo código. Comprar o Pro não lhe envia palavra-passe: a sua conta existe, apenas ainda não tem nenhuma, por isso da primeira vez use definir ou repor a palavra-passe com o endereço da subscrição.
No Business e no Enterprise convida cada colega por e-mail a partir dessa mesma página. Cada um recebe um código de ativação só seu e, assim que o usa, o endereço aparece junto ao lugar — quando alguém sai, vê qual era o seu e liberta-o para o seguinte. Um convite ocupa um lugar a partir do envio e expira ao fim de 14 dias se não for usado; retire-o para recuperar o lugar de imediato.
Testar versões preliminares
As novidades chegam a fucini.software antes de chegarem ao Marketplace, e pode pedir que lhas ofereçamos. Abra a vista Coverage, expanda o painel da licença e prima Testar versões preliminares… — ou defina fuciniCoverage.update.preRelease. A partir daí, a extensão consulta aqui um canal preliminar à parte, além do habitual, e oferece a mais recente das duas.
Screenshot pending — add assets/img/licence-prerelease.png (see SCREENSHOTS.md).As versões preliminares são testadas, mas são as compilações de que temos menos certeza — estaria a oferecer-se para encontrar o que nos escapou. Ao aderir, diz-nos que esta instalação está no canal, para sabermos quantas pessoas estão a testar e podermos dizer-lhe o que mudou; ao sair, a próxima versão estável devolve-o ao caminho habitual. Nem sempre há uma versão preliminar disponível, e aderir quando não há não custa nada: a extensão encontra um canal vazio, nada diz sobre isso e continua a oferecer versões estáveis até que uma seja publicada.
Screenshot pending — add assets/img/licence-prerelease-joined.png (see SCREENSHOTS.md).20. Contacto e licença
Perguntas, relatórios de erros ou termos de licenciamento alternativos — consulte a página de contacto ou envie um e-mail para info@fucini.consulting. Licenciado sob MIT com uma condição de atribuição nas notas de versão; consulte também a Notice.
21. Na linha de comandos
O leitor também corre sem editor: npm install -g fucini-coverage, grátis, no Windows, Linux, WSL e macOS. fucini-coverage check coverage/lcov.info --lines 80 é o gate com que um pipeline falha; summary, export, report, badge e compare fazem o que fazem os comandos dos editores com esses nomes, e mcp serve as seis ferramentas da secção acima a um agente, num servidor. Lê fucini-coverage.json, o ficheiro de definições que a edição para Visual Studio lê, pelo que os limiares são fixados uma só vez. fucini-coverage help <command> explica cada um; a página completa é fucini-coverage no npm.
Screenshot pending — add assets/img/cli-demo.gif (see SCREENSHOTS.md).