Skip to content

Средство запуска тестов Bun теперь поддерживает встроенную отчётность по покрытию кода. Это упрощает просмотр того, какая часть кодовой базы покрыта тестами, и поиск областей, которые в настоящее время недостаточно протестированы.

Включение покрытия

bun:test поддерживает просмотр того, какие строки кода покрыты тестами. Для использования этой функции передайте --coverage в CLI. Он выведет отчёт о покрытии в консоль:

bash
bun test --coverage

-------------|---------|---------|-------------------
File         | % Funcs | % Lines | Uncovered Line #s
-------------|---------|---------|-------------------
All files    |   38.89 |   42.11 |
 index-0.ts  |   33.33 |   36.84 | 10-15,19-24
 index-1.ts  |   33.33 |   36.84 | 10-15,19-24
 index-10.ts |   33.33 |   36.84 | 10-15,19-24
 index-2.ts  |   33.33 |   36.84 | 10-15,19-24
 index-3.ts  |   33.33 |   36.84 | 10-15,19-24
 index-4.ts  |   33.33 |   36.84 | 10-15,19-24
 index-5.ts  |   33.33 |   36.84 | 10-15,19-24
 index-6.ts  |   33.33 |   36.84 | 10-15,19-24
 index-7.ts  |   33.33 |   36.84 | 10-15,19-24
 index-8.ts  |   33.33 |   36.84 | 10-15,19-24
 index-9.ts  |   33.33 |   36.84 | 10-15,19-24
 index.ts    |  100.00 |  100.00 |
-------------|---------|---------|-------------------

Включение по умолчанию

Для всегдашнего включения отчётности по покрытию по умолчанию добавьте следующую строку в ваш bunfig.toml:

toml
[test]
# Всегда включать покрытие
coverage = true

По умолчанию отчёты о покрытии будут включать тестовые файлы и исключать sourcemaps. Обычно это то, что вам нужно, но это можно настроить в bunfig.toml.

toml
[test]
coverageSkipTestFiles = true  # по умолчанию false

Пороги покрытия

Можно указать порог покрытия в bunfig.toml. Если ваш набор тестов не достигает или не превышает этот порог, bun test завершится с ненулевым кодом выхода, чтобы указать на неудачу.

Простой порог

toml
[test]
# Для требования 90% покрытия на уровне строк и функций
coverageThreshold = 0.9

Подробные пороги

toml
[test]
# Для установки различных порогов для строк и функций
coverageThreshold = { lines = 0.9, functions = 0.9, statements = 0.9 }

Установка любого из этих порогов включает fail_on_low_coverage, вызывая неудачу запуска теста, если покрытие ниже порога.

Репортёры покрытия

По умолчанию отчёты о покрытии выводятся в консоль.

Для постоянных отчётов о покрытии кода в средах CI и для других инструментов вы можете передать опцию CLI --coverage-reporter=lcov или опцию coverageReporter в bunfig.toml.

toml
[test]
coverageReporter = ["text", "lcov"]  # по умолчанию ["text"]
coverageDir = "path/to/somewhere"    # по умолчанию "coverage"

Доступные репортёры

РепортёрОписание
textВыводит текстовую сводку покрытия в консоль
lcovСохраняет покрытие в формате lcov

Репортёр покрытия LCOV

Для генерации отчёта lcov вы можете использовать репортёр lcov. Это создаст файл lcov.info в каталоге coverage.

toml
[test]
coverageReporter = "lcov"
bash
# Или через CLI
bun test --coverage --coverage-reporter=lcov

Формат LCOV широко поддерживается различными инструментами и сервисами:

  • Редакторы кода: Расширения VS Code могут показывать покрытие встроенным образом
  • Сервисы CI/CD: GitHub Actions, GitLab CI, CircleCI
  • Сервисы покрытия: Codecov, Coveralls
  • IDE: WebStorm, IntelliJ IDEA

Использование LCOV с GitHub Actions

yaml
name: Test with Coverage
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: oven-sh/setup-bun@v2
      - run: bun install
      - run: bun test --coverage --coverage-reporter=lcov
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info

Исключение файлов из покрытия

Пропуск тестовых файлов

По умолчанию тестовые файлы сами включаются в отчёты о покрытии. Вы можете исключить их с помощью:

toml
[test]
coverageSkipTestFiles = true  # по умолчанию false

Это исключит файлы, соответствующие шаблонам тестов (например, *.test.ts, *.spec.js), из отчёта о покрытии.

Игнорирование конкретных путей и шаблонов

Вы можете исключить конкретные файлы или шаблоны файлов из отчётов о покрытии, используя coveragePathIgnorePatterns:

toml
[test]
# Одиночный шаблон
coveragePathIgnorePatterns = "**/*.spec.ts"

# Несколько шаблонов
coveragePathIgnorePatterns = [
  "**/*.spec.ts",
  "**/*.test.ts",
  "src/utils/**",
  "*.config.js"
]

Эта опция принимает glob-шаблоны и работает аналогично шаблонам игнорирования collectCoverageFrom из Jest. Файлы, соответствующие любому из этих шаблонов, будут исключены из расчёта покрытия и отчётности как в текстовых, так и в LCOV выводах.

Распространённые варианты использования

toml
[test]
coveragePathIgnorePatterns = [
  # Исключить файлы утилит
  "src/utils/**",

  # Исключить файлы конфигурации
  "*.config.js",
  "webpack.config.ts",
  "vite.config.ts",

  # Исключить конкретные шаблоны тестов
  "**/*.spec.ts",
  "**/*.e2e.ts",

  # Исключить артефакты сборки
  "dist/**",
  "build/**",

  # Исключить сгенерированные файлы
  "src/generated/**",
  "**/*.generated.ts",

  # Исключить код vendor/third-party
  "vendor/**",
  "third-party/**"
]

Sourcemaps

Внутренне Bun транспилирует все файлы по умолчанию, поэтому Bun автоматически генерирует внутреннюю source map, которая сопоставляет строки вашего исходного кода с внутренним представлением Bun. Если по какой-либо причине вы хотите отключить это, установите test.coverageIgnoreSourcemaps в true; это редко будет желательно за пределами продвинутых вариантов использования.

toml
[test]
coverageIgnoreSourcemaps = true  # по умолчанию false

Значения покрытия по умолчанию

По умолчанию отчёты о покрытии:

  • Исключают каталоги node_modules
  • Исключают файлы, загруженные через не-JS/TS загрузчики (например, .css, .txt), если не указан пользовательский JS-загрузчик
  • Включают сами тестовые файлы (можно отключить с помощью coverageSkipTestFiles = true)
  • Могут исключать дополнительные файлы с помощью coveragePathIgnorePatterns

Продвинутая конфигурация

Пользовательский каталог покрытия

toml
[test]
coverageDir = "coverage-reports"  # по умолчанию "coverage"

Несколько репортёров

toml
[test]
coverageReporter = ["text", "lcov"]

Покрытие с конкретными шаблонами тестов

bash
# Запуск покрытия только на конкретных тестовых файлах
bun test --coverage src/components/*.test.ts

# Запуск покрытия с шаблоном имени
bun test --coverage --test-name-pattern="API"

Интеграция с CI/CD

Пример GitHub Actions

yaml
name: Coverage Report
on: [push, pull_request]

jobs:
  coverage:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Bun
        uses: oven-sh/setup-bun@v2

      - name: Install dependencies
        run: bun install

      - name: Run tests with coverage
        run: bun test --coverage --coverage-reporter=lcov

      - name: Upload to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: ./coverage/lcov.info
          fail_ci_if_error: true

Пример GitLab CI

yaml
test:coverage:
  stage: test
  script:
    - bun install
    - bun test --coverage --coverage-reporter=lcov
  coverage: '/Lines\s*:\s*(\d+.\d+)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/lcov.info

Интерпретация отчётов о покрытии

Объяснение текстового вывода

-------------|---------|---------|-------------------
File         | % Funcs | % Lines | Uncovered Line #s
-------------|---------|---------|-------------------
All files    |   85.71 |   90.48 |
 src/        |   85.71 |   90.48 |
  utils.ts   |  100.00 |  100.00 |
  api.ts     |   75.00 |   85.71 | 15-18,25
  main.ts    |   80.00 |   88.89 | 42,50-52
-------------|---------|---------|-------------------
  • % Funcs: Процент функций, которые были вызваны во время тестов
  • % Lines: Процент исполняемых строк, которые были выполнены во время тестов
  • Uncovered Line #s: Конкретные номера строк, которые не были выполнены

К чему стремиться

  • 80%+ общее покрытие: Обычно считается хорошим
  • 90%+ критические пути: Важная бизнес-логика должна быть хорошо протестирована
  • 100% утилиты: Чистые функции и утилиты легко протестировать полностью
  • Меньшее покрытие для UI-компонентов: Часто приемлемо, так как они могут требовать интеграционных тестов

Лучшие практики

Сосредоточьтесь на качестве, а не только на количестве

ts
// Хорошо: Тестирование фактической функциональности
test("calculateTax должен обрабатывать различные налоговые ставки", () => {
  expect(calculateTax(100, 0.08)).toBe(8);
  expect(calculateTax(100, 0.1)).toBe(10);
  expect(calculateTax(0, 0.08)).toBe(0);
});

// Избегайте: Просто попадание в строки для покрытия
test("calculateTax существует", () => {
  calculateTax(100, 0.08); // Без утверждений!
});

Тестирование граничных случаев

ts
test("валидация пользовательского ввода", () => {
  // Нормальный случай
  expect(validateEmail("user@example.com")).toBe(true);

  // Граничные случаи, которые осмысленно улучшают покрытие
  expect(validateEmail("")).toBe(false);
  expect(validateEmail("invalid")).toBe(false);
  expect(validateEmail(null)).toBe(false);
});

Использование покрытия для поиска отсутствующих тестов

bash
# Запуск покрытия для определения непокрытого кода
bun test --coverage

# Посмотреть конкретные файлы, которые требуют внимания
bun test --coverage src/critical-module.ts

Комбинирование с другими метриками качества

Покрытие — это только одна метрика. Также рассмотрите:

  • Качество код-ревью
  • Покрытие интеграционными тестами
  • Тесты обработки ошибок
  • Тесты производительности
  • Безопасность типов

Устранение неполадок

Покрытие не отображается для некоторых файлов

Если файлы не отображаются в отчётах о покрытии, они могут не импортироваться вашими тестами. Покрытие отслеживает только файлы, которые фактически загружены.

ts
// Убедитесь, что импортируете модули, которые хотите протестировать
import { myFunction } from "../src/my-module";

test("моя функция работает", () => {
  expect(myFunction()).toBeDefined();
});

Ложные отчёты о покрытии

Если вы видите отчёты о покрытии, которые не соответствуют вашим ожиданиям:

  1. Проверьте, правильно ли работают source maps
  2. Проверьте шаблоны файлов в coveragePathIgnorePatterns
  3. Убедитесь, что тестовые файлы фактически импортируют код для тестирования

Проблемы производительности с большими кодовыми базами

Для больших проектов сбор покрытия может замедлить тесты:

toml
[test]
# Исключить большие каталоги, для которых не нужно покрытие
coveragePathIgnorePatterns = [
  "node_modules/**",
  "vendor/**",
  "generated/**"
]

Рассмотрите запуск покрытия только в CI или конкретных ветках, а не при каждом запуске тестов во время разработки.

Bun от www.bunjs.com.cn