Монорепозитории становятся всё более популярными и инструмент Nx уже давно зарекомендовал себя как мощное решение для их поддержки. Он упрощает управление зависимостями, автоматизирует задачи генерации кода, обеспечивает кэширование сборок и, конечно же, помогает запускать тесты и оценивать покрытие кода. Однако стандартный подход Nx при запуске тестов через Jest имеет одну особенность: для каждого проекта создаётся свой собственный отчёт.

Проблема разрозненных отчётов
Когда запускается тестирование, например, командой:
nx test my-app --codeCoverage
в каждом проекте создаётся своя директория с отчётом, например, coverage/apps/my-app
или coverage/libs/my-shared-lib
. В каждой из этих папок находится файл coverage-final.json
с данными о покрытии конкретного проекта. Такой подход удобен для локального анализа, но когда речь идёт о монорепозитории, где важно видеть целостную картину, наличие множества отдельных отчётов становится проблемой.
Решение: объединение отчётов с помощью nyc-merge
Встроенные возможности Nx не предусматривают агрегирование данных покрытия из нескольких проектов в один сводный отчёт. Но это не так сложно — можно написать свой скрипт, который соберёт все coverage-final.json
файлы, или воспользоваться готовым инструментом. Одним из таких решений является CLI-инструмент nyc-merge.
Что даёт nyc-merge?
Интеграция с Nx: Инструмент автоматически находит файлы отчетов в стандартных каталогах (
coverage/apps/*
,coverage/libs/*
и т.д.).Гибкость поиска: Использование glob-шаблонов (с помощью библиотеки
fast-glob
) позволяет легко учесть любую структуру директорий.Корректное объединение: Благодаря использованию
istanbul-lib-coverage
(ядро утилиты nyc) отчёты объединяются с учётом всех тонкостей.Параллельная обработка: Быстрая обработка файлов даже на многоядерных машинах.
Простой интерфейс: Минимум настроек, позволяющих интегрировать инструмент в любые CI/CD-процессы.
Пошаговое руководство по объединению отчётов
1. Установка nyc-merge
Установите инструмент как зависимость для разработки в корне вашего Nx-воркспейса:
npm install --save-dev nyc-merge
# или
yarn add --dev nyc-merge
# или
pnpm add --save-dev nyc-merge
2. Запуск тестов и сбор отчётов
Запустите тесты для всех проектов, либо укажите конкретные приложения и библиотеки:
nx run-many --target=test --all --codeCoverage
# или для конкретных проектов:
# nx run-many --target=test --projects=app1,lib1,lib2 --codeCoverage
После выполнения тестов мы получим отдельные отчёты, расположенные, например, в coverage/apps
и coverage/libs
.
3. Объединение отчетов
Для объединения файлов воспользуйтесь nyc-merge
. Пример команды:
npx nyc-merge \
-o coverage/coverage-final.json \
'coverage/**/coverage-final.json'
Если структура ваших директорий иная, можно использовать свои пути, например:
npx nyc-merge \
-o coverage/coverage-final.json \
'coverage/apps/*/coverage-final.json' \
'coverage/libs/*/coverage-final.json'
4. Генерация сводного HTML-отчёта
Объединив данные в один файл, создайте наглядный HTML-отчёт:
npx nyc report --reporter=html --report-dir=coverage --temp-dir=coverage
Таким образом, вы получаете единое представление покрытия для всего монорепозитория, что упрощает анализ и улучшает контроль качества кода.
Интеграция в package.json
Удобства ради можно добавить соответствующие скрипты в корневой файл package.json
вашего проекта:
{
"scripts": {
"coverage:test:all": "nx run-many --target=test --all --codeCoverage",
"coverage:merge": "npx nyc-merge -o coverage/coverage-final.json coverage/**/coverage-final.json",
"coverage:html": "npx nyc report --reporter=html --report-dir=coverage --temp-dir=coverage",
"coverage": "npm run coverage:test:all && npm run coverage:merge && npm run coverage:html"
}
}
Теперь, выполнив команду:
npm run coverage
вы получите полный цикл: запуск тестов, объединение отчётов и генерацию итогового HTML-отчёта.
Настройка покрытия кода в Jest
Немаловажным аспектом является конфигурация Jest, которая отвечает за сбор покрытия кода. Ниже приведён пример файла jest.preset.js
с оптимальными настройками:
module.exports = {
...nxPreset,
collectCoverage: true,
coverageDirectory: 'coverage',
coverageReporters: ['json'],
coverageThreshold: {
global: {
statements: 80,
branches: 80,
functions: 80,
lines: 80,
},
},
};
Объяснения ключевых опций:
collectCoverage: true
Включает сбор информации о покрытии, позволяя фиксировать, какие участки кода были выполнены во время тестов.coverageDirectory: 'coverage'
Указывает директорию для сохранения отчётов о покрытии.coverageReporters: ['json']
Выбирает формат сохранения отчёта, в данном случаеjson
, что необходимо для последующего объединения с помощьюnyc-merge
.coverageThreshold
Определяет минимальные требования к покрытию кода. Если пороги не достигаются, тесты завершаются с ошибкой. В примере лимиты установлены на уровне 80% по основным категориям (инструкции, ветвление кода, функции и строки).

Вывод сводки в консоль
Для получения краткой сводки по покрытию можно добавить ещё один скрипт:
{
"scripts": {
"coverage:summary": "npx nyc report --reporter=text-summary --report-dir=coverage --temp-dir=coverage",
"coverage:report": "npm run coverage:test:all && npm run coverage:merge && npm run coverage:summary"
}
}
Можно повесить на хуки гита или встроить в CI/CD.
Заключение
Если вы работаете с Nx и хотите видеть реальное покрытие кода по всему монорепозиторию, попробуйте nyc-merge. Это простой, быстрый и надежный способ получить единый отчет, который также легко интегрируется в любой CI/CD и cэкономит ваше время.
Репозиторий проекта: https://github.com/BaryshevRS/nyc-merge