Средство запуска тестов Bun теперь поддерживает встроенную отчётность по покрытию кода. Это упрощает просмотр того, какая часть кодовой базы покрыта тестами, и поиск областей, которые в настоящее время недостаточно протестированы.
Включение покрытия
bun:test поддерживает просмотр того, какие строки кода покрыты тестами. Для использования этой функции передайте --coverage в CLI. Он выведет отчёт о покрытии в консоль:
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:
[test]
# Всегда включать покрытие
coverage = trueПо умолчанию отчёты о покрытии будут включать тестовые файлы и исключать sourcemaps. Обычно это то, что вам нужно, но это можно настроить в bunfig.toml.
[test]
coverageSkipTestFiles = true # по умолчанию falseПороги покрытия
Можно указать порог покрытия в bunfig.toml. Если ваш набор тестов не достигает или не превышает этот порог, bun test завершится с ненулевым кодом выхода, чтобы указать на неудачу.
Простой порог
[test]
# Для требования 90% покрытия на уровне строк и функций
coverageThreshold = 0.9Подробные пороги
[test]
# Для установки различных порогов для строк и функций
coverageThreshold = { lines = 0.9, functions = 0.9, statements = 0.9 }Установка любого из этих порогов включает fail_on_low_coverage, вызывая неудачу запуска теста, если покрытие ниже порога.
Репортёры покрытия
По умолчанию отчёты о покрытии выводятся в консоль.
Для постоянных отчётов о покрытии кода в средах CI и для других инструментов вы можете передать опцию CLI --coverage-reporter=lcov или опцию coverageReporter в bunfig.toml.
[test]
coverageReporter = ["text", "lcov"] # по умолчанию ["text"]
coverageDir = "path/to/somewhere" # по умолчанию "coverage"Доступные репортёры
| Репортёр | Описание |
|---|---|
text | Выводит текстовую сводку покрытия в консоль |
lcov | Сохраняет покрытие в формате lcov |
Репортёр покрытия LCOV
Для генерации отчёта lcov вы можете использовать репортёр lcov. Это создаст файл lcov.info в каталоге coverage.
[test]
coverageReporter = "lcov"# Или через 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
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Исключение файлов из покрытия
Пропуск тестовых файлов
По умолчанию тестовые файлы сами включаются в отчёты о покрытии. Вы можете исключить их с помощью:
[test]
coverageSkipTestFiles = true # по умолчанию falseЭто исключит файлы, соответствующие шаблонам тестов (например, *.test.ts, *.spec.js), из отчёта о покрытии.
Игнорирование конкретных путей и шаблонов
Вы можете исключить конкретные файлы или шаблоны файлов из отчётов о покрытии, используя coveragePathIgnorePatterns:
[test]
# Одиночный шаблон
coveragePathIgnorePatterns = "**/*.spec.ts"
# Несколько шаблонов
coveragePathIgnorePatterns = [
"**/*.spec.ts",
"**/*.test.ts",
"src/utils/**",
"*.config.js"
]Эта опция принимает glob-шаблоны и работает аналогично шаблонам игнорирования collectCoverageFrom из Jest. Файлы, соответствующие любому из этих шаблонов, будут исключены из расчёта покрытия и отчётности как в текстовых, так и в LCOV выводах.
Распространённые варианты использования
[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; это редко будет желательно за пределами продвинутых вариантов использования.
[test]
coverageIgnoreSourcemaps = true # по умолчанию falseЗначения покрытия по умолчанию
По умолчанию отчёты о покрытии:
- Исключают каталоги
node_modules - Исключают файлы, загруженные через не-JS/TS загрузчики (например,
.css,.txt), если не указан пользовательский JS-загрузчик - Включают сами тестовые файлы (можно отключить с помощью
coverageSkipTestFiles = true) - Могут исключать дополнительные файлы с помощью
coveragePathIgnorePatterns
Продвинутая конфигурация
Пользовательский каталог покрытия
[test]
coverageDir = "coverage-reports" # по умолчанию "coverage"Несколько репортёров
[test]
coverageReporter = ["text", "lcov"]Покрытие с конкретными шаблонами тестов
# Запуск покрытия только на конкретных тестовых файлах
bun test --coverage src/components/*.test.ts
# Запуск покрытия с шаблоном имени
bun test --coverage --test-name-pattern="API"Интеграция с CI/CD
Пример GitHub Actions
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
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-компонентов: Часто приемлемо, так как они могут требовать интеграционных тестов
Лучшие практики
Сосредоточьтесь на качестве, а не только на количестве
// Хорошо: Тестирование фактической функциональности
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); // Без утверждений!
});Тестирование граничных случаев
test("валидация пользовательского ввода", () => {
// Нормальный случай
expect(validateEmail("user@example.com")).toBe(true);
// Граничные случаи, которые осмысленно улучшают покрытие
expect(validateEmail("")).toBe(false);
expect(validateEmail("invalid")).toBe(false);
expect(validateEmail(null)).toBe(false);
});Использование покрытия для поиска отсутствующих тестов
# Запуск покрытия для определения непокрытого кода
bun test --coverage
# Посмотреть конкретные файлы, которые требуют внимания
bun test --coverage src/critical-module.tsКомбинирование с другими метриками качества
Покрытие — это только одна метрика. Также рассмотрите:
- Качество код-ревью
- Покрытие интеграционными тестами
- Тесты обработки ошибок
- Тесты производительности
- Безопасность типов
Устранение неполадок
Покрытие не отображается для некоторых файлов
Если файлы не отображаются в отчётах о покрытии, они могут не импортироваться вашими тестами. Покрытие отслеживает только файлы, которые фактически загружены.
// Убедитесь, что импортируете модули, которые хотите протестировать
import { myFunction } from "../src/my-module";
test("моя функция работает", () => {
expect(myFunction()).toBeDefined();
});Ложные отчёты о покрытии
Если вы видите отчёты о покрытии, которые не соответствуют вашим ожиданиям:
- Проверьте, правильно ли работают source maps
- Проверьте шаблоны файлов в
coveragePathIgnorePatterns - Убедитесь, что тестовые файлы фактически импортируют код для тестирования
Проблемы производительности с большими кодовыми базами
Для больших проектов сбор покрытия может замедлить тесты:
[test]
# Исключить большие каталоги, для которых не нужно покрытие
coveragePathIgnorePatterns = [
"node_modules/**",
"vendor/**",
"generated/**"
]Рассмотрите запуск покрытия только в CI или конкретных ветках, а не при каждом запуске тестов во время разработки.