. 90% тестов интеграционные-
юнит тесты – мокаем все внешнее, запускаем изнутри кода
-
интеграционные тесты – используем тестовое внешнее окружение (БД, API, fs, etc.), запускаем изнутри кода
-
e2e тесты – запускаем приложение в отдельном процессе и тестируем вне кода самого приложения
Практически все тесты, которые я пишу интеграционные: (1) реальная сложность это чаще всего именно сочетание запросов к БД / стороннего API и бизнес-логики и только в такой связке можно проверить работоспособнсть приложения, (2) скорость их написания не меньше, чем юнит тесты, если у вас есть шаблон
Если же мне надо протестировать именно бизнес-логику (алгоритм), тогда я вынесу его в отдельную функцию, в которой не будут пробрасываться никакие внешние зависимости (чтобы ничего не надо было мокать)
. Не тестируй траспортЯ пишу интеграционные тесты на уровне функций бизнес-логики, то есть, не включаю вызов через HTTP, MQ, TCP, etc.
Если вы хотите протестировать транспорт, тестируйте его отдельно или в рамках e2e тестов
. Тестируй фичи
Условно "фича" это самая верхняя функция, которую вы вызываете из слоя транспорта. То есть, ваши тесты "имитируют вызов этого endpoint / trigger".
Тестироват глубже чаще всего не имеет смысла.
. Тестируй НЕ все– Если это просто запрос данных, то можешь протестировать чисто то, что фильтры правильно применились, а можешь забить хрен
– Если это CRUD, который ты написал в сотый раз, можно забить хрен
– А вот если в рамках фичи ты активно меняешь какие-то данные (INSERT, UPDATE, DELETE), то ее стоит протестировать
Поэтому некоторые приложения (финансовые транзакции) я покрываю на 90%, некоторые (отдать данные фронту) на 30%
. Дели тесты на юнит и интеграционные
Я делаю постфикс в название функций тестирования или файлов (например, .unit.ts, .int.ts), что позволяет мне написать отдельные конфигурации для каждого из них и запускать только те, которые нужно
. Пиши тесты рядом с кодом
Только так и никак иначе. Потому что так (1) ты не протестируешь лишнее, (2) легко понять какой тест к чему относится, (3) легко переносить такую папку в сторонее место
. Пиши тесты в разных файлах
Тестируя даже один и тот же код, я могу сделать несколько файлов с тестами, чтобы удобнее между ними распределять код.
. Сделать глобальную либу для тестов
В такую либу я выношу: (1) подключение к БД, с созданием snapshot, (2) аутентификации, (3) seeder со всеми основными сущностями, который кладет их в БД, чтобы не приходилось делать это каждый раз заново, (4) инициатор всех нужных зависимостей (логгер, конфига, etc.)
. Не используй ООП
Ну, точнее, если вы хотите протестировать отдельный метод, есть большая вероятность, что если он не статический, то вам придется создавать инстанс пропихивая множество зависимостей, которые не нужны этому методу
Если вы с этим столкнулись и хотите продолжать использовать ООП, то узнайте что такое Service Object
В ФП, ПП и
ФОП такой проблемы нет (потому что каждая функция существует отдельно от другой)
. Создавай отдельный env для тестов
Он может переиспользовать структуру основного env, то должен быть отдельным
. Используй docker-composeПеред началом интеграционных тестов я просто из кода в global setup или же в Makefile / npm scripts, поднимаю docker-compose со всеми нужными мне БД / API, потом поднимаю миграции и фикстуры, и когда все готово уже запускаю приложение
Есть еще testcontainers, но я не увидел ниодного преимущества перед использованием чистого docker-compose
. Создавай snapshot БДКак я делаю: создаю основную БД,, накатываю на нее миграции и фикстуры, а потом превращаю ее в template из которого каждый отдельный тест создает свою версию БД.
Это позволяет запускать интеграционные тесты все и сразу (ну, или с лимитом) и быть уверенным, что один тест не повлияет на другой.
(вторая часть ниже)