Пишете ли вы unit и интеграционные тесты
Что проверяют
Различаете ли вы уровни и понимаете ли, что и на каком уровне проверять.
Как отвечать
Модульные тесты проверяют логику в изоляции: зависимости подменены, база и сеть не задействованы, прогон занимает миллисекунды. Проверяют то, ради чего класс написан: расчёты, правила, обработку краевых случаев.
Интеграционные проверяют, что части работают вместе: репозиторий с настоящей базой, обработчик запроса со всей цепочкой, взаимодействие с внешним сервисом. Медленнее, зато ловят то, что модульные не видят: неверный запрос, несоответствие схемы, ошибку конфигурации.
Инструменты в экосистеме .NET: xUnit или NUnit как каркас, библиотеки подмены зависимостей, выразительные проверки, фабрика приложения для интеграционных проверок веб-слоя, контейнеры для поднятия настоящей базы в тесте.
Что стоит проговорить про подход:
- тестируем поведение, а не реализацию. Тест, знающий, какие внутренние методы вызываются, ломается при любом рефакторинге и мешает вместо помощи;
- структура из трёх частей: подготовка, действие, проверка. Имя теста описывает сценарий и ожидание;
- не подменять то, что можно взять настоящим. Настоящая база в контейнере даёт больше уверенности, чем заглушка репозитория, и стоит недорого. Заменитель хранилища в памяти вводит в заблуждение: он не проверяет ни запросы, ни ограничения, ни транзакции;
- детерминированность: никакой зависимости от текущего времени, случайности и порядка выполнения. Время подменяется абстракцией часов;
- покрытие это индикатор, а не цель. Высокий процент при проверках без утверждений ничего не значит.
Если интеграционных тестов в проекте не было, скажите честно и объясните, где они были бы полезны. Это лучше, чем приписывать себе несуществующую практику.
Где спотыкаются
Подменяют всё подряд и проверяют, что заглушка вернула то, что в неё положили.
Тестируют приватные детали реализации.
Используют хранилище в памяти вместо настоящей базы.
Гонятся за процентом покрытия.