Монорепозитарии на примерах с использованием Lerna. Часть 2
После краткого обзора проекта с монорепозитариями, использование Lerna для управления проекта и борьбы с дублированием зависимостей мы рассмотрим преимущества тестирования использования монорепозитарий.
Эта статья является частью серии, начинающейся с Монорепозитарии на примерах с использованием Lerna. Часть 1. Финальная версия проекта monorepo для этой серии доступна для скачивания.
Дублирование зависимостей
Я столкнулся с интересной проблемой в предыдущей статье;
Напоминаем, что мы закончили со следующей структурой папок и зависимостями:
- apple и banana зависят от sillyname@0.0.3
- grocery зависит от sillyname@0.1.0
- grocery зависит от apple и banana
Текущее состояние
- Когда мы запустим index.js в grocery, код в grocery использует sillyname@0.1.0 а код в apple и banana использует sillyname@0.0.3 .
- Обычно не будет ни каких проблем с запуском sillyname, и все должно работать как ожидается.
- Но в то же самое время если мы создадим фронтенд приложение, на нужно будет сохранить две версии sillyname в одном bundle. Но размер bundle может иметь ограничение и это может стать проблемой.
Вернемся к этому вопросу в следующей статье этой серии; в частности, поскольку это связано с использованием библиотек зависимостей дизайна внешнего интерфейса (наше решение будет в использовании одноранговых зависимостей).
Тестирование
Один из аргументов в пользу использования монорепозитарий заключается в том, что его проще тестировать; давайте рассмотрим это с помощью Jest.
примечание: эта статья подразумевает базовое понимание Jest;
У вас должен быть корневой package.json, который создатся по время установки lerna. Вы должны прописать запуск всех ваших тестов, и все другие схожие задачи. Корневой package.json так же должен содержать все “hoisted” пакеты зависимостей, что увеличить скорость запуска проекта при использование флага — hoist.
С начало установим Jest в: корне проекта
npm install jest --only=dev
И внесем изменения:
jest.config.js
module.exports = { collectCoverage: true, collectCoverageFrom: [ 'packages/**/*.{js}', '!**/node_modules/**', ], roots: [ 'packages/', ], };
package.json
{ "scripts": { "test": "jest" }, "devDependencies": { "jest": "^22.4.2", "lerna": "^2.9.0" } }
Далее, видим что у monorepo нет никаких преимуществ для юнит тестирования; так как нам нужно создать фейковый sillyname для sillyname и apple (так же как для banana) и написать отдельные тесты:
packages/(apple|banana)/__mocks__/sillyname.js
module.exports = () => 'TEST';
packages/(apple|banana)/index.test.js
const apple = require('./'); test('returns correct string', () => { expect(apple).toBe('apple and TEST'); });
Точно так же фейковые apple, banana, и sillyname для тестирования grocery модуля.
packages/grocery/__mocks__/(apple|banana|sillyname).js
module.exports = 'TEST';
packages/grocery/index.test.js
const log = jest.fn(); console.log = log; const grocery = require('./'); test('outputs correct string', () => { expect(log.mock.calls.length).toBe(3); expect(log.mock.calls[0][0]).toBe('grocery and TEST'); expect(log.mock.calls[1][0]).toBe('TEST'); expect(log.mock.calls[2][0]).toBe('TEST'); });
Но monorepo действительно поможет нам написать интеграционные тесты, например нам нужно проверить связь apple и banana с grocery.
integration.test.js
jest.unmock('apple'); jest.unmock('banana'); const log = jest.fn(); console.log = log; const grocery = require('./packages/grocery/'); test('outputs correct string', () => { expect(log.mock.calls.length).toBe(3); expect(log.mock.calls[0][0]).toBe('grocery and TEST'); expect(log.mock.calls[1][0]).toBe('apple and TEST'); expect(log.mock.calls[2][0]).toBe('banana and TEST'); });
В результате:
- Мы создали интеграционный тест в корне проекта.
- Вызов unmock запускает интеграционный тест; тест использует код apple и banana при загрузке grocery.
Сейчас мы можем запустить наши тесты командой:
npm run test
примечание: Jest будет предупреждать о дубликатах фейковых функций (mock) sillyname при запуске интеграционных тестов. Так как нам нужны эти mocks, я не знаю как избавиться от этих предупреждений.Следующий шаг
Оригинал: Monorepos By Example: Part 2