11. Coverage отчёты

Что такое Code Coverage?
Заголовок раздела «Что такое Code Coverage?»Code Coverage показывает, какой процент кода выполняется во время тестов.
Типы покрытия
Заголовок раздела «Типы покрытия»| Тип | Описание |
|---|---|
| Statement | Сколько строк/инструкций выполнено |
| Branch | Сколько ветвлений (if/else) пройдено |
| Function | Сколько функций вызвано |
| Line | Сколько строк выполнено |
Настройка
Заголовок раздела «Настройка»module.exports = { collectCoverage: true, collectCoverageFrom: [ 'src/**/*.{js,ts,jsx,tsx}', '!src/**/*.d.ts', '!src/**/*.stories.{js,ts}', '!src/index.ts', ], coverageThresholds: { global: { branches: 70, functions: 80, lines: 80, statements: 80, }, // Конкретный файл './src/utils/payment.ts': { statements: 100, branches: 100, }, }, coverageReporters: ['text', 'text-summary', 'html', 'lcov'],};# Запускnpx jest --coveragenpx jest --coverage --coverageDirectory=coverageexport default defineConfig({ test: { coverage: { provider: 'v8', // или 'istanbul' reporter: ['text', 'html', 'json'], include: ['src/**/*.ts'], exclude: ['src/**/*.test.ts', 'src/types/**'], thresholds: { statements: 80, branches: 70, functions: 80, lines: 80, }, }, },})Пример отчёта в консоли
Заголовок раздела «Пример отчёта в консоли»----------|---------|----------|---------|---------|File | % Stmts | % Branch | % Funcs | % Lines |----------|---------|----------|---------|---------|All files | 82.35 | 75.00 | 87.50 | 82.35 | cart.ts | 90.00 | 85.00 | 100.00 | 90.00 | utils.ts | 70.00 | 60.00 | 75.00 | 70.00 |----------|---------|----------|---------|---------|HTML отчёт
Заголовок раздела «HTML отчёт»npx jest --coverageopen coverage/lcov-report/index.htmlHTML отчёт показывает:
- Красным: непокрытые строки/ветки
- Зелёным: покрытые
- Жёлтым: частично покрытые
Понимать coverage: что не охвачено
Заголовок раздела «Понимать coverage: что не охвачено»export function processPayment(amount, method) { if (amount <= 0) { // Branch: тестируем throw new Error('Invalid amount'); }
if (method === 'card') { // Branch: тестируем return chargeCard(amount); } else if (method === 'crypto') { // Branch: НЕ тестируем! return chargeCrypto(amount); } else { // Branch: НЕ тестируем! throw new Error('Unknown method'); }}
// Тесты покрывают только частьtest('throws for invalid amount', () => { expect(() => processPayment(-1, 'card')).toThrow();});
test('processes card payment', () => { expect(processPayment(100, 'card')).toBeDefined();});// Branch coverage: 50% (crypto и else не покрыты)Istanbul комментарии (игнорировать)
Заголовок раздела «Istanbul комментарии (игнорировать)»/* istanbul ignore next */ // игнорировать следующую строку/* istanbul ignore if */ // игнорировать if ветку/* istanbul ignore else *//* istanbul ignore file */ // весь файл
// Vitest / c8/* c8 ignore next *//* c8 ignore start */// ... игнорируемый код/* c8 ignore stop */
// Примеры законного использованияfunction isProduction() { /* istanbul ignore next */ return process.env.NODE_ENV === 'production';}
class Logger { /* istanbul ignore next */ static getInstance() { if (!Logger.instance) { Logger.instance = new Logger(); } return Logger.instance; }}CI/CD интеграция
Заголовок раздела «CI/CD интеграция»# GitHub Actions- name: Test with coverage run: npm run test:coverage
- name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage/lcov.info fail_ci_if_error: true// Порог не пройден — CI падает// > Coverage threshold not met:// > statements: 72% < 80% ← не прошли!Практические задания
Заголовок раздела «Практические задания»- Настрой coverage для своего проекта, установи пороги
- Найди непокрытые ветки в HTML отчёте и добавь тесты
- Настрой отправку coverage в Codecov через GitHub Actions
- Coverage = процент кода, покрытого тестами
- Statement, Branch, Function, Line — четыре метрики
- 80% — хорошая цель, 100% — не всегда нужно
- Используй пороги (thresholds) в CI/CD
- HTML отчёт — лучший инструмент для анализа