1. Вступ
Fucini Coverage Studio перетворює трасувальні файли покриття, які ваша збірка вже створює, на повноцінне покриття в редакторі — у VS Code і у Visual Studio. Він читає двадцять п'ять форматів, нормалізує їх в одну канонічну модель Fucini, детерміновано зливає кілька запусків і показує все в самому редакторі — поле, CodeLens, підказки та вікно Covered Files — тож немає окремого переглядача, заради якого треба полишати редактор. Обидві редакції ділять один читач: той самий звіт дає ті самі числа, до цифри, в обох. Цей посібник написано з погляду VS Code; там, де Visual Studio відрізняється, поле In Visual Studio каже як.
Розширення створене з урахуванням процесів функціональної безпеки: покриття MC/DC, покриття регіонів і інстанціацій C++, композитний показник із ваговими коефіцієнтами безпеки та настроюваний вердикт COMPLIANT / NON-COMPLIANT, узгоджений із підходами IEC 61508, ISO 26262 та DO-178C.
Screenshot pending — add assets/img/marketplace-demo.gif (see SCREENSHOTS.md).2. Встановлення та вимоги
- VS Code ≥ 1.88 — мінімальна версія, яку підтримує це розширення — або Visual Studio 2022 чи 2026, Community, Professional або Enterprise (див. поле нижче).
- Трасувальний файл покриття, який ваш проєкт уже створює (див. §4).
Встановіть із Marketplace або з файлу .vsix через Extensions → ⋯ → Install from VSIX…. Розширення активується під час запуску та додає піктограму Coverage на панель активності.
У Visual Studio. Той самий продукт виходить як друге розширення, Fucini Coverage Studio для Visual Studio, для Visual Studio 2022 і 2026 — Community, Professional та Enterprise. Він не використовує власного покриття коду Visual Studio: у Visual Studio 2022 це функція Enterprise, тож у Community та Professional це єдине покриття, яке IDE покаже. Встановіть .vsix, відкривши його — VSIX Installer запитає, в яку Visual Studio — або через Extensions → Manage Extensions; розширення завантажується, коли відкривається рішення або тека. Вікно Coverage потребує Microsoft Edge WebView2 Runtime, який Windows 11 і Visual Studio 2026 уже мають; позначки в редакторі працюють і без нього.
3. Швидкий старт
Хочете побачити, як це працює, ще до налаштування власного проєкту? Завантажте демонстраційний проєкт (~6 КБ — крихітний C-проєкт із готовим lcov.info):
- Розпакуйте його будь-де, потім відкрийте
coverage-studio-demo.code-workspaceу VS Code (File → Open Workspace from File…). - Встановіть Fucini Coverage Studio, якщо ще не зробили цього (див. §2 вище).
- Власний
.vscode/settings.jsonробочої області вже вказує на вбудованийcoverage/lcov.info, тож смуги покриття та подання Covered Files з'являються одразу після активації розширення — крокLoad Coverageне потрібен. - Хочете самостійно перегенерувати файл трасування (наприклад, з іншим компілятором)? Запустіть
scripts/gen-coverage.sh(або.ps1у Windows) — доступні цілі компіляторів дивіться у власномуREADME.mdробочої області.
У Visual Studio. Відкрийте рішення або теку (File → Open → Folder — так відкривають проєкт CMake) — демо вище відкривається як тека, і його .vscode/settings.json читається і там. Звіт у місці, яке називають налаштування, завантажується сам, а панель Fucini Coverage вікна Output каже, які файли; інакше — Tools → Coverage Studio → Load Coverage File…, один раз — це запам'ятовується. Відкрийте вихідний файл і виберіть Show Coverage in Editor: червоне — рядок, що ніколи не виконувався, бурштинове — рішення, ухвалене лише в один бік, а Ctrl+Shift+U, N переходить до наступного непокритого рядка. View → Other Windows → Coverage — це дерево з числами кожного файлу та одним балом над усіма, який рядок стану показує для запуску і для файлу, в якому ви перебуваєте. Tools → Coverage Studio → Getting Started відкриває ці кроки як сторінку з кнопкою для кожного; першого разу вона відкривається сама.
- Створіть файл трасування покриття за допомогою звичайного робочого процесу тестування.
- Палітра команд (
Ctrl+Shift+P) →Fucini Coverage: Load Coverage. За увімкненогоwatch.enabled(типово), відповідний файл завантажується автоматично. - Відкрийте вихідний файл із покриттям: рядок стану показує його відсоток, подання Coverage заповнюється, наведення на рядок показує кількість влучань, а прогін з'являється в нативній панелі Test Coverage. Смужки на непокритих рядках, теплова карта влучань і вбудовані лічильники
×N— за одне налаштування звідси (editorGutter.mode,hitCounts.inline).
Screenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).4. Створення файлів трасування
Під час завантаження автоматично розпізнаються будь-які з наведених нижче:
Повні рецепти «скопіюй і встав» для кожного компілятора — зокрема Swift, Rust, Go, Python, .NET, PHP та інших — на сторінці Рецепти покриття: 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
JSON від llvm-cov — найбагатше джерело даних: окрім рядків, гілок і функцій він містить регіони, MC/DC та інстанціації шаблонів C++.
C / C++ — GCC (gcov → lcov)
gcc --coverage calc.c calc_test.c -o test && ./test
lcov --capture --directory . --output-file lcov.info
# or gcovr --cobertura coverage.xml
# or skip the conversion entirely: gcovr --json coverage.json
JavaScript / TypeScript — Istanbul / nyc
nyc --reporter=json mocha # emits coverage/coverage-final.json
Java — JaCoCo
mvn test # emits target/site/jacoco/jacoco.xml
Ruby — SimpleCov
# .resultset.json (built-in) or coverage.json via the simplecov-json gem
Go
go test ./... -coverprofile=coverage.out # read directly, no conversion
Python — coverage.py
coverage run --branch -m pytest && coverage json # emits coverage.json
PHP — PHPUnit (Clover)
XDEBUG_MODE=coverage phpunit --coverage-clover clover.xml
.NET / C# — Coverlet (OpenCover)
dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
| Формат | Типовий файл | Додаткові метрики |
|---|---|---|
| LCOV | lcov.info | рядки, гілки, функції |
| llvm-cov JSON | coverage.json | + регіони, MC/DC, інстанціювання |
| Cobertura XML | coverage.xml | рядки, гілки |
| JaCoCo XML | jacoco.xml | рядки, гілки, функції |
| Istanbul / nyc | coverage-final.json | інструкції, гілки, функції |
| SimpleCov | .resultset.json | рядки |
| Clover XML | clover.xml | рядки, гілки, функції |
| OpenCover XML | coverage.opencover.xml | рядки, гілки, функції |
| coverage.py JSON | coverage.json | рядки, гілки |
| gcov / gcovr JSON | coverage.json | рядки, гілки, функції |
| Go coverage profile | coverage.out | рядки |
| SonarQube generic | coverage.xml | рядки, гілки |
| GNATcoverage XML (Ada) | *.xml | рядки, гілки, MC/DC |
| BullseyeCoverage XML | coverage.xml | рядки, умови/рішення |
| Visual Studio | *.coveragexml | рядки, гілки |
| Coveralls JSON | coveralls.json | рядки, гілки |
| Xcode xccov JSON | coverage.json | функції та підсумки за файлами — без даних по рядках |
| gcov plain text | *.gcov | рядки, гілки, виклики функцій |
| VectorCAST | coverage.xml | рядки, гілки, пари MC/DC, функції, виклики функцій |
| Testwell CTC++ | *.txt | рядки, умови/рішення |
| Lauterbach TRACE32 | *.xml | оператори, рішення, умови, MC/DC, функції, виклики, об'єктний код |
| EMMA XML (Java) | coverage.xml | рядки |
| UCIS / Aldec UCDB | *.xml | оператори, гілки рішень |
| NCover XML | Coverage.xml | рядки, функції |
| dotCover DetailedXML | dotCover.xml | рядки, функції |
| PIT (mutation) | mutations.xml | оцінка мутацій — без покриття |
| Stryker (mutation) | mutation-report.json | оцінка мутацій — без покриття |
Нативний проєкт C++, виміряний із Visual Studio
У Visual Studio. Власне покриття проєкту C++ у Visual Studio було лише в Enterprise, а безкоштовний плагін OpenCppCoverage, що закривав цю прогалину, знято з підтримки. Tools → Coverage Studio → Run Native Project with Coverage бере стартовий проєкт — .vcxproj — питає в MSBuild, куди він збирається і на якому наборі інструментів, і вимірює його одним із двох способів. На наборі інструментів ClangCL, з llvm-profdata і llvm-cov із LLVM на машині (їх приносить компонент Visual Studio C++ Clang tools for Windows), він збирає проєкт заново в coverage\native\ з -fprofile-instr-generate -fcoverage-mapping, через props-файл, який MSBuild велено імпортувати першим — у проєкті нічого не змінюється, — запускає програму із заданим LLVM_PROFILE_FILE, зливає профіль і експортує coverage\native\lcov.info, з точністю до регіону. На будь-якому іншому наборі інструментів, зі встановленим OpenCppCoverage, він збирає проєкт як є — у збірки Debug є PDB — і запускає його під OpenCppCoverage, який пише coverage\native\opencppcoverage.xml. Кожна команда потрапляє в панель Fucini Coverage, а звіт завантажується й запам’ятовується, як звіт тестового запуску. Проєкту, який не можна виміряти, повідомляється чому і що встановити. MSBuild 17.8 (Visual Studio 2022 17.8) або новіший — заради питання, яке він ставить.
Screenshot pending — add assets/img/vs-native-run.gif (see SCREENSHOTS.md).5. Завантаження та пошук
Типово розширення сканує від кореня робочої області. Уточніть це двома налаштуваннями:
{
"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"
]
}
- Кожен запис
pathsє відносним щодоdefaultLocation(або кореня робочої області, якщо не задано). - Запис із
*шукається рекурсивно; просте ім'я файлу збігається лише безпосередньо в базовій папці. - Коли
pathsпорожній, розширення шукає спершуcoverage.json, потімlcov.info, завантажуючи те, що знайде першим. - Pick Coverage File використовує вибрані вами файли замість цих шляхів — кожен вибір додається до набору, і всі вони об’єднуються — доки ви їх не вивантажите або не зміните ці налаштування.
- Змінні — кожне налаштування шляху розгортає
${workspaceFolder},${workspaceFolderBasename},${userHome},${env:NAME},${command:id}і${config:section.key}. Змінна, якої розширення не знає, залишається як записано, тож помилка друку з'являється в журналі пошуку як шлях, який шукали, а не зникає безслідно.${command:id}спершу виконує цю команду — лише в довіреній робочій області й щонайбільше п’ять секунд, — тож${command:cmake.buildDirectory}слідує за вибраним набором CMake. - Записи-URL — запис
http(s)://отримується у сховище розширення при кожному завантаженні й читається звідти; подання Coverage називає URL-адресу. Кожне отримання умовне (ETag / Last-Modified), тож незмінений артефакт нічого не завантажує, а коли отримання не вдається, натомість завантажується остання завантажена копія, з причиною у виводі.remote.headersдодає заголовкиName: valueіз розгорнутими змінними,remote.refreshMinutesповторно отримує за таймером, а фрагмент#lcov.infoназиває формат, коли сама адреса не закінчується на назву файлу. - Глоби ігнорування —
fuciniCoverage.ignoreвідкидає цілі файли (вендорні, згенеровані, сторонні) з прогону під час його завантаження, тож кожне подання, кожен запобіжник і кожен експорт рахують без них; результат завантаження каже, скільки їх пропущено, а вивід називає їх. Шаблони зіставляються зі шляхом відносно робочої області та з абсолютним шляхом, а шаблон без/збігається з назвою теки чи файлу на будь-якій глибині, як у.gitignore. - Багатокореневі робочі області — кожна тека шукається на власних умовах:
defaultLocation,paths,pathRemap,ignore,watch.*іremote.*читаються для кожної теки окремо, тож діє власний.vscode/settings.jsonтеки або її запис у.code-workspace, а${workspaceFolder}у записі означає власну теку цього запису. Файли трасування всіх тек зливаються в один прогін, подання Coverage групує файли за теками, а тека, додана до робочої області або вилучена з неї, сама перезавантажує покриття. - Перезавантаження після завдання —
watch.reloadAfterTasksназиває завдання (labelіз tasks.json абоsource: name, як їх показує список Run Task), завершення яких перезавантажує покриття, незалежно від того, чи ввімкненоwatch.enabled, — для збірок, за якими спостерігач не встигає. Абсолютний записpathsпоза робочою областю теж опитується, тож файл, що там з'явився, завантажується. - Поступ, який можна скасувати — завантаження десяти чи більше файлів трасування, або 8 МБ чи більше їх, виконується під сповіщенням про поступ із кнопкою Cancel, яке називає файл, що читається, і фазу; менше завантаження лише крутить індикатор у рядку стану. Скасування залишає попередній прогін завантаженим і каже про це.
Від 1.2026.6 абсолютний запис теж може містити підстановку: ${workspaceFolder}/build/coverage-merged/*.lcov.info завантажує кожен такий файл у цій теці, а ** означає будь-яку глибину. Пошук іде в теках перед першою підстановкою, і за ними ведеться спостереження, тож звіт, який збірка туди записує, завантажується сам. Редакція для Visual Studio читає такий запис так само, а від 1.2026.5 відносна підстановка і там шукається на будь-якій глибині, як завжди було тут.
Якщо paths не налаштовано, завантажується перший із загальновідомих імен звітів, знайдений у базовій теці. Спершу чотири, які шукалися завжди, — coverage.json, lcov.info, coverage.out, clover.xml, — потім, починаючи з 0.2026.83, jacoco.xml, coverage.xml, cobertura.xml, coverage.cobertura.xml, coverage.opencover.xml і coverage-final.json, а далі місця, куди пишуть типові конфігурації: coverage/ (nyc, Jest, vitest, PHPUnit, SimpleCov), target/site/jacoco/jacoco.xml (Maven), build/reports/jacoco/test/jacocoTestReport.xml (Gradle) і TestResults/*/coverage.cobertura.xml (dotnet test). Тож проєкт на Java чи .NET показує своє покриття вже під час першого відкриття, як це завжди робив проєкт із lcov.
Від 1.2026.3 рішенню .NET потрібно ще менше: тека TestResults/<run>/ кожного тестового проєкту є серед відомих місць, а не лише тека самої робочої області, а <user>_<machine>_<date>.cobertura.xml збирача Microsoft знаходиться поруч із coverage.cobertura.xml від Coverlet — тож рішення, тести якого запускали в Test Explorer Visual Studio, показує своє покриття при першому відкритті, кожна тека запуску завантажується, а злиття зберігає для кожного файлу слово найновішого запуску. А fuciniCoverage.ignore.generated, увімкнений за замовчуванням, залишає файли дизайнера та згенеровані файли — *.Designer.cs, *.g.cs, *.generated.cs, *.razor.g.cs, AssemblyInfo, глобальні using-и, Migrations/ та obj/ — поза кожним підсумком, сторінкою та експортом ще до застосування ignore, тож згенерована таблиця, яку ніхто не тестує, не коштує рішенню його порога.
У Visual Studio: покриття після кожного запуску тестів. Запускайте тести як завжди. Tools → Coverage Studio → Collect Coverage in Test Explorer… кладе поруч із рішенням один .runsettings зі збирачем Cobertura від Microsoft. Visual Studio підхоплює його, коли Tools → Options → Test → Auto detect runsettings files увімкнено; інакше виберіть його один раз у Test → Configure Run Settings. Відтоді кожен запуск пише звіт під тестовим проєктом, а стеження за рішенням завантажує його щойно він з'являється, злитий з усім, що називають налаштування — однаково з Test Explorer, з термінала чи зі скрипту. Ніщо не чіпляється до Test Explorer, тож Visual Studio 2026 і Microsoft.Testing.Platform працюють як є. Run Tests with Coverage — команда VS Code: вона розпізнає dotnet test, vitest, jest, pytest, go, cargo, maven, gradle, phpunit і ctest, запускає тести з увімкненим покриттям у вікні Output і завантажує те, що вони записали; тестовий проєкт без coverlet.collector запускається зі збирачем, що постачається з тестовим SDK, а testRun.skipWhenTestsFail залишає на екрані останнє добре покриття, коли запуск завершується червоним.
Артефакт CI за токеном, що перевіряється щочверть години — токен лишається в середовищі, ніколи в 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).Перезавантаження навмисно мовчазне — діалог після кожної збірки є запитанням з однією відповіддю. Не мовчить значок Coverage: поки подання не перед вами, він показує кількість трасувальних файлів, які було прочитано знову, а його підказка називає їх. Відкрийте подання — і лічильник зникає.
Screenshot pending — add assets/img/coverage-badge.gif (see SCREENSHOTS.md).Файли, які ніколи не мають рахуватися, хоч би що казав про них файл трасування:
{
"fuciniCoverage.ignore": ["vendor/**", "**/*.generated.ts", "build/**"]
}
Перезавантаження, коли завершується тестове завдання, для збірки, за якою спостерігач файлів не встигає — прогін, що замінює дерево виводу за символічним посиланням, звіт на мережевому ресурсі, крок покриття, що дообробляє свій файл:
{
"fuciniCoverage.watch.reloadAfterTasks": ["npm: test", "coverage-report"]
}
6. Об'єднання запусків
Кожен наявний запис paths завантажується і зливається в один запуск. Злиття детерміноване — результат не залежить від порядку завантаження — а файл, виміряний більш ніж одним файлом трасування, бере свої числа з того, що має найновіший час зміни на диску: власний повторний запуск модуля заміняє те, що про нього казав ширший, старіший запуск, а не додається до нього. Подання Покриття показує, що це зробило: кожен рядок файлу називає файл трасування, з якого взято його числа, значок обведено там, де ці числа переважили старіший звіт, кожен рядок файлу трасування над деревом рахує, скільки його файлів переважено або переважили інші, а клацання рядка файлу трасування підсвічує його файли в дереві, доки його не клацнути знову (coverageView.mergedMarks вимикає обведення й підсвічування).
Об’єднаний прогін може містити більше, ніж шість класичних метрик, кожну — зі звіту, який її вимірює: виклики функцій, об’єктний код і мутаційний показник поряд із рядками, функціями, регіонами, гілками, MC/DC та інстанціюваннями. Подання Coverage показує стовпець для кожної метрики, яку містить прогін, — і жодного для тієї, якої він не містить, — упорядковані за вагою кожної метрики у вашій оцінці, найважча першою, за будь-якої ширини — те, що не вміщується, прокручується вбік, а не зникає. Перетягніть подання на нижню панель, і воно перетвориться на таблицю. Картки рядка стану, HTML-звіт та експорти CSV і Markdown дотримуються того самого правила: те, що звіт містить, показується, а те, чого він не містить, пропускається, а не друкується як нуль.
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).З якого звіту береться файл
Коли кілька завантажених звітів вимірюють той самий файл, найновіший забирає його цілком — це правильно, коли власний повторний прогін модуля замінює те, що казав старіший, ширший прогін. І неправильно, коли звіти вимірюють той самий код навмисно: тоді редактор перескакує між ними з кожною збіркою, і кожен розповідає лише частину історії. coverageFile.sources каже, що робити натомість, для кожного файлу окремо. Це потрібно у трьох ситуаціях:
- Один звіт кращий.
coverage.jsonвід llvm-cov містить MC/DC, аgcov.infoвід GCC для тієї самої збірки — лише рядки й гілки: виберітьcoverage.json, а інший залиште для тих кількох файлів, які збирає лише GCC. - Кілька наборів тестів однієї збірки. Модульні тести, інтеграційні тести й hardware-in-the-loop пишуть кожен свій звіт; кожен окремо лишає поза увагою рядки, які виконали інші. Поєднати, union: рядок покритий там, де його виконав будь-який звіт, а лічильники додаються.
- Одна кодова база, два компілятори. Ті самі вихідні файли, зібрані clang і GCC, проходять різними шляхами через код, специфічний для інструментарію, — тут intrinsic, там переносний запасний варіант, — і кожен звіт каже, що друга половина ніколи не виконувалася. Поєднати, agree: рядок покритий лише там, де його виконав кожен звіт, що його вимірює, а рядки, щодо яких звіти розходяться, позначено бірюзовим. Саме це питання ставить перевірка між компіляторами: що насправді випробувала кожна збірка, яку я постачаю?
Правила рідко доводиться писати вручну. Клацніть правою кнопкою файл у поданні Покриття і виберіть Choose Coverage Source... (або виконайте Choose Coverage Source for This File... для відкритого файлу): список містить кожен звіт, що вимірює файл, кожен зі своїми рядками, гілками та MC/DC, а далі Combine them — agree і Combine them — union; виберіть один варіант і вкажіть, чи діє він для файлу, його теки чи шаблону. Clear Coverage Source for This File... знову прибирає правило. У налаштуваннях кожне правило — це glob-шаблон над файлами, glob-шаблон над звітом (шаблон без / збігається з іменем файлу звіту, {a,b} називає кілька) і, для поєднання, "combine": "agree" або "union". Вирішує перше правило, чиї файли збігаються і чий звіт вимірює файл; файл, який вимірює лише один звіт, ніколи в нього не забирається. Гілки, MC/DC і регіони поєднаного файлу беруться зі звіту, найповнішого на них. coverageFile.mergeStrategy: "order" вирішує файли, щодо яких не діє жодне правило, за порядком у coverageFile.paths, а не за часом.
{
"fuciniCoverage.coverageFile.paths": ["clang.json", "gcc/bits.gcov.json.gz"],
"fuciniCoverage.coverageFile.sources": [
{ "files": "src/**", "report": "{clang.json,bits.gcov.json.gz}", "combine": "agree" }
]
}
Що ви бачите: рядок файлу в поданні Покриття називає звіт, з якого взято його числа, або, якщо звіти поєднано, кожен звіт і режим із ≠ n для спірних рядків. Поле редактора та Annotated Source позначають ці рядки бірюзовим і кажуть, який звіт скільки разів їх виконав. Спливаюча підказка рядка стану називає джерело відкритого файлу, а для всього прогону — чинні правила і те, як вирішено решту файлів. samples/c-cross-check із демо — це випадок двох компіляторів, готовий до відкриття. Visual Studio робить усе це теж: Choose Coverage Source... на рядку подання Покриття, а також Choose і Clear Coverage Source for This File... у Tools > Coverage Studio.
Вибір і поєднання джерел входять до платних планів. У Community найновіший звіт перемагає в кожному файлі, як і без правила, а про правило в налаштуваннях сказано, що воно не використовується, замість того щоб мовчки його ігнорувати.

bits.c з подання Покриття — звіт clang, звіт GCC або обидва, поєднані разом.


bits.c, clang і GCC, поєднані за agree, — рядок показує ≠ 4, а чотири рядки, які виконала лише одна збірка, бірюзові.
bits.c досягає 100% своїх рядків — а рядки, щодо яких збірки розходяться, лишаються бірюзовими.


7. Переспрямування шляхів
CI часто фіксує абсолютні шляхи збірної машини, яких немає на вашій робочій станції. Перепишіть їх упорядкованими правилами:
{
"fuciniCoverage.pathRemap": [
{ "from": "/builds/ci/project", "to": "${workspaceFolder}" },
{ "from": "\\\\", "to": "/" }
]
}
Правила застосовуються по порядку; для кожного префікса перемагає перший збіг. Використовуйте це, щоб згладити відмінності роздільників Windows/Unix або зіставити шлях контейнера з вашою робочою копією.
Правило рідко доводиться писати самому. Найпоширеніше «завантажилося, а нічого не підсвічується» — це файл трасування, чиї шляхи походять із контейнера або робочої копії CI (/build/src/a.c, /home/runner/work/repo/repo/src/a.c, C:\agent\_work\1\s\src\a.c), тоді як у робочій області є src/a.c. Коли після завантаження лишаються незіставлені файли, розширення шукає їхні назви в робочій області, виводить правило префікса, яке пояснює найбільше з них, записує його в журнал як [FUCINI_REMAP_002], а результат завантаження пропонує Apply Suggested Remap — одне клацання дописує правило до fuciniCoverage.pathRemap і перезавантажує. Suggest Path Remap Rule виконує той самий аналіз на вимогу з палітри. Без клацання нічого не записується.
У to можна використати ${workspaceRoot}, що означає теку робочої області, у якій лежить файл трасування; у багатокореневій робочій області спочатку пробується ця тека, потім кожна інша тека, у якій файл справді знаходиться. Самі правила читаються для кожної теки окремо, тож кожен корінь багатокореневої робочої області може мати власні.
8. Покриття в редакторі
- Смуги та лінійка — типово власне поле редактора показує лише знахідки: смужки MC/DC, трикутники «з попереднього прогону», крапки відредагованих рядків.
editorGutter.modeдодає смужки лише на непокритих рядках або теплову карту влучань (нижче); кольорове подання цілого файлу — це Annotated Source. - CodeLens функцій — відсоток покриття над кожною функцією; клацніть, щоб перейти до першого непокритого рядка. Перемикається через
codeLens.enabled. - Наведення на гілки та MC/DC — наведіть на рядок рішення, щоб побачити кількість спрацювань/невиконань для кожної гілки та таблицю векторів для кожної умови. Увімкніть кольорову смугу на полях через
mcdcGutter.enabled. - Попередження про мертвий код — функції з вимірюваними рядками й нульовим покриттям позначаються на панелі Problems (
deadCode.enabled). - Next / Previous Uncovered — перехід між прогалинами.
- Рядок стану — елемент
$(dashboard) NN%для всього запуску та елемент для окремого файлу, обидва з кольоровим кодуванням за композитним показником; наведіть курсор для повної таблиці метрик. - Значки у Провіднику — значки покриття для файлів і тек, із розбивкою за метриками при наведенні. Типово вимкнено: увімкніть їх параметром
explorerBadges.enabled. - З попереднього прогону — червоний трикутник на кожному рядку, виконаному в попередньому прогоні й не виконаному в цьому, зелений для зворотного випадку, з оглядовою лінійкою та кількістю влучань при наведенні.
- Змінені буфери — кожна позначка, підказка та CodeLens рухаються разом із текстом під час редагування і зникають із переписаного рядка, де сіра крапка пояснює чому.
- Вбудовані лічильники влучань —
hitCounts.inlineдописує×12після кожного рядка, з якого починається інструкція, включно з×0: те саме число, яке завжди було в підказці при наведенні, тільки без наведення. Toggle Inline Hit Counts перемикає його; меню рядка стану пропонує його як «Показати» або «Сховати» залежно від стану. - Порядкові записи в Problems —
problems.perLineставить діагностику рівня Information, із хвилястою лінією в редакторі, на кожен суцільний блок рядків, які жодного разу не виконалися, у відкритому документі (мертва функція на сорок рядків — це один запис, а не сорок) і, якuncoveredAndPartial, на кожен рядок, у якому якусь вітку гілки жодного разу не взято. Записи йдуть за своїми рядками під час редагування й зникають, коли документ закривається; пофайловий запис заproblems.enabledне змінився. - Підфарбовування рядків —
lineHighlightкладе напівпрозоре тло за самі рядки для того, що позначає поле (uncovered, абоheatmapтакож для виконаних рядків). Окремий параметр, тож поле може лишатися чистим, поки прогалини підфарбовані, або навпаки. - Оглядова лінійка —
overviewRulerвирішує щодо смужки на смузі прокручування незалежно від поля:follow(разом зі стовпчиками, як раніше),uncovered(завжди, тож поле може бути вимкнене, а смуга прокручування все одно показує карту прогалин) абоoff. - Який трасувальний файл покрив рядок — коли об’єднано кілька звітів, підказка з кількістю влучень завершується словом Покрито: і кожним звітом, що покрив цей рядок, разом із назвою набору тестів із
TN:у lcov; клацання на рядку трасувального файлу в поданні Coverage підсвічує внесені ним рядки в кожному відкритому редакторі.
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).Режими поля редактора
editorGutter.mode вирішує, що власне поле редактора показує про покриття понад знахідки, які воно показує завжди. off (типово) — лише вони. uncovered ставить смужку на кожен рядок, який жодного разу не виконався, і бурштинову — на кожен рядок, у якому якусь вітку гілки жодного разу не взято, а на покритих рядках нічого, тож зелена стіна не ховає три червоні. coverage додає зелену смужку на кожен покритий рядок, тож увесь файл читається червоним, бурштиновим і зеленим у кольорах колірної шкали. heatmap натомість додає теплий відтінок на кожен виконаний рядок — тим гарячіший, чим частіше він виконувався; він показує, як часто рядок виконувався, а не чи він покритий, тож файл зі 100% там від жовтого до коричневого, але ніколи не зелений. Choose Editor Gutter Mode... вибирає режим із палітри або з меню рядка стану; кнопка режиму праворуч у рядку стану або Alt+G одним натисканням переходить до наступного (statusBar.showModeToggle ховає кнопку). Обидва записують налаштування. Приклад вмикає смужки на непокритих рядках і вбудовані лічильники разом:
{
"fuciniCoverage.editorGutter.mode": "uncovered",
"fuciniCoverage.hitCounts.inline": true
}
Screenshot pending — add assets/img/gutters.png (see SCREENSHOTS.md).
coverage — зелений там, де рядок виконався повністю, бурштиновий там, де якусь вітку гілки жодного разу не взято, червоний там, де нічого не виконалося. Елемент файлу в рядку стану називає звіт, з якого взято його числа; кнопка режиму поруч показує Coverage.
Alt+G чотири рази — heatmap, off, uncovered і знову coverage.
Quote.cs.Теплова карта відносна щодо файлу. Відтінок рядка порівнює його лічильник із найгарячішим рядком того самого файлу за логарифмічною шкалою, у п’ять кроків — тож тіло циклу, яке виконалося тисячу разів, і функція, яка виконалася двічі, видимі обидва, а не одне заглушує інше, а файл, у якому все виконалося рівно один раз, рівномірно теплий, а не рівномірно блідий. У темній темі градієнт іде від тьмяного оливкового до яскравого помаранчевого, у світлій — від блідо-жовтого до коричневого: в обох випадках більше кольору означає більше виконань, а червоний залишається лише для рядків, які ніколи не виконувалися. lineHighlight: "heatmap" кладе ті самі відтінки заливкою за кодом, а hitCounts.inline записує точний лічильник після рядка.
{
"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).Кольори — ваші. colorScale.lowColor, midColor і highColor фарбують червоний, бурштиновий і зелений у полі, у заливках і в кожному відсотку; heatmap.colors і heatmap.colorsDark містять п’ять відтінків теплової карти для світлої й темної теми, від рядка, що виконувався найрідше, до того, що виконувався найчастіше. Сторінка налаштувань показує результат ще до збереження: у розділі Colour scale попередній перегляд лишається на виду, поки рядки прокручуються повз нього, — градієнт із двома опорними точками, кілька відсотків у їхніх кольорах і маленькі світлий і темний редактори, пофарбовані в режимі coverage і тепловою картою, — і перемальовується, щойно вибрано колір.
{
"fuciniCoverage.heatmap.colors": ["#e3f2fd", "#90caf9", "#42a5f5", "#1e88e5", "#0d47a1"]
}


Частина рядка, яка жодного разу не виконалася
Рядок або покрито, або ні, а правда часто десь посередині: return x > hi ? hi : x; виконався, а його гілка hi — жодного разу. Коли lineHighlight увімкнено, ніколи не виконана частина виконаного рядка підфарбовується в редакторі — для кожного формату, що містить діапазони стовпців (llvm-cov, Istanbul, Go, dotnet-coverage); це ті самі фрагменти, які позначає анотований вихідний код. Лише в рядках, що виконалися: рядок, який жодного разу не виконався, уже позначено цілком. Шаблон C++ вважається виконаним там, де його виконало будь-яке інстанціювання; що зробило кожне окреме інстанціювання, показує метрика інстанціювань.
Screenshot pending — add assets/img/partial-line.png (see SCREENSHOTS.md).Які тести виконали цей рядок
Деякі звіти повідомляють не лише те, що рядок виконався, а й те, які тести його виконали: coverage.py, записаний із coverage json --show-contexts і dynamic_context = test_function у .coveragerc, OpenCover, зібраний із -coverbytest, і файл трасування lcov, записаний по одній секції на тест (TN:), секції якого додаються в один запис із тестами біля кожного рядка. Наведіть вказівник на початок рядка, де стоїть лічильник виконань, — і тести буде названо: скорочено до класу й методу, перші п’ять поіменно, решту — числом; CodeLens функції каже, скільки тестів її виконали. Show Tests That Ran This Line — Command Palette, контекстне меню редактора, у Visual Studio Tools → Coverage Studio або Ctrl+Shift+U, T — перелічує їх, найактивніші першими, і відкриває вибраний там, де його написано в робочому просторі. Запуск dotnet test не може сказати, який тест що виконав; задайте testRun.perTest, і Run Tests with Coverage перелічить тестові класи й запустить їх по одному, позначаючи кожен звіт його класом, щоб підказка, лінза й команда могли відповісти й для .NET. Ці дані зберігаються для кожного файлу окремо, тож переживають злиття зі звітом, який нічого не знає про тести.
{
"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 — тест, який його виконав, і Go to Test, що відкриває цей тест.Пройшов чи ні — на позначках
Покритий рядок має однаковий вигляд, пройшов його тест чи ні. Там, де звіт каже, які тести виконали рядок, і файл результатів виконувача каже, чим вони завершилися, рядок, який виконав тест, що не пройшов, дістає червону смужку на початку й риску на оглядовій лінійці; його підказка називає тести, що не пройшли, а Show Tests That Ran This Line пише failed біля кожного. Коли тест червоний, дивитися треба в код, який він виконував. Результати читаються під час кожного завантаження з теки кожного звіту — будь-який .trx та імена, під якими записують результати JUnit (TEST-*.xml, junit*.xml, test-results*.xml), — і з testResults.paths, як шляхи або glob-шаблони відносно теки. Run Tests with Coverage просить у dotnet test файл test-results.trx поруч зі звітом, тож з увімкненим testRun.perTest нічого налаштовувати не треба. testResults.enabled вимикає це читання.
{
"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).Тести, яких стосується зміна
Повний запуск повільно відповідає на те, на що Run Tests Affected by My Changes… відповідає одразу: які з усіх тестів виконували код, який я щойно редагував? У git запитується diff робочого дерева відносно testImpact.baseRef — типово HEAD, тобто те, що ще не закомічено; origin/main — для всього, що змінює гілка, — і перелічуються тести, які виконали змінений рядок, першим той, що виконав найбільшу частину зміни. Вибір тесту відкриває його. Там, де звіти походять із потестового запуску (testRun.perTest), перший пункт запускає лише ці тести, кожен клас у власний звіт, тож звіти всіх інших класів лишаються, а підсумки залишаються підсумками всього набору. Тест, який виконав лише рядки нижче від вставки чи вилучення, теж є в списку: інакше його звіт називав би не ті рядки.
Screenshot pending — add assets/img/test-impact.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-test-impact.gif (see SCREENSHOTS.md).Найменше тестів, які все ще виконують кожен рядок
Show Minimal Test Set… відповідає на два запитання з тих самих потестових рядків: які кілька тестів усе ще виконували б кожен рядок, який виконує набір, — для швидкого запуску перед комітом, — і які тести не виконують жодного рядка, якого б уже не виконував інший. Спершу йдуть вибрані тести, кожен із рядками, які він додає, і рядками, які виконує лише він; далі решта, кожен із позначкою, що нічого не додає. Вибір жадібний — тест, що виконує найбільше, потім той, що додає до цього найбільше, — тож він близький до найменшого набору й щоразу той самий. Зайвий за рядками — не означає зайвий за тим, що тест перевіряє: тест, який не додає жодного рядка, усе одно може бути єдиним, що перевіряє значення, обчислене в цих рядках. Список каже, куди дивитися, коли набір проріджують, і ніколи — що видаляти.
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).Запустити цей тест, із покриттям
Поставте курсор у тест і виконайте Run This Test with Coverage — Command Palette, контекстне меню редактора, у Visual Studio Tools → Coverage Studio або Ctrl+Shift+U, R — і лише цей тест запуститься з увімкненим покриттям: тестовий метод, у якому стоїть курсор, або тестовий клас чи блок describe, коли він між методами, або файл, коли він вище за всі класи. Що під курсором, читається з тексту, тож це працює для C#, VB і F# ([Fact], [Test], [TestMethod] тощо), JavaScript і TypeScript (it, test, describe) та Python (def test_…), хоч би яку мовну службу було встановлено. Рецепт теки звужується до нього — dotnet test --filter "FullyQualifiedName~…", jest або vitest <file> -t "…", ідентифікатор вузла pytest, — а те, що він записав, завантажується як будь-який запуск; виконувач, якого не можна звузити, повідомляє про це, і Run Tests with Coverage запускає всі.
Screenshot pending — add assets/img/run-this-test.gif (see SCREENSHOTS.md).
[Fact] — прогін у списку Tracefiles, рядки над методами кажуть, що код виконав один тест.Go і Rust. У файлі Go func TestXxx під курсором (або Fuzz…, Example…) запускається сам, у власному пакеті й за точним іменем — go test ./pkg/calc -run "^TestTotal$", — а поза тестом запускається пакет файлу. У файлі Rust функція #[test] запускається за своїм шляхом у крейті з --exact; коли курсор у mod і поза будь-яким тестом, запускаються тести цього модуля; інтеграційний тест у tests/ запускається у власному бінарному файлі (--test api). Виконувачу передаються лише файли його мови: файл TypeScript у теці Go дістає речення, а не порожній запуск.
Покриття після кожного збереження
З увімкненим testRun.onSave збереження джерела запускає тести, що його покривають, із покриттям, за мить після збереження, і поле редактора йде слідом. Для рішення .NET проєкт збереженого файлу знаходиться через граф .csproj, і запускаються лише тестові проєкти, які на нього посилаються — безпосередньо чи через інші проєкти, — по одному dotnet test <project> на кожен; будь-який інший виконувач виконує весь свій рецепт; файл, яким не володіє жоден проєкт і який не вимірює жоден звіт, не запускає нічого. Кілька збережень поспіль — один запуск, а запуск, що вже триває, не переривається. Решта — як це робить Run Tests with Coverage: термінал, панель Output, завантажений звіт. Типово вимкнено — це звичка, яку обирають, а не типове налаштування, яке виявляють.
{
"fuciniCoverage.testRun.onSave": true
}
Screenshot pending — add assets/img/coverage-on-save.gif (see SCREENSHOTS.md).
testRun.onSave увімкнено — Quote.cs збережено, тести запускаються самі, рядок над методом змінюється.Сам застосунок, із покриттям
Тестовий запуск каже, до чого доходять тести. Те, до чого доходить людина, — проклацуючи екрани перед випуском, відтворюючи кроки клієнта, — теж покриття, і Run App with Coverage… його збирає. Застосунок .NET із теки — Exe, WinExe, вебпроєкт чи worker-проєкт, але ніколи не тестовий проєкт; де їх кілька, пропонується вибір — запускається під dotnet-coverage від Microsoft у власній консолі, щоб у консольний застосунок можна було вводити, і працює, доки ви його не закриєте. Те, що ви пройшли, потім завантажується як будь-який запуск, а в сеансі покриття додається до того, що виконали тести. Те, як застосунок завершився, на запуск не впливає. Інструмент потрібно один раз установити: 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).Мутанти — і де саме вони є
Інструмент мутаційного тестування — PIT для Java, Stryker для JavaScript, C# і Scala, Mull для C і C++ — вносить у ваш код дрібні зміни й запускає тести проти кожної з них. Зміна, якої не помітив жоден тест, — це мутант, що вижив: код виконався, але ніщо не перевірило, що саме він зробив. Мутаційна оцінка показує, скільки мутантів було виявлено; починаючи з 0.2026.83 редактор показує, де перебувають решта. Рядок із мутантом має примітку після себе (⚑ 2 mutants survived), змінений текст підкреслено, якщо звіт указує, який саме це був текст (Stryker і Mull це роблять), на оглядовій лінійці з’являється смужка, а підказка під час наведення показує, що було змінено, скільки тестів виконали цей код і — для виявлених мутантів — який тест їх виявив.
Screenshot pending — add assets/img/mutant-hover.png (see SCREENSHOTS.md).Вижив означає, що тести виконали змінений код і всі пройшли. Не протестовано (у звіті — no coverage) означає, що цей код не виконує взагалі жоден тест, тож помітити зміну не було кому. Виявлені мутанти підраховуються в підказці під час наведення й ніколи не позначаються, а мутанти, які ніколи не були чесною перевіркою, — наприклад, такий, що не скомпілювався б, — залишаються поза оцінкою. Анотований вихідний код має рядок під кожним таким рядком і кнопку Next Mutant (U), а HTML-звіти мають розділ Surviving Mutants із посиланням на рядок. Нічого не потрібно вмикати, а проєкт без мутаційного звіту нічого з цього не бачить.
Screenshot pending — add assets/img/mutants.gif (see SCREENSHOTS.md).Чи помітив би тест? Мутаційний запуск під курсором
Мутаційний запуск проєкту триває годину; однієї функції — хвилину. Run Mutation Tests Here запускає саме цю хвилину: функція, у якій стоїть курсор, — або виділені рядки, або файл — це те, що мутаційному виконувачу теки сказано мутувати, а його звіт завантажується поруч із покриттям на екрані, де позначено мутантів, що вижили. Для C# це Stryker.NET (dotnet tool install --global dotnet-stryker), якому передається діапазон символів і тестовий проєкт, що посилається на проєкт файлу; для JavaScript і TypeScript — StrykerJS, якому передаються рядки; для Java — PIT із Maven, якому передається клас. Те, як виконувач завершився, на запуск не впливає: оцінка, нижча за його поріг, — це код виходу, і все одно звіт. Про виконувач, який нічого не записав, повідомляється — разом із тим, що для нього треба встановити.
Screenshot pending — add assets/img/mutation-here.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-mutation-here.gif (see SCREENSHOTS.md).Власне подання Test Coverage VS Code
З увімкненим testCoverage.publish (типово) кожен завантажений прогін іде також у нативне подання Test Coverage редактора — панель покриття в Test Explorer, пофайлові відсотки, які воно ставить у Провіднику, і власний перемикач редактора Show Inline Coverage — як рядки, вітки гілок і функції, з деталями, що завантажуються на вимогу, з якого б файлу трасування вони не походили й без жодного тестового адаптера. Show in Test Coverage View публікує активний прогін і відкриває панель, хоч би що казало налаштування; меню рядка стану пропонує це за quickActions.showTestCoverage. Вимкнено — запис Fucini Coverage у Test Explorer не з'являється взагалі. Коли трасувальний файл називає свої тести (секції TN: у lcov), кожен тест з’являється під Fucini Coverage у Test Explorer, і подання може фільтрувати покриття файлу за тестом.
Screenshot pending — add assets/img/test-coverage-view.png (see SCREENSHOTS.md).Непокриті рядки на панелі Problems
Типово вимкнено, бо за своєю природою галасливе, і лише для відкритих документів — прогін на дві тисячі файлів не затопить панель. Не залежить від problems.enabled, який тримається одного запису на файл:
{
"fuciniCoverage.problems.perLine": "uncoveredAndPartial"
}
Screenshot pending — add assets/img/problems-panel.png (see SCREENSHOTS.md).9. Покриття diff
Обмежте оформлення лише рядками, що змінилися відносно базового посилання git, — ідеально для перевірки того, що саме покрив (або не покрив) PR:
{
"fuciniCoverage.gitDiff.enabled": true,
"fuciniCoverage.gitDiff.baseRef": "origin/main"
}
Screenshot pending — add assets/img/diff-coverage.png (see SCREENSHOTS.md).У Visual Studio. Ті самі два налаштування, читані з тих самих файлів: розширення саме виконує git diff <baseRef> для кожного файлу запуску і звужує запуск до рядків, які змінила ваша гілка — на полі, у вікні Coverage і в порогах. Панель Output каже, що відповів git, коли він не відповідає нічого.
Поріг для нового коду
threshold.newCode — окремий поріг поруч із порогами для всього запуску: найменший відсоток вимірюваних рядків, змінених відносно gitDiff.baseRef, який має бути виконано. Проєкт із 62% загалом усе одно може вимагати, щоб написане сьогодні було протестовано. Він рахується під час кожного завантаження на всьому запуску, який лишається на екрані, — gitDiff.enabled — це інше: змінені рядки замість запуску. Check Coverage Thresholds і записи відповідності на панелі Problems повідомляють про його непроходження окремим реченням: New code 72.00% < 80% (18 of 25 line(s) changed against origin/main ran). Зміна без жодного вимірюваного рядка — коментарі, README — нічого не провалює.
{
"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).Новий код за тегом, за автором, за датою
Новий код типово — це рядки, які робоче дерево змінює відносно gitDiff.baseRef — гілки, коміту або тегу: "v1.4.0" — це все від того випуску. Два налаштування питають про те, чого посилання не може. gitDiff.author приймає частину імені автора, і тоді новий код — це рядки, які git приписує цьому автору; gitDiff.since приймає день, і це рядки, востаннє змінені того дня або пізніше, хоч би якою гілкою вони прийшли; обидва разом — рядки цього автора від того дня. Вони читаються з git blame, файл за файлом, — що великий запуск відчує під час кожного завантаження, — і заступають diff для покриття diff і для порога вище. Ще не закомічений рядок рахується в будь-якому разі.
{
"fuciniCoverage.gitDiff.author": "Ada",
"fuciniCoverage.gitDiff.since": "2026-09-01"
}
Screenshot pending — add assets/img/new-code-author.png (see SCREENSHOTS.md).Непрямі зміни: що змінилося, хоча ніхто цього не чіпав
Diff каже, які рядки змінилися; два запуски кажуть, які рядки перестали або почали виконуватися. Варті уваги ті рядки, де ці двоє розходяться: код, якого ніхто не редагував і який більше не виконується, бо видалено тест, гілка раніше за ходом виконання тепер повертається достроково, змінилася фікстура. Рецензія diff їх побачити не може — вони поза ним за означенням. Show Indirect Coverage Changes… перелічує їх за файлами, першим той, що втратив найбільше, і відкриває вибраний на першому такому рядку. Запуск звіряється з базовою лінією CI, якщо baseline.report її називає, — саме за нею оцінюють pull request, — а інакше з попереднім запуском; рядки, які робоче дерево змінює відносно gitDiff.baseRef, і все нижче від місця, де ця зміна зсуває рядки файлу, пропускаються.
Screenshot pending — add assets/img/indirect-changes.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-indirect-changes.png (see SCREENSHOTS.md).10. Композитний показник
Замість звітування шести окремих чисел, розширення згортає їх в один Зважене гармонічне середнє (WHM). Для метрик із відсотками pᵢ та вагами wᵢ:
WHM = ( Σ wᵢ ) / ( Σ wᵢ / pᵢ )
У гармонічному середньому домінує найменший доданок, тож слабку метрику не можна замаскувати ідеальною — саме та властивість, яка потрібна для запобіжника безпеки. Типові ваги:
| Метрика | Вага | Обґрунтування |
|---|---|---|
| MC/DC | 4 | IEC 61508 SIL 3–4 / ISO 26262 ASIL C–D / DO-178C DAL A–B. |
| Гілки | 2 | IEC 61508 SIL 2+ / ISO 26262 ASIL B+. |
| Умови | 3 | Між гілками та MC/DC (DO-178C, ISO 26262). |
| Регіони | 1.5 | Шляхи всередині інструкції (напр., часткове коротке замикання). |
| Рядки | 1 | IEC 61508 SIL 1+ / ISO 26262 ASIL A+. |
| Функції | 1 | Перевірка на мертвий код. |
| Інстанціювання | 0.5 | Покриття шаблонів C++; найвужча область. |
| Виклики функцій | 1 | Місця виклику, які було виконано (gcov, VectorCAST, Testwell CTC++, TRACE32). |
| Об’єктний код | 0 | Вимкнено, доки ви не надасте йому ваги: він поглинає покриття операторів. |
| Мутаційний показник | 0 | Вимкнено, доки ви не надасте йому ваги: це не покриття. |
Встановіть будь-яку вагу в 0, щоб виключити цю метрику з показника. Метрики, відсутні в даних (наприклад, MC/DC у звичайному запуску lcov), просто пропускаються.
Об’єктний код і мутаційний показник мають вагу 0, доки ви не вирішите інакше (whmWeights.objectCode, whmWeights.mutation). Покриття об’єктного коду поглинає покриття операторів, тож зважувати обидва означає двічі рахувати той самий доказ; мутаційний показник узагалі не є покриттям — набір тестів може виконати кожен рядок і нічого не виявити. Обидва все одно мають власний стовпець і власний поріг.
Покриття умов
a && b — це одне рішення (дві гілки) і дві умови з чотирма результатами. Набір тестів може пройти обидві гілки й жодного разу не побачити b хибним: покриття гілок повне, а покриття умов — три з чотирьох. Цей рівень у DO-178C та ISO 26262 розташований між покриттям гілок і MC/DC, і починаючи з 0.2026.83 це окрема метрика, а не складова гілок: рядок у картках рядка стану, стовпець у поданні Coverage, у звітах та експортах, вага 3 в оцінці (whmWeights.conditions) і запобіжник (threshold.conditions; без запобіжника в профілі standard, 100 у профілі safety).
Зчитується з проб condition BullseyeCoverage, з експорту cond TRACE32 та з GCC 14, зібраного з -fcondition-coverage. Звіт, який не відрізняє умови від рішень, не має ні такого рядка, ні стовпця, ні ваги. Якщо ви використовуєте Bullseye або TRACE32: раніше умови рахувалися як гілки, тому з цим випуском ваш відсоток гілок зміниться, а з новою вагою — і ваша зведена оцінка; установіть для whmWeights.conditions значення 0, щоб отримати оцінку такою, якою вона була.
GCC 14, рядок за рядком. -fcondition-coverage змушує gcov казати, якого результату якої умови бракує — умова 1 ніколи не істинна, умова 0 не мала жодного з двох результатів, — і кожна умова позначається у своєму рядку й називається в підказці, з JSON gcov і з його текстового лістингу (condition outcomes covered 3/6). Метрика є там, де й інші: threshold.conditions задає для неї поріг і лишається без оцінки там, де запуск не має такого показника, Copy Coverage Summary має стовпець Conditions, badge.metric приймає conditions, а поле пошуку приймає conditions < 80. Показник гілок функції не враховує результатів її умов, як і показники файлу та запуску.
Screenshot pending — add assets/img/gcc-conditions.png (see SCREENSHOTS.md).Складність і CRAP
Деякі звіти містять цикломатичну складність кожної функції: OpenCover (саме цей формат записує Coverlet), JaCoCo, Clover і Cobertura. Там, де вона є, розширення обчислює для функції показник CRAP — Change Risk Anti-Patterns — на основі цієї складності та покриття, яке воно виміряло саме:
CRAP = complexity² × (1 − coverage)³ + complexity
Проста, повністю протестована функція отримує власну складність і нічого більше; складна, ледь протестована — сотні. У прикладі C# демонстраційного проєкту Price() має складність 22 і близько 37% покритих рядків, що дає 142,2, тоді як Shipping() має складність 12 і повністю покрита, що дає 12. Загальноприйнята межа — 30: функція, яка її досягає або перевищує, потрапляє до списку Riskiest Methods у HTML-звіті, найгірші — першими.
Складність і показник наведено в CodeLens функції та поряд із функцією в анотованому вихідному коді. Max CRAP — це найвищий показник серед усіх функцій файлу — найгірший, а не середній — і він є стовпцем у поданні Coverage, HTML-звіті та експортах CSV і Markdown. Це довідкова інформація: він не має ні порога, ні ваги в композитному показнику. Звіти без даних про складність (lcov, gcov, Istanbul, coverage.py) не мають CRAP, і порожнього стовпця теж.
Починаючи з 0.2026.83 він є також для C і C++. llvm-cov не повідомляє складність, тому її підраховують за даними про гілки, які звіт уже містить: умови, записані у власному файлі функції, плюс один — це визначення McCabe, і саме це рахують інструменти рівня вихідного коду для .NET і Java. Умови, що походять із макросу з іншого файлу, — наприклад, кожен assert — не враховуються.
Screenshot pending — add assets/img/riskiest-methods.png (see SCREENSHOTS.md).Risk hotspots, і які файли показувати
Під деревом подання Coverage Risk hotspots перелічує функції, де складний код зустрічається з малим покриттям, найгірші першими, і кожна відкриває свій файл на цій функції. Функція потрапляє туди за оцінкою CRAP — hotspots.crapThreshold, за замовчуванням 30, число, яке запропонували автори метрики — або лише за цикломатичною складністю, hotspots.complexityThreshold, за замовчуванням вимкнено; їх мають лише звіти, що несуть складність (OpenCover, Cobertura від Coverlet, JaCoCo, llvm-cov). Community бачить кількість і найгіршу оцінку; ранжований список — у Pro. Поруч із сортуванням другий випадний список каже, які файли показує дерево — усі, файли з прогалинами, непротестовані файли або файли, змінені від останнього запуску; теки йдуть за своїми файлами і зберігають власні числа. Обидва є і у Visual Studio, у вікні Coverage.
Screenshot pending — add assets/img/vs-hotspots.png (see SCREENSHOTS.md).Простори імен, класи й методи
Для звіту .NET, що називає свої класи — Cobertura і coverage.cobertura.xml від Coverlet, OpenCover, — третій випадний список, Folders / Namespaces, малює той самий запуск як простори імен, класи й методи: число простору імен — сума його класів, число класу — його методів, точно так само, як число теки — сума її файлів, з тим самим сортуванням і тим самим фільтром. Рядок методу відкриває файл на цьому методі; клас, оголошений поза простором імен, стоїть під (no namespace). Вибір записується в coverageView.perspective; запуск, що не несе імен класів, не має випадного списку й показує свої теки. У Visual Studio вікно Coverage має той самий випадний список.
Screenshot pending — add assets/img/namespace-perspective.png (see SCREENSHOTS.md).
Пошук у дереві
Під кнопками й випадними списками — поле пошуку. Слово залишає рядки, чиє ім’я або шлях його містять — кожне введене слово має бути там; порівняння залишає рядки, чия цифра йому відповідає — < 80% за оцінкою, lines >= 90, branches = 0, functions != 100, mcdc < 50, — а invoice < 80 вимагає обох. Рядки методів із перспективи просторів імен і точки ризику шукаються разом із файлами, тож функція знаходиться там, де вона є в запуску. Дерево фільтрується під час набору, у сторінці, без перемальовування; тека зі збігом розкривається для нього й знову згортається, коли поле порожніє; Esc очищає його. Те саме поле, та сама граматика — у Visual Studio.
Screenshot pending — add assets/img/tree-search.gif (see SCREENSHOTS.md).lines < 80.Дерево йде за редактором
Файл, на який ви дивитеся, підсвічено в поданні Coverage, теки над ним розгорнуто, а його рядок прокручено в поле зору — у дереві більше не треба шукати файл, який уже відкрито. В іншому дерево зберігає свою позицію прокручування, і нічого не перемальовується. coverageView.followActiveEditor, типово ввімкнений, вимикає це для тих, хто воліє лишати дерево там, де його поставив.
Screenshot pending — add assets/img/follow-editor.gif (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-follow-editor.gif (see SCREENSHOTS.md).11. Перевірка відповідності
Вердикт COMPLIANT / NON-COMPLIANT (показаний в анотованому перегляді джерела, HTML-звіті та обох спливаючих підказках рядка стану) визначається пороговими значеннями для кожної метрики та режимом:
Screenshot pending — add assets/img/statusbar.png (see SCREENSHOTS.md).| Режим | COMPLIANT, коли… |
|---|---|
strict (default) | кожна окремо контрольована метрика досягає власного порога — без компромісів. |
whm | єдина зважена зведена оцінка досягає threshold.weighted. |
both | виконано і зважену перевірку, І сувору перевірку кожної метрики. |
either | виконано або зважену перевірку, АБО сувору перевірку кожної метрики (найм’якший режим). |
Поріг 0 вимикає цей запобіжник, а метрика, якої звіт не містить, ніколи не оцінюється. Що означає поріг, якого ви не задали, визначає профіль нижче. Виконайте Fucini Coverage: Check Coverage Thresholds для оцінки на вимогу.
У Visual Studio. Tools → Coverage Studio → Check Coverage Thresholds оцінює запуск за тими самими ключами threshold.* і повідомляє про це в рядку стану та панелі Output; з compliance.diagnostics, problems.enabled, problems.perLine або deadCode.enabled знахідки стоять в Error List поруч із знахідками самого компілятора — один запис на файл нижче порога, один на непокритий діапазон, один на функцію, що ніколи не виконувалася — і кожен відкриває свій файл на цьому рядку.
Screenshot pending — add assets/img/vs-error-list.png (see SCREENSHOTS.md).Профілі порогів
threshold.profile визначає, що означає поріг, якого ви не задали. standard, типове значення починаючи з 0.2026.82, — це те, чого можна вимагати від звичайного проєкту, не пов’язаного з функційною безпекою. safety — це кожен запобіжник на рівні 100: те, чого вимагає обґрунтування безпеки, і саме те, що постачалося до 0.2026.81 включно.
| Метрика | standard | safety |
|---|---|---|
| Рядки | 80 | 100 |
| Функції | 80 | 100 |
| Регіони | 75 | 100 |
| Гілки | 70 | 100 |
| Композитний показник | 75 | 100 |
| MC/DC, інстанціювання, виклики функцій, об’єктний код | без запобіжника | 100 |
| Умови | без запобіжника | 100 |
| Мутаційний показник | без запобіжника | без запобіжника |
Поріг, який ви задали самі, має перевагу над будь-яким профілем. У прикладі запобіжник для гілок встановлено на 90, а для всього іншого — на 100; щоб тримати на рівні 100 лише деякі метрики, залишайтеся на standard і задайте їх самостійно. Одне застереження випливає з того, як працюють параметри: значення, що дорівнює типовому, неможливо відрізнити від відсутності значення, тому під safety поріг, записаний точно як його стандартна величина — скажімо, 80 для рядків, — усе одно рахується як 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).Якщо ви покладалися на старі типові значення, після оновлення до 0.2026.82 вас оцінюють поблажливіше, доки ви не виберете safety. Інсталяція, яка працювала раніше, отримує про це одноразове повідомлення з кнопкою Keep 100% (safety), яка записує профіль у ваші параметри користувача; для спільного проєкту додайте його також до параметрів робочої області, щоб усіх оцінювали однаково. Configure Coverage Compliance & Thresholds... містить профіль над сіткою порогів, а попередній перегляд наживо оцінює за запобіжниками, які справді діють. У кожній картці та кожному звіті метрика, запобіжник якої вимкнено, показує своє значення з нейтральним тире замість позначки чи хрестика.
Screenshot pending — add assets/img/statusbar-metrics.png (see SCREENSHOTS.md).11a. Покриття об'єктного коду
Кожна інша метрика тут вимірюється за вихідним кодом: інструмент інструментує ваш код, інструментована збірка виконується, і лічильники кажуть, які оператори, гілки чи умови було задіяно. Покриття об'єктного коду вимірює інше — скільки зібраного двійкового файлу насправді виконалося, у байтах інструкцій, спостерігаючи за потоком інструкцій, а не інструментуючи вихідний код. Це важливо, бо компілятор породжує код, якого немає в жодному вашому рядку: перевірки меж масивів, таблиці переходів switch, вивантаження регістрів, перевірки стека, виклики допоміжних підпрограм рантайму для ділення чи плаваючої коми на ядрах без відповідної інструкції. Це також єдина тут метрика, що відповідає на питання чи покриває це асемблер? — рукописний асемблер ніколи не інструментується, і засіб на рівні вихідного коду до нього не дістанеться. DO-178C прямо пояснює чому: на рівні A, коли компілятор або компонувач породжує код, який не простежується безпосередньо до операторів вихідного коду, ціль 6.4.4.2b вимагає додаткової верифікації саме цього породженого коду.
Воно поглинає покриття операторів — кожна виконана інструкція походить з якогось оператора, тож 100% покриття об'єктного коду означає 100% покриття операторів. Зворотне не діє, і саме ця асиметрія і є сенсом вимірювання. Звідси випливає двоє. Воно не має жодної ваги у зведеній оцінці, бо усереднення двох мір тих самих виконань зараховує одні й ті самі докази двічі; замість цього воно контролюється порогом fuciniCoverage.threshold.objectCode — вимога, а не вага, як цього і просить стандарт. І саме розрив є результатом: прогін зі 100% покриттям рядків і меншим за 100% покриттям об'єктного коду точно вказав на породжений компілятором код, якого немає у вашому джерелі, тож картка відповідності каже 312 байтів не виконано, при 100% покритті рядків, а не ховає це за «94%». Протилежне — коли ввесь двійковий файл нібито виконався, а його джерело ні — це суперечність, а не низька оцінка: майже завжди застарілий файл трасування з одного боку злиття або назви модулів, які так і не збіглися зі шляхами файлів. Це повідомляється як знахідка.
Покриттю об'єктного коду потрібно, щоб двійковий файл виконувався там, де його інструкції можна спостерігати. Шляхів три, і вони разюче різняться за вартістю. Об'єктне покриття дає лише третій; перші два наведено тому, що вони розв'язують суміжну задачу, яку часто й варто розв'язувати насправді.
- Інструментована збірка, що виконується на цільовому пристрої. Крос-компілятори GCC приймають
-fprofile-arcs -ftest-coverage, тож інструментація, яка працює на робочій станції, працює й на цілі — з тією різницею, що на «голому залізі» немає файлової системи, куди записати лічильники.gcda, і часто немаєexit(), під час якого їх записати. Лічильники все одно лежать в оперативній пам'яті, тож вихід — вивантажити цю пам'ять і відтворити файли поза ціллю;embedded-gcovвід NASA JPL (Apache-2.0) робить саме це, без файлової системи, операційної системи чи стандартної бібліотеки C. Це дає покриття операторів, гілок і функцій збірки, зробленої вашим крос-компілятором, для вашої системи команд, на вашому обладнанні — але не покриття об'єктного коду, а вимірюваний двійковий файл інструментований, тобто більший і повільніший за той, що ви постачаєте. Результат завантажуйте як LCOV, gcovr JSON, gcov JSON або, на тулчейні старішому за GCC 9, як текстовий список.gcov. - Симулятор системи команд. Запустіть справжній цільовий двійковий файл у симуляторі й виведіть покриття з виконаних адрес: без обладнання, без інструментації, без зонда — і, оскільки спостерігаються інструкції, він може дати справжнє покриття об'єктного коду. Обмеження — точність: симулятор добре моделює ядро й гірше периферію, тож до результатів на рівні всієї системи ставтеся з осторогою, якщо він не моделює вашу мікросхему докладно.
- Трасування на кристалі й налагоджувач. Шлях сертифікаційного рівня і єдиний справді неінвазивний: блок трасування ядра передає потік інструкцій налагоджувачу, який перетворює його на покриття. Нічого не інструментується, розмір коду не змінюється, час виконання не зачеплено — саме це й робить результат доказом про той двійковий файл, який ви справді постачаєте. Перевірте кристал, перш ніж закладати це в бюджет: у багатьох сімействах мікроконтролерів повне трасування доступне лише на емуляційному чи налагоджувальному варіанті з великим буфером трасування та швидкісним портом, тоді як серійні кристали мають скорочений блок трасування, а запасний варіант виробника для них — програмне трасування, яке інструментує код і споживає процесорний час, тобто знищує саме ту властивість, заради якої цей шлях і обирали.
Багато вбудованих проєктів вимірюють покриття, компілюючи ті самі джерела для робочої машини і запускаючи модульні тести там. Це швидко, не потребує обладнання, і для більшості команд це правильна типова поведінка — але варто чітко розуміти, що саме описують ці докази: інший компілятор, інший оптимізатор, інша система команд і інший двійковий файл, ніж той, що постачається. Для більшості програмного забезпечення це прийнятний і добре зрозумілий компроміс. Для робіт, що оцінюються за IEC 61508, ISO 26262 чи DO-178C, це стандартне заперечення «хост проти цілі», і наведені вище шляхи є стандартними відповідями на нього — перший закриває питання для покриття вихідного коду, третій — для об'єктного коду.
Наразі експорт, який читається для об'єктного коду, — це COVerage.EXPORT.ListModule Lauterbach TRACE32 з metric="object"; завантажуйте його як будь-який інший файл трасування. Ця метрика оцінюється й контролюється лише за платною ліцензією та під час оцінного періоду. Встановлення Community не оцінює її — але повідомляється, коли файл трасування її містить, бо вердикт відповідності, що мовчки опускає найсильніший доказ у файлі, був би гіршим за той, що каже, що саме він опустив.
12. Виключення рядків без коду
Коли excludeComments увімкнено (типово), оператори, що повністю припадають на рядки лише з коментарями або порожні рядки, виключаються із загальних підсумків — це також нейтралізує відому особливість llvm-cov/gcov, коли випадкова кількість влучень потрапляє на коментар. Стандартні маркери теж враховуються:
x = risky(); // LCOV_EXCL_LINE
// LCOV_EXCL_START
debug_only_block();
// LCOV_EXCL_STOP
Директиви препроцесора так само не вважаються кодом у C, C++, Objective-C, CUDA і C#: рядок, що починається з # — #define, #include, #if, — і рядки, на які його продовжує кінцевий зворотний слеш. gcov зараховує кожне використання макросу рядку, де його визначено, тож заголовок, єдиним рядком якого у звіті був #define CHANNEL_COUNT (33U), читався як покритий на 100%, бо цикл у файлі .c доходив до нього, а той, чию константу ніщо не використовувало, — як покритий на 0%. Такому заголовку тепер нічого вимірювати, і його немає в списку.
Встановіть excluded.includeInTotals у true, щоб все ж рахувати виключені рядки.
Виключення файлу чи теки, з дерева
Клацніть правою кнопкою файл або теку в поданні Coverage і виберіть Exclude from Coverage — він є і серед дій зі шляхом рядка — або виконайте Exclude This File from Coverage для відкритого файлу: шлях файлу відносно робочого простору, або /** теки, потрапляє в fuciniCoverage.ignore у налаштуваннях теки, один раз, і перезавантаження прибирає його з кожного підсумку й кожної сторінки; шаблон лежить там, щоб його можна було прибрати знову. У Visual Studio меню рядка і Tools → Coverage Studio мають ті самі дві команди, що пишуть те саме налаштування в той самий файл.
Screenshot pending — add assets/img/exclude-from-tree.gif (see SCREENSHOTS.md).
fees.ts — дерево без нього, шаблон у .vscode/settings.json.Атрибути й простори імен, для .NET
Два налаштування читають із джерела те, чого звіт сказати не може. ignore.attributes — типово ExcludeFromCodeCoverage — виключає клас, метод чи властивість під атрибутом, який воно називає, як це зробив би LCOV_EXCL_START/STOP, яким би інструментом не було записано звіт: Coverlet шанує атрибут, OpenCover, dotCover і сконвертований lcov — ні, а тепер усі вони погоджуються. Імена із суфіксом Attribute чи без нього, з простором імен чи без; додайте GeneratedCode, Obsolete або власні. ignore.namespaces залишає поза списком кожен файл, чиє оголошення простору імен збігається з префіксом, * як підстановка — Acme.Generated, Acme.*.Migrations, *Tests, — а панель Output називає файли, які воно забрало. Обидва читаються в тому самому проході, що читає маркери в коментарях, в обох редакціях.
{
"fuciniCoverage.ignore.attributes": ["ExcludeFromCodeCoverage", "GeneratedCode"],
"fuciniCoverage.ignore.namespaces": ["Acme.Generated", "*.Migrations"]
}
Виключення з редактора
Виділіть рядки й візьміть Exclude Selection from Coverage з лампочки, контекстного меню редактора або Command Palette — у Visual Studio з лампочки (Ctrl+.), меню правої кнопки у вікні коду, Tools → Coverage Studio або Ctrl+Shift+U, X, — і виключення записується там, де код: [ExcludeFromCodeCoverage] над класом, методом чи властивістю C#, VB або F#, коротким ім’ям, якщо файл уже імпортує System.Diagnostics.CodeAnalysis, і повністю кваліфікований, якщо ні, щоб не довелося додавати жоден using; LCOV_EXCL_LINE наприкінці одного рядка коду; LCOV_EXCL_START і LCOV_EXCL_STOP навколо кількох, із відступом першого рядка — власним знаком коментаря мови, //, #, ', -- або ;. Один крок скасування. Лампочка пропонує це й на рядку, який записи в Problems позначають як непокритий. Уже позначений рядок або член, що вже має атрибут, лишаються як є.
Screenshot pending — add assets/img/exclude-selection.gif (see SCREENSHOTS.md).
LCOV_EXCL навколо гілки, потім [ExcludeFromCodeCoverage] над методом.Лише гілки, і маркери gcovr
Захисний else, default:, до якого не доходить жодне значення, вітка, яку компілятор додає для винятку: рядок виконується й має рахуватися, і лише його гілку неможливо взяти. LCOV_EXCL_BR_LINE і LCOV_EXCL_BR_START … LCOV_EXCL_BR_STOP вилучають із підрахунку гілки у своїх рядках, а самі рядки в ньому лишають. LCOV_EXCL_EXCEPTION_BR_LINE і його область вилучають ще менше — лише вітки, до яких веде виняток, якщо звіт каже, які саме, як це робить JSON gcov. Кожен маркер читається також із префіксами gcovr: GCOVR_EXCL_LINE, GCOVR_EXCL_START, GCOVR_EXCL_BR_LINE, GCOV_EXCL_STOP та решта означають те саме, що й маркери LCOV_EXCL_, тож вихідний код, написаний для gcovr, читається тут так само, хоч би який інструмент створив звіт. Не читається: GCOVR_EXCL_FUNCTION — ніщо в тому рядку не каже, де функція закінчується.
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).Сказати чому: обґрунтовані виключення
Вилучення коду з підрахунку — це твердження: «це неможливо протестувати», «це допоміжний засіб розробника», — а за DO-178C, ISO 26262 чи IEC 61508 твердження, яке змінює число, на яке спирається сертифікат, має бути записане й придатне для перевірки. Тому виключення може сказати чому — там, де його записано: текст після LCOV_EXCL_LINE чи LCOV_EXCL_START або Justification в [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) { /* … */ }
Причини читаються під час кожного завантаження, і журнал їх рахує. Export Coverage Report… записує список — exclusions and their justifications, у Markdown або CSV: файл, рядки, спосіб запису й обґрунтування або none given. Файл, у якому не лишилося нічого вимірюваного, усе одно є в цьому списку. З увімкненим exclusions.requireReason виключення без причини — це знахідка: попередження на панелі Problems на його рядку й непроходження Check Coverage Thresholds. Exclude Selection from Coverage тоді спершу питає причину й записує її разом із маркером або як Justification атрибута; якщо запит закрито чи лишено порожнім, нічого не виключається.
Screenshot pending — add assets/img/justified-exclusions.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/vs-justified-exclusions.png (see SCREENSHOTS.md).12a. Чи це покриття все ще описує цей файл?
Покриття, прочитане з файлу трасування, описує код таким, яким він був під час запуску тестів, і більшість форматів не каже, яка це була версія. Тому кожен файл на панелі «Покриття» перебуває в одному з трьох станів:
- ✓ Перевірено — файл трасування зберігає вміст кожного виміряного рядка, і він досі збігається з файлом.
- Без позначки — не спростовано. Ніщо не суперечить покриттю і ніщо його не підтверджує. Це звичайний стан.
- ⚠ Спростовано — сам файл спростовує своє покриття. Рядок притемнено, а підказка каже, що саме знайдено.
Лише два формати можуть заслужити позначку, бо лише два зберігають бодай щось про виміряний код: lcov, записаний із --checksum (у geninfo типово вимкнено; задокументована мета — саме не дати поєднати покриття двох версій файлу) та GNATcoverage XML, який вбудовує текст кожного виміряного рядка. Увімкнути цю опцію lcov варто.
Попередженню не потрібне ні те, ні інше, і воно працює з кожним форматом: покриття, записане за кінцем файлу, названа функція, якої вже немає там, куди її ставить звіт, або виконані рядки, порожні у файлі. Позначок часу самих по собі ніколи не досить — git checkout змінює кожну, не змінюючи жодного байта — тож змінена позначка часу є щонайбільше приводом поглянути ще раз. Перевірка виконується при завантаженні покриття і знову щоразу, коли файл зберігається або змінюється на диску, тож позначка йде за файлом: правка, що суперечить прогону, її ставить, checkout, що повертає виміряну версію, її знімає. Підказка каже точно, що це довело. Установіть staleWarning.enabled у false, щоб вимкнути все це.
12b. Невиміряне проти непокритого
Файл, якого прогін ніколи не згадує, — невиміряний: його не завантажив жоден тест, тож жоден інструмент не записав для нього ані рядка. Це не те саме, що непокритий — виміряний, з нулем влучань, — і розширення ніколи не оцінювало відсутній файл як 0%. Чого воно не робило до 0.2026.69 — так це взагалі не показувало відсутні: модуль без жодних тестів ніколи не з'являвся ні в дереві, ні в підсумках, ні в перевірці порогів, і читач бачив «92%» для проєкту, половину файлів якого ніколи не було виконано.
Тепер, із завантаженим прогоном, пофайловий елемент рядка стану каже не виміряно для вихідного файлу того ж виду, що й прогін, якого в прогоні немає — «того ж виду, що й прогін» означає, що він має одне з розширень файлів, які прогін вимірював, тож заголовки й джерела проєкту на C є кандидатами, а його скрипти на Python — ні. Усе понад це вмикається за бажанням через fuciniCoverage.unmeasured.mode:
off(типово) — більше нічого не змінюється.list— подання Coverage отримує внизу групу Невиміряні, яка називає кожен такий файл, і кожен рядок відкриває його; результат завантаження рахує їх; значки позначають їх?у Провіднику; аfuciniCoverage.threshold.unmeasuredFilesможе провалити Check Coverage Thresholds, коли їх більше за задане вами число. Жоден відсоток не зрушується.count— усе, що робитьlist, і до того ж кожен невиміряний файл зараховується проти прогону як непокритий файл зі стількома рядками, скільки в ньому рядків коду, тож рядок стану, пороги, значки, історія, кожен експорт і подання Test Coverage показують нижче число. Файл зображується як невиміряний скрізь, де з'являється, його смужки в полі кажуть «не виміряно», а не «жодного разу не виконався», а перевірка невідповідності його не чіпає — немає вимірювання, якому міг би суперечити його вміст.
{
"fuciniCoverage.unmeasured.mode": "list",
"fuciniCoverage.threshold.unmeasuredFiles": 0
}
Заголовні файли — відомий хибний спрацьовувач у C: вони мають родину розширень прогону, і жоден файл трасування ніколи не назве такий, бо сам по собі він компілюється в ніщо. Тому fuciniCoverage.unmeasured.exclude типово пропускає **/*.h, **/*.hpp, **/*.hh, **/*.inl і **/*.d.ts, у тому самому глоб-синтаксисі, що й fuciniCoverage.ignore; додайте порт на платформу, яка тут не збирається, або згенеровані заглушки — і вони випадають зі списку, з підрахунку та зі стану рядка стану. Файл, названий в ignore, також ніколи не називається невиміряним — його ж і хотіли пропустити. threshold.unmeasuredFiles типово дорівнює -1, що не перевіряє; 0 провалює перевірку, щойно будь-який файл того ж виду, що й прогін, не було завантажено жодним тестом, і діє він лише доки unmeasured.mode має значення list або count.
13. HTML-звіти
- Generate Full HTML Report — багатосторінковий звіт власного рендерингу для кожної директорії. Вивід іде в
htmlReport.outputDirабо в глобальне сховище розширення, якщо не задано. - Open Annotated Source — анотований перегляд одного файлу. Вкажіть у
externalHtmlReport.dirзаздалегідь зібрану директоріюllvm-cov show --format=html, щоб використовувати ці сторінки замість вбудованого рендерера. - Export Fucini JSON — повна нормалізована модель для власних інструментів.
- Export Coverage Report... — запуск як CSV (за файлами або за функціями), зведення у Markdown, файл трасування LCOV, XML Cobertura, SARIF або автономний значок SVG для вашого README. Доступно також із кнопки поруч із Generate Full HTML Report у поданні Covered Files. Усе, крім CSV, втрачає дані — MC/DC, регіонам та інстанціюванням немає місця в LCOV, Cobertura чи SARIF — тож Fucini JSON і CSV лишаються форматами, що несуть кожну метрику.
- Copy Uncovered Lines — зведення прогалин у форматі Markdown, готове для вставки в PR.
У Visual Studio. Група Reports у Tools → Coverage Studio: Show Annotated Source відкриває активний документ як сторінку в області документів — кожен рядок у своєму кольорі, знахідки поруч — прокручувану разом із редактором в обидва боки; Open HTML Report пише односторінковий звіт до htmlReport.outputDir (або %LOCALAPPDATA%\Fucini\CoverageStudio\html-report) і відкриває браузер; Generate Full HTML Report пише туди індекс на теку і сторінку на файл; Export Coverage Report… пропонує ті самі вісім форматів і питає, куди зберегти; Generate Coverage Badge пише значок туди, куди каже badge.outputPath, після кожного завантаження з badge.autoUpdate. Анотованій сторінці потрібен WebView2, як і вікну Coverage; звітам на диску — ні.
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).Анотоване джерело проти звичайного джерела
Open Annotated Source замінює активну вкладку кольоровою вебпанеллю покриття для цього файлу, у тій самій колонці; Open Annotated Source to the Side робить те саме, але у розділеному вигляді, тож джерело та анотований перегляд розташовуються поруч. Щоб натомість перемикатися туди-сюди на місці — зручно на маленькому екрані, де розділення робить кожну панель занадто вузькою — використовуйте Toggle Annotated Source: вона перемикає активну вкладку між цими двома режимами, пам'ятаючи, який із них ви зараз переглядаєте. Зсередини анотованого перегляду Show Source одразу повертає до звичайного редактора для цього файлу.
Який саме HTML ви побачите, залежить від externalHtmlReport.dir: якщо його задано і там уже існує сторінка, що відповідає активному файлу (llvm-cov розкладає посторінкові файли як <repo-name>/<relative-path>.html, тож папку з назвою репозиторію налаштовувати не потрібно), показується саме ця згенерована набором інструментів сторінка замість вбудованого рендерера — її локальні посилання/стилі переписуються для роботи всередині вебпанелі, і вона містить деталі, яких вбудований перегляд не відтворює (розгортання MC/DC, підсвічування регіонів, згортання за директоріями). Немає відповідної сторінки для цього файлу або налаштування порожнє? Тоді використовується вбудований рендерер. Розширення лише читає цю директорію — воно ніколи в неї не записує.
Значок покриття для README
Generate Coverage Badge записує SVG у стилі shields для активного прогону в робочу область — badge.outputPath, типово coverage-badge.svg, відносно теки робочої області або абсолютно, з тими самими змінними, що й у кожному іншому налаштуванні шляху, — і пропонує відкрити його. Це звичайний файл у вашому репозиторії, тож README вбудовує його без жодного сервісу позаду, без звернення до shields.io, і це працює також у репозиторії без доступу до мережі:

badge.metric вибирає, що показує значок: lines (з підписом coverage), branches, mcdc або weighted — той самий композитний показник, який показує рядок стану, з підписом score. Прогін без даних для вибраної метрики отримує сірий n/a замість червоних 0%. Колір іде за вашими власними рівнями colorScale.*: lowColor нижче lowThreshold, midColor до highThreshold, highColor від нього й вище. З увімкненим badge.autoUpdate значок переписується після кожного успішного завантаження, мовчки, а канал виводу записує кожен запис як [FUCINI_BADGE] — типово вимкнено, бо це пише в робочу область при кожному завантаженні. Закомітьте SVG разом із кодом — і картинка на сторінці репозиторію йтиме за числом у редакторі.
{
"fuciniCoverage.badge.outputPath": "docs/coverage-badge.svg",
"fuciniCoverage.badge.metric": "weighted",
"fuciniCoverage.badge.autoUpdate": true
}
14. Історія та тенденції
Увімкніть history.enabled, щоб зберігати запуски локально (утримуючи history.retention з них). Далі ви отримаєте стрілку тенденції (▲/▼) у рядку стану, графік тренду в поданні Coverage і дві команди порівняння: Compare with Last Run і Compare Two History Runs, кожна з яких формує diff регресій/покращень для кожного файлу.
У Visual Studio. Кожне завантаження порівнюється з попереднім: трикутник на полі біля кожного рядка, що почав або перестав виконуватися (sinceLastRun.enabled), тренд поруч з оцінкою в рядку стану і Compare with Last Run для файлів, чиї числа змінилися. З history.enabled запуски зберігаються під %LOCALAPPDATA%\Fucini\CoverageStudio\history, у кількості history.retention, тож порівняння переживає перезапуск, графіку тренду є що малювати, а Compare Two History Runs… вибирає будь-які два з них.
Screenshot pending — add assets/img/history-compare.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/since-last-run.png (see SCREENSHOTS.md).Графік тренду
Під панеллю інструментів подання Coverage, за двох збережених запусків і більше, покриття рядків з історії у вигляді лінії, від найстарішого до найновішого, останні тридцять: крапка на запуск, що при наведенні каже його дату й цифру, і остання цифра поруч зі стрілкою напрямку від першого. Вертикальна шкала — власний діапазон запусків, тож команда на 92–94% бачить рух, а не пласку лінію під 100. Обидві редакції малюють його з тієї самої історії.
Screenshot pending — add assets/img/trend-chart.png (see SCREENSHOTS.md).
Сеанси покриття
Один тестовий запуск рідко покриває все, чого торкнулася зміна: модульні тести прогнали тут, інтеграційний набір там, прохід інтерфейсом з увімкненим покриттям десь іще. Start Coverage Session перетворює наступні завантаження на одну суму — кожен запуск додається до попереднього рядок за рядком як об’єднання, рядок, виконаний будь-яким із них, покритий, а лічильники додаються, — тож поле редактора, дерево й оцінка показують, куди вони дійшли всі разом. Запуск на екрані, якщо він є, — перший у сеансі. Смуга над деревом каже, скільки запусків і відколи, і завершує сеанс; End Coverage Session робить те саме, і наступне завантаження знову стоїть саме по собі. У Visual Studio один пункт у Tools → Coverage Studio починає сеанс, а позначений — завершує його.
Screenshot pending — add assets/img/coverage-session.gif (see SCREENSHOTS.md).
Базова лінія CI: де я відносно main?
Compare with Last Run відповідає, що зробила ваша остання зміна; перед pull request питання в тому, де ви відносно main, і відповідь — на сервері збірки. baseline.report називає звіт, який публікує збірка гілки main, і кожне завантаження звіряється з ним: картка в рядку стану несе однорядкову дельту — vs CI baseline: 84.20% → 85.10% (+0.90%), 3 file(s) moved, — а Compare with CI Baseline перелічує файли, що змінилися, файл за файлом, тими самими словами, що й Compare with Last Run. У Visual Studio команда є в Tools → Coverage Studio і запитує або читає звіт, коли ви попросите. Три способи назвати його, у .vscode/settings.json:
- URL, який віддає CI. GitLab тримає останні артефакти завдання гілки за стабільною адресою; токен лишається поза файлом налаштувань завдяки
${env:…}уremote.headers. Jenkins:https://jenkins.example.com/job/app/job/main/lastSuccessfulBuild/artifact/coverage/lcov.info. TeamCity:https://tc.example.com/repository/download/App_Main/.lastSuccessful/coverage/lcov.infoзAuthorization: Bearer ${env:TC_TOKEN}. URL запитується й кешується точно так само, як URL ізcoverageFile.paths(ETag,remote.refreshMinutes). - Файл, скопійований конвеєром на спільний ресурс — абсолютний шлях на кшталт
\\build\drops\app\main\coverage.cobertura.xml. - Завантажений артефакт, що зберігається в теці, скажімо
ci/main.lcov.info(внесіть теку до.gitignore), — шлях відносно теки.
{
"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}"]
}
Підійде будь-який формат, який знає читач. Шлях, записаний CI відносно свого checkout — src/Billing/Invoice.cs, як його пише Coverlet на раннері, — перед порівнянням розміщується під цією текою, щоб зустрітися з файлом, який розв’язав локальний запуск; абсолютний шлях з іншої машини не збігається ні з чим, тож нехай конвеєр пише відносні шляхи. Базова лінія, яку не можна запитати чи прочитати, — це рядок у панелі Output, але ніколи не невдале завантаження.
Screenshot pending — add assets/img/ci-baseline.gif (see SCREENSHOTS.md).main.
Артефакт — це zip, і його теж читають. GitHub і GitLab віддають артефакт як архів, хоч би що в нього поклали. Назвіть звіт у ньому після #: файл в архіві знаходиться за своїм шляхом або за його закінченням; без # це єдиний файл архіву або єдиний його файл, схожий на звіт, а де їх кілька, панель Output їх називає. Те саме стосується zip, який ви завантажили самі (ci/artifact.zip#lcov.info), і, у VS Code, URL у coverageFile.paths. Токен надсилається серверу, для якого його задано, і не далі: перенаправлення до сховища, де лежить архів, виконується без нього.
{
"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. Для агентів ШІ: покриття на екрані
Агент, який пише тести, може запустити їх і прочитати відсоток. Чого він сам не може — це запитати про те, що знає редактор: які рядки цієї функції жодного разу не виконалися, який бік якої гілки, які тести виконують рядок, чи покрито diff, який він щойно написав. Шість інструментів відповідають саме на це, словами, за якими агент може діяти, із завантаженого запуску — ті самі виключення, те саме переспрямування шляхів, ті самі числа, що й на екрані. Тож агент, якому сказано покрити прогалини функції, і рецензент, який дивиться на поле редактора, говорять про ті самі рядки.
| Інструмент | На що відповідає |
|---|---|
coverage_summary | Підсумки запуску за кожною метрикою і файли, найдальші від повного покриття. Перше, про що варто запитати. |
coverage_gaps | Що жодного разу не виконалося у файлі, функції чи діапазоні рядків: непокриті рядки, не взяті вітки гілок, умови MC/DC без своєї пари, мутанти, що вижили. |
tests_for_line | Які тести виконали рядок, якщо звіт це каже — потестовий запуск. |
patch_coverage | Покриття diff — робочого дерева відносно посилання або переданого патча — і його рядки, які жодного разу не виконалися. |
coverage_delta | Що змінилося від попереднього запуску: підсумки й файли, які додали або втратили. |
test_run_command | Команда, яка запускає тести цього робочого простору з увімкненим покриттям. Агент виконує її; редактор перезавантажує звіт сам. |
Власний агент VS Code має їх як інструменти без жодного налаштування. Усі інші агенти — будь-який клієнт, що підтримує MCP, Model Context Protocol, — отримують до них доступ через сервер, який редактор запускає, коли ввімкнено mcp.enabled, у VS Code так само, як у Visual Studio. Copy MCP Server Configuration кладе запис для клієнта в буфер обміну — такий, яким VS Code і Visual Studio читають його в mcp.json; клієнт, що називає зовнішній ключ mcpServers, бере той самий запис під цим іменем.
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 …" }
}
}
}
- Він вимкнений, доки ви його не ввімкнете, і слухає лише на
127.0.0.1: ніщо з-поза цього комп’ютера до нього не дістається. - Виклик має нести ваш токен, створений один раз і збережений для вас; без нього відповідь — 401. Скопійована конфігурація містить токен: не кладіть її в репозиторій.
- Виклик, надісланий вебсторінкою, — про це каже його
Origin— відхиляється, хоч би що він ніс. - Він читає завантажений запуск і нічого не записує. Тестовий запуск називається, а не запускається: агент виконує команду у власному терміналі.
Порт — mcp.port, 39217, якщо не задано інший. Якщо він зайнятий — друге вікно, інша редакція поруч із цією, — використовується наступний вільний, а скопійована конфігурація називає той, що працює. Панель Output каже, де сервер слухає ([FUCINI_MCP]) і чому він не зміг ([FUCINI_MCP_001]). Те, чого план не включає, — назви тестів, деталі MC/DC — інструменти рахують, не розкриваючи, як це робить підказка.
15. Довідник команд
У Visual Studio. Усі команди — в Tools → Coverage Studio, з тими самими назвами, що в таблиці, без префікса Fucini Coverage:; панель інструментів вікна Coverage і контекстне меню рядка мають ті, що їм належать, а контекстне меню вікна коду — три, що діють на редактор: Run This Test with Coverage, Show Tests That Ran This Line і Exclude Selection from Coverage. Команди з клавішами — двоклавішні акорди після Ctrl+Shift+U: R перезавантажує, N і P переходять до наступного і попереднього непокритого рядка, B — до наступного частково протестованого рішення, T перелічує тести, що виконали рядок, X виключає виділення; це не Alt+N з VS Code, бо у Visual Studio Alt з літерою відкриває меню. Змініть їх у Tools → Options → Keyboard, де вони перелічені як Coverage Studio: …. Немає в цій редакції: панель Test Coverage — це API VS Code, натомість запуск є у вікні Coverage, а Solution Explorer не може показувати позначки. Лише в цій редакції: Run Native Project with Coverage, для стартового проєкту C++.
У Visual Studio: де що є. Вікно Coverage відкривається через View → Other Windows → Coverage, а також першим пунктом у Tools → Coverage Studio, де зібрано всі команди цієї редакції, групами: завантаження й перезавантаження, стеження за файлом, дві команди копіювання та картки; Run Tests with Coverage, Run Native Project with Coverage і Collect Coverage in Test Explorer…; Next і Previous Uncovered та частково перевірені рішення; розфарбовування, лічильники виконань і режими смуги; джерело покриття файлу, тести, що виконали рядок, один тест із покриттям, два способи виключення; Compare with Last Run, Compare Two History Runs…, Compare with CI Baseline, сеанс покриття і Check Coverage Thresholds; група Reports — Show Annotated Source, Open HTML Report, Generate Full HTML Report, Export Coverage Report… і Generate Coverage Badge; далі Getting Started, пороги відповідності та Licence…. Власна панель інструментів вікна містить п'ять найуживаніших: Load Coverage, Reload, Toggle Coverage Painting, Copy Coverage Summary і пороги відповідності; під ними перспектива, фільтр і сортування та поле пошуку; під ними тренд. Наведіть вказівник на рядок дерева й натисніть його ⋯, щоб відкрити меню рядка — відкрити файл, відкрити його теку, скопіювати шлях, абсолютний чи відносний, з будь-яким видом скісних рисок, виключити його з покриття. Праворуч у рядку стану — оцінка запуску та оцінка відкритого файлу, з трендом від останнього запуску; Show Coverage Card і Show Coverage Card for This File відкривають картки з числами за ними — ті самі, що VS Code показує, коли вказівник спиняється на його елементі рядка стану.







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).| Команда | Що робить |
|---|---|
| Load Coverage | Знайти й завантажити покриття для робочого простору. Типово Alt+Shift+R (Ctrl+Alt+R на macOS). |
| Pick Coverage File | Вибрати файли трасування — один, кілька або ще один щоразу; вибрані файли додаються, зливаються й записуються в coverageFile.paths, тож надалі завантажуються самі. |
| Show Loaded Coverage Files | Перелічити файли трасування активного прогону. Подання «Покриття» теж показує їх, кожен із кнопкою вивантаження та кнопкою вибору поруч. |
| Toggle Tracefile Watch | Стежити за змінами файлів трасування та перезавантажувати автоматично. |
| Run Tests with Coverage | Розпізнати тестовий рушій, запустити його з покриттям у завданні термінала, завантажити записане й запропонувати додати шлях до налаштувань. |
| Run This Test with Coverage | Тест під курсором — метод, клас чи блок describe, або файл — запускається рецептом, звуженим до нього, потім завантажується як будь-який запуск. Також у контекстному меню редактора. |
| Show Tests That Ran This Line | Там, де звіт каже, які тести що виконали, перелічити тести, що виконали рядок під курсором, найактивніші першими, і відкрити вибраний там, де його написано. |
| Run Tests Affected by My Changes… | Перелічити тести, які виконали рядок, що його робоче дерево змінює відносно testImpact.baseRef, відкрити вибраний або запустити лише їх там, де звіти походять із потестового запуску. |
| Show Minimal Test Set… | Найменше тестів, які все ще виконують кожен рядок, який виконує набір, потім тести, що не додають жодного власного рядка. |
| Run App with Coverage… | Запустити застосунок .NET із теки під dotnet-coverage і, коли він закриється, завантажити те, що ви пройшли. |
| Run Mutation Tests Here | Мутувати функцію, у якій стоїть курсор, — або виділення, або файл — за допомогою Stryker.NET, StrykerJS чи PIT і завантажити звіт поруч із покриттям на екрані. |
| Exclude This File from Coverage / Exclude from Coverage | Додати відкритий файл — або, на рядку подання Coverage, файл чи /** теки — до fuciniCoverage.ignore у налаштуваннях теки, один раз. |
| Exclude Selection from Coverage | Записати виключення там, де код: [ExcludeFromCodeCoverage] над членом .NET, LCOV_EXCL_LINE в одному рядку, LCOV_EXCL_START/STOP навколо кількох, знаком коментаря самого файлу. Також лампочка і контекстне меню редактора. |
| Start Coverage Session / End Coverage Session | Поки триває сеанс, кожне завантаження додається до попереднього як об’єднання; смуга над деревом рахує запуски і завершує його. |
| Next / Previous Uncovered | Переходити між непокритими регіонами. Типово Alt+N / Alt+P (Ctrl+Alt+N / Ctrl+Alt+P на macOS). |
| Choose Editor Gutter Mode... | Вимкнено, смужки лише на непокритих рядках, червоно-бурштиново-зелені смужки або теплова карта влучань у полі редактора. |
| Cycle Editor Gutter Mode | Один крок далі по колу off, uncovered, coverage і heatmap — Alt+G або кнопка режиму в рядку стану. |
| Choose Coverage Source for This File... | Коли відкритий файл вимірює більше ніж один завантажений звіт, виберіть, з якого з них беруться його числа — для файлу, його теки або шаблону; записує правило coverageFile.sources. |
| Clear Coverage Source for This File... | Прибрати правила coverageFile.sources, які стосуються відкритого файлу. |
| Toggle Inline Hit Counts | Показати чи сховати лічильники виконань ×N після кожного рядка — перемикає hitCounts.inline. |
| Show in Test Coverage View | Опублікувати активний прогін у власну панель Test Coverage VS Code (навіть із вимкненим testCoverage.publish) і відкрити її. |
| Suggest Path Remap Rule | Вивести правило pathRemap, яке зіставило б незіставлені файли активного прогону з робочою областю, і запропонувати додати його. |
| What Community Includes | Кожен ліміт і кожна невключена функція безкоштовного рівня в одному списку, з тим, скільки кожного ліміту використано. |
| Open HTML Report | Відкрити згенерований статичний звіт. |
| Generate Full HTML Report | Побудувати багатосторінковий звіт. |
| Open Annotated Source / …to the Side | Анотований перегляд покриття для файлу. |
| Toggle Annotated Source | Перемкнутися між кодом і анотованим поданням. Типово Alt+A (Ctrl+Alt+A на macOS). |
| Show Worst-Covered Files / Folders / Functions | Quick Pick із сортуванням від найгіршого. |
| Copy Uncovered Lines | Підсумок у Markdown для кожного непокритого діапазону. |
| Compare Two History Runs / with Last Run | Пофайлова різниця регресії — два запуски, збережені історією, або запуск на екрані відносно того, який він замінив. |
| Compare with CI Baseline | Завантажений запуск відносно звіту, названого в baseline.report — звіту гілки main із CI, URL чи завантаженого артефакту — файл за файлом. |
| Show Indirect Coverage Changes… | Рядки, покриття яких змінилося, хоча ніхто їх не редагував, відносно базової лінії CI або попереднього запуску, за файлами. |
| Check Coverage Thresholds | Оцінити перевірки відповідності. |
| Export Fucini JSON | Експортувати поточний запуск як Fucini JSON. |
| Export Coverage Report... | Виберіть формат — CSV, Markdown, LCOV, XML Cobertura, SARIF або значок SVG — і призначення. |
| Generate Coverage Badge | Записати SVG-значок активного прогону в badge.outputPath, показуючи badge.metric, і запропонувати відкрити його. |
| Copy MCP Server Configuration | Покласти в буфер обміну те, що потрібно клієнту MCP, щоб запитувати про покриття на екрані, — адресу сервера й ваш токен; якщо сервер вимкнено, запропонувати ввімкнути його. |
| Show Status Bar Menu | Відкрити меню швидких дій. |
| Browse for External HTML Report / Full Report Output Dir… | Задати каталоги звітів через діалог вибору. |
16. Довідник налаштувань
Повна, категоризована таблиця налаштувань — кожен параметр із типовим значенням — розміщена на сторінці Features & Settings. Усі ключі мають префікс fuciniCoverage..
Варто зазначити: fuciniCoverage.language закріплює власний інтерфейс розширення під час роботи (рядок стану, сповіщення, підказки, вебпанелі) за конкретною мовою, незалежно від мови інтерфейсу VS Code — за замовчуванням auto, і постачається з пакетами для всіх 18 підтримуваних мов. Це не змінює пункти палітри команд чи підписи в налаштуваннях, які VS Code визначає за власною мовою інтерфейсу.
У Visual Studio. Ті самі ключі fuciniCoverage.*, що читаються щонайбільше з чотирьох файлів, пізніший перемагає: власні користувацькі налаштування VS Code, якщо VS Code є на машині — читаються, ніколи не записуються, тож ваші кольори й пороги переходять разом; %APPDATA%\Fucini\CoverageStudio\settings.json, користувацькі налаштування цієї редакції; .vscode\settings.json у теці або поруч із рішенням, тож репозиторій, налаштований для VS Code, налаштований для Visual Studio; і fucini-coverage.json у корені рішення, для команди, яка воліла б не тримати теку .vscode у репозиторії .NET — редакція для VS Code теж його читає. Шестірня на панелі інструментів вікна Coverage відкриває вікно налаштувань, яке записує користувацький файл або той файл теки, що існує, як каже його перемикач Write changes to, і зберігає коментарі файлу, який редагує. fuciniCoverage.language там працює так само; меню йдуть за мовою самої Visual Studio.
17. Коди помилок
Діагностика надходить до вихідного каналу Fucini Coverage (View → Output → Fucini Coverage), кожна зі стабільним кодом FUCINI_*.
У Visual Studio. Ті самі коди йдуть до панелі Fucini Coverage вікна Output (View → Output) і зберігаються в %LOCALAPPDATA%\Fucini\CoverageStudio\coverage-studio.log — для запитання, що надходить після закриття IDE. Три, що трапляються: нічого не позначено, хоча панель каже, що файли завантажено — режим поля off, виберіть Show Coverage in Editor; FUCINI_REMAP_001 та інформаційна смуга — звіт називає шляхи, яких тут немає, і панель пропонує правило pathRemap; вікно Coverage каже, що потребує WebView2 — встановіть Microsoft Edge WebView2 Runtime, позначкам у редакторі він не потрібен.
| Код | Значення |
|---|---|
FUCINI_PARSE_001 | Непідтримуваний/нерозпізнаний формат покриття — жоден парсер не підійшов до файлу. |
FUCINI_PARSE_010 | Файл lcov не містив записів SF. |
FUCINI_PARSE_020 | JSON llvm-cov недійсний, без data[] або не містив файлів. |
FUCINI_PARSE_030 | Кореневий елемент Cobertura <coverage> відсутній або XML недійсний. |
FUCINI_PARSE_040 | Кореневий елемент JaCoCo <report> відсутній або немає вихідних файлів. |
FUCINI_PARSE_050 | JSON Istanbul/SimpleCov недійсний або не містив файлів. |
FUCINI_PARSE_060 | JSON SimpleCov недійсний або без масиву files верхнього рівня. |
FUCINI_PARSE_070 | Профіль Go без заголовка mode: або без блоків покриття. |
FUCINI_PARSE_080 | У Clover відсутній кореневий <coverage> чи <project>, або немає файлів. |
FUCINI_PARSE_090 | У OpenCover відсутній кореневий <CoverageSession> або немає файлів. |
FUCINI_PARSE_100 | JSON coverage.py недійсний або без об'єкта files верхнього рівня. |
FUCINI_PARSE_110 | JSON gcov/gcovr недійсний або без масиву files верхнього рівня. |
FUCINI_PARSE_120 | GNATcoverage XML без елемента <source> або index.xml, чиї xi:include так і не було розгорнуто — завантажте натомість файли *.xml для кожного джерела. |
FUCINI_PARSE_130 | Відсутній кореневий елемент <BullseyeCoverage> або в ньому немає елементів <src>. |
FUCINI_PARSE_140 | Відсутній кореневий елемент <CoverageDSPriv>, немає таблиці <SourceFileNames> для зіставлення рядків або немає даних про рядки. |
FUCINI_PARSE_150 | Некоректний JSON покриття Xcode або відсутній масив targets верхнього рівня. |
FUCINI_PARSE_160 | Відсутній кореневий елемент <coverage> SonarQube або в ньому немає елементів <file>. |
FUCINI_PARSE_170 | Некоректний JSON Coveralls або відсутній масив source_files верхнього рівня. |
FUCINI_LOAD | Завантаження скасовано з його сповіщення про поступ; попередній прогін, якщо він був, лишається завантаженим. |
FUCINI_REMOTE_001 | URL-адресу coverageFile.paths не вдалося отримати, з причиною; натомість завантажується остання завантажена копія. Звичайні рядки [FUCINI_REMOTE] записують кожне завантаження та кожну перевірку без змін (304). |
FUCINI_REMOTE_002 | URL-адреса з coverageFile.paths не дала повної відповіді за 30 секунд — найчастіше це проксі або VPN, що приймає з’єднання й далі мовчить; натомість завантажується остання завантажена копія. |
FUCINI_REMOTE_003 | URL-адреса з coverageFile.paths відповіла HTML-сторінкою замість файлу трасування — найімовірніше, сторінкою входу. Сторінка не кешується, натомість завантажується остання завантажена копія; перевірте токен у remote.headers. |
FUCINI_REMAP_002 | Для шляхів, які завантаження лишило незіставленими, запропоновано правило pathRemap, зі скількома з них воно пояснює — або жодного не вдалося вивести, або виведене правило вже є в налаштуванні й їх не розв'язало. |
FUCINI_REMAP_003 | Запропоноване правило дописано до fuciniCoverage.pathRemap командою Apply Suggested Remap, і покриття перезавантажується. |
FUCINI_GITDIFF_001 | Розширення Git недоступне; покриття diff пропускається й показується весь прогін. |
FUCINI_GITDIFF_002 | gitDiff.baseRef починається з -, з чого жодне посилання git починатися не може (git прочитав би його як опцію); покриття diff пропускається й показується весь прогін. |
FUCINI_IGNORE | Скільки файлів fuciniCoverage.ignore вилучив із прогону, і які саме. |
FUCINI_UNMEASURED_001 | Файли того ж виду, що й прогін, яких не завантажив жоден тест, по одному на рядок. |
FUCINI_UNMEASURED_002 | Понад 5 000 файлів робочої області збіглися з одним із розширень прогону; для списку невиміряних розглянуто лише перші 5 000. |
FUCINI_UNMEASURED_003 | У режимі count деякі невиміряні файли перелічено, але не зараховано: досягнуто межу читання (2 000 файлів або 50 МБ на завантаження). |
FUCINI_UNMEASURED_004 | Невиміряний файл не вдалося прочитати; його перелічено, але не зараховано. |
FUCINI_TESTCOVERAGE | Скільки файлів опубліковано в подання Test Coverage VS Code. |
FUCINI_BADGE | Значок записано, з його шляхом, підписом і значенням. |
FUCINI_BADGE_001 | Значок не вдалося записати, з причиною. |
FUCINI_WORKSPACE | Теку додано до робочої області або вилучено з неї; покриття шукається знову. |
FUCINI_VARIABLES | Що відповіла кожна ${command:…} у налаштуваннях шляхів або чому її залишено як є: команда не спрацювала, повернула щось непридатне або робоча область не довірена. |
FUCINI_WATCH | Що робить спостерігач: шляхи, за якими він стежить, налаштований файл, який з'явився, завдання, назване в watch.reloadAfterTasks, яке завершилося (з його кодом виходу) і спричинило перезавантаження, або шлях під files.watcherExclude, який натомість опитується. |
18. Конфіденційність
Телеметрію контролює параметр telemetry.enabled з областю window. За замовчуванням його вимкнено. Щоденне зведення та повідомлення про видалення також потребують, щоб глобальний telemetry.telemetryLevel VS Code дозволяв телеметрію; сигнал про встановлення та кілька невеликих подій надсилаються незалежно від нього, як і запис у журналі використання для встановлення на пробному періоді чи безкоштовному рівні Community. На Community Unlock Full Features обмінює цю телеметрію на всі можливості Pro, зокрема MC/DC, на 30 днів, один раз на машину — вимкніть його знову, і діятиме стандартний набір Community; на платну ліцензію це не впливає в жодному разі. Що саме надсилається, див. у політиці конфіденційності.
Дві речі варто знати, бо з ними ви можете щось зробити. Перша — ваш ID журналу використання: на пробному періоді та на Community розширення показує його в Show License / Activation і внизу розділу What Community Includes, де вибір цього рядка копіює ID і відкриває політику. Журнал знає вашу машину за гешем і більше ні за чим, тож цей ID — єдиний спосіб запитати, що журнал зберігає про вас, вимагати видалення чи заперечити проти нього: наведіть його — і ми знайдемо ваш рядок; без нього не знайдемо. Друга — запис про встановлення: один рядок, який створюється, коли встановлення звітує вперше, і зберігається, а не видаляється через 90 днів; він містить ідентифікатор встановлення, день, місце, до якого було розв'язано його адресу, версії та операційну систему — але не саму адресу й нічого про ваш код. Саме він дає нам змогу сказати, скільки встановлень було за ці роки. Обидва повністю описані в політиці конфіденційності, і обидва ми видаляємо на ваше прохання.

19. Оцінка та активація
Fucini Coverage Studio розповсюджується як оцінювальна передрелізна версія. Під час першого запуску вас просять погодитися її оцінювати, і починається пробний період — усі можливості доступні протягом 14-денного пробного періоду, який відлічується від першого використання на цій інсталяції. Немає фіксованої дати, після якої щось припиняє працювати.
Починаючи з версії 2.2026.2 пробний період нової інсталяції починається, щойно розширення один раз зв’яжеться із сервером ліцензій; до того часу воно працює на рівні Community і повідомляє про це. У контейнері розробки або Codespace пробний період не починається — повний набір там відкриває код підписки, ключ або 7-денна перепустка.
Коли пробний період завершується, нічого не блокується: розширення переходить на безкоштовний рівень Community. Щоб повернути повний набір, активуйте — активація з'єднується з ліцензійним сервером і застосовує отриманий ключ автоматично, без електронної пошти й без ключа, який довелося б переносити вручну:
Screenshot pending — add assets/img/licence-dialog.png (see SCREENSHOTS.md).- Виконайте
Fucini Coverage: Show License / Activation(також доступно зі стрічки стану після завершення пробного періоду чи дії ключа) і натисніть Request License… (або Request Renewed Key…, якщо ви вже активували раніше). - Підтвердьте запит. Ключ видається автоматично, а ваші контактні дані з попереднього запиту використовуються повторно, а не запитуються знову.
- Готово. Ключ активації генерується й автоматично записується в
fuciniCoverage.license.key. Стрічка стану за мить перемикається з пробного періоду на активовану ліцензію.
Ручний шлях в одній картинці: відкрийте панель ліцензії, виберіть Enter Key, вставте ключ із листа — і банер перемикається на «Activated».
Screenshot pending — add assets/img/activate-key.gif (see SCREENSHOTS.md).Якщо автоматичний запит усе ж не спрацює (немає з'єднання, проблема на сервері): виконайте Fucini Coverage: Copy Activation Request Code, надішліть код через сторінку контактів або на info@fucini.consulting, а отриманий у відповідь ключ FCK1.… вставте командою Fucini Coverage: Enter Activation Key (або безпосередньо у settings.json):
{ "fuciniCoverage.license.key": "FCK1.…вставте ключ повністю…" }Назва налаштування — fuciniCoverage.license.key (область user/global). Ключ прив'язаний до вашої машини та користувача ОС, може мати термін дії і може вмикати чи обмежувати окремі функції та обмежувати кількість завантажень покриття на день. Якщо з'являється повідомлення «invalid for this machine», запросіть новий ключ із цього встановлення — ключ, виданий для іншої машини, тут ніколи не пройде перевірку.
У Visual Studio. У цій редакції немає безкоштовного рівня: без підписки нічого не читається. З підпискою план вирішує там те саме, що й у VS Code, — функція, якої план не включає, недоступна, і її команда каже про це замість того, щоб виконатися. Найстаріша версія, яку ще підтримує сервер ліцензій, діє й там: старіша збірка повідомляє про це раз на день, із датою, коли вона перестане працювати, і працює до того часу. Робота без мережі ніколи не зупиняє збірку.
Безкоштовний рівень Community: тижнева квота
Community ніколи не перестає показувати покриття. Позначки на полях, оглядова лінійка, підказки при наведенні, CodeLens, подання Coverage, режим спостереження, покриття diff та історія не рахуються взагалі, а завантаження tracefile командою обмежене лише 25 разами на день. Обліковується виведення: по п'ять на тиждень для відкриття HTML-звіту, експорту, порівняння двох прогонів, перевірки порогів і перегляду анотованого вихідного коду на місці.
Тиждень — ваш, а не календарний: він починається з першого використання й закінчується через сім днів. Коли квоту вичерпано, повідомлення називає дію та день, коли вона повернеться, а після цього одного повідомлення про неї згадує лише рядок стану. Fucini Coverage: What Community Includes показує кожну квоту, скільки використано й коли вона оновиться, ще до того, як ви дійдете до будь-якої з них.
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).Три деталі належать до платних планів, тоді як самі знахідки залишаються безкоштовними: Community позначає кожен рядок, де є мутанти, що вижили, і каже, скільки їх, але не що саме змінив кожен мутант; каже, скільки тестів виконали рядок, але не їхні назви; і показує Max CRAP прогону, але не ранжований список Riskiest Methods.
Screenshot pending — add assets/img/mutant-hover-community.png (see SCREENSHOTS.md).Якщо ви вже користувалися Community, коли з'явилася тижнева квота (0.2026.83), ваші попередні обмеження діють ще 30 днів; вас повідомлять про це один раз, із датою. Лічильники зберігаються на вашому комп'ютері — у власному сховищі VS Code та в ~/.fucini-coverage/, тож новий профіль VS Code продовжує той самий тиждень, — і ніколи нікуди не надсилаються.
7-денна перепустка
Не готові до підписки? 7-денна перепустка — це все з Pro на один тиждень, оплачене один раз: нічого не поновлюється, і скасовувати нічого. Придбайте її на сторінці цін (у повідомленні про ліміт Community є кнопка для цього), а код активації надійде електронною поштою.
Screenshot pending — add assets/img/pricing-week-pass.png (see SCREENSHOTS.md).- Виконайте
Fucini Coverage: Enter Subscription Code— команда є і в редакції Community, і в Pro. - Виберіть Pro і вставте код
FCB1-…з листа. - Це все. Ключ видається й застосовується за вас і працює офлайн. Тиждень відлічується від оплати, тож активуйте одразу після покупки. Коли він мине, розширення саме повернеться до Community і далі показуватиме покриття.
Screenshot pending — add assets/img/pass-step-plan.png (see SCREENSHOTS.md).
Screenshot pending — add assets/img/pass-step-code.png (see SCREENSHOTS.md).У Visual Studio. Той самий код активує Fucini Coverage Studio для Visual Studio, 2022 і 2026: відкрийте Tools → Coverage Studio → Licence…, вставте код, виберіть план, для якого він призначений, і натисніть Activate. Вікно Coverage тоді показує Activated над деревом; розгорнутий стрілкою рядок показує дату, до якої дійсний ключ, і кнопку до вашого облікового запису. Одна машина — одне місце: активуйте VS Code або Visual Studio, і інший редактор на тій самій машині підхопить це сам — Visual Studio читає ключ VS Code, а VS Code читає ключ Visual Studio — тож нічого не вводиться двічі й друге місце не займається. Обидва підтримують ключ однаково: Pro Plus, Business і Enterprise звіряються двічі на день, а ключ Pro поновлюється за тиждень до закінчення.


Перехід на новий компʼютер і керування місцями
Ключ прив'язаний до однієї машини, тож новий компʼютер потребує нового — а підписка оплачує рівно стільки машин, скільки в ній зазначено. Звільніть стару самі: увійдіть у керування підпискою, знайдіть місце, яким більше не користуєтесь, натисніть Free up і активуйте нову машину тим самим кодом. Купівля Pro не надсилає вам пароля — обліковий запис існує, просто пароля ще немає, тож першого разу скористайтеся встановити або скинути пароль з адресою, на яку оформили підписку.
У планах Business і Enterprise ви запрошуєте кожного колегу електронною поштою з тієї самої сторінки. Кожен отримує код активації, що належить лише йому, і щойно він ним скористається, його адреса зʼявляється біля його місця — коли хтось іде, ви бачите, яке місце було його, і звільняєте для наступного. Запрошення тримає місце від моменту надсилання і спливає через 14 днів, якщо лишається невикористаним; відкличте його, щоб одразу повернути місце.
Тестування попередніх збірок
Нове потрапляє на fucini.software раніше, ніж у Marketplace, і ви можете попросити, щоб його вам пропонували. Відкрийте подання Coverage, розгорніть панель ліцензії та натисніть Тестувати попередні збірки… — або увімкніть fuciniCoverage.update.preRelease. Відтоді розширення перевіряє тут окремий канал попередніх збірок поряд зі звичайним і пропонує новішу з двох.
Screenshot pending — add assets/img/licence-prerelease.png (see SCREENSHOTS.md).Попередні збірки протестовані, але це збірки, у яких ми найменш упевнені, — ви зголошуєтеся знайти те, що ми проґавили. Приєднання повідомляє нам, що ця інсталяція в каналі, тож ми знаємо, скільки людей тестує, і можемо розповісти, що змінилося; вихід поверне вас на звичний шлях з наступним стабільним випуском. Попередня збірка є не завжди, і приєднатися, коли її немає, нічого не коштує: розширення знаходить порожній канал, нічого про це не каже і далі пропонує стабільні випуски, доки якусь не опублікують.
Screenshot pending — add assets/img/licence-prerelease-joined.png (see SCREENSHOTS.md).20. Контакти та ліцензія
Питання, повідомлення про помилки або альтернативні умови ліцензування — див. сторінку контактів або напишіть на info@fucini.consulting. Ліцензовано за умовами MIT з умовою про атрибуцію в нотатках до релізу; див. також Notice.
21. У командному рядку
Читач працює і без редактора: npm install -g fucini-coverage, безкоштовно, на Windows, Linux, WSL і macOS. fucini-coverage check coverage/lcov.info --lines 80 — контрольна точка, на якій конвеєр зупиняється з помилкою; summary, export, report, badge і compare роблять те, що й однойменні команди редакторів, а mcp обслуговує шість інструментів із розділу вище для агента на сервері. Він читає fucini-coverage.json, файл налаштувань, який читає редакція для Visual Studio, тож пороги задаються один раз. fucini-coverage help <command> пояснює кожну; повна сторінка — fucini-coverage на npm.
Screenshot pending — add assets/img/cli-demo.gif (see SCREENSHOTS.md).