Тесты регрессионных компонентов с огурцом. Есть ли граница для слоев, которые должны быть проверены?
На прошлой неделе я обнаружил, что должен подумать о том, как провести рефакторинг старого приложения, которое содержит только юнит-тесты. Моей первой идеей было добавить несколько сценариев тестирования компонентов с помощью Cucumber, чтобы ознакомиться с бизнес-логикой и убедиться, что я ничего не нарушаю своими изменениями. Но в тот момент у меня был разговор с одним из архитекторов в компании, в которой я работаю, и это заставило меня задуматься, стоит ли это того, и какой код я должен был на самом деле протестировать.
Это приложение имеет множество различных типов конечных точек: остальные конечные точки, которые нужно вызывать и вызывать, хранимые процедуры Oracle, а также темы и очереди JMS. Он развертывается в файле war на сервере Tomcat, а фабрика соединений с посредником и источник данных к базе данных настраиваются на сервере и выбираются с использованием JNDI.
Моя первая идея состояла в том, чтобы загрузить все приложение во встроенный Jetty, указав на настоящий web.xml, чтобы все загружалось так, как оно будет загружено из производственной среды, но затем высмеивало фабрику соединений и источник данных. Таким образом, будет проверена вся логика подключения к инфраструктуре, в которой развернуто приложение. Думая о гексагональной архитектуре, это кажется слишком большим усилием, имея в виду, что это только порты, логика которых должна заключаться только в преобразовании полученных данных в данные приложения. Разве это не должно быть модульным тестированием?
Моя следующая идея состояла в том, чтобы просто смоделировать хранимые процедуры и загрузить XML-файлы Spring в моем тесте без какого-либо веб-сервера, что облегчает имитацию классов. Для этого я буду использовать библиотеки, такие как Spring MockMvc для остальных конечных точек и Mockrunner для JMS. Но, опять же, этот подход все равно будет тестировать некоторые адаптеры и усложнять тестирование, поскольку результатом тестов будут полезные нагрузки XML и JSON. Преобразования, выполняемые в этом приложении, довольно тяжелые, когда один и тот же тип сообщения может содержать разные версии класса (каждое сообщение может содержать много сложных объектов, которые реализуют несколько интерфейсов).
Поэтому прямо сейчас я подумал, что, возможно, лучшим подходом было бы просто создать мои тесты из точки входа в приложение, сервисы, вызываемые из адаптеров, и убедиться, что сервисы отвечают за отправку сообщений брокеру или вызов других REST. конечные точки фактически вызываются. Затем просто убедитесь, что есть соответствующие модульные тесты для конечных точек, и проверьте, что все работает после развертывания, просто предоставив некоторые тесты дыма, которые выполняются в реальной среде. Это будет проверять логику подключения, и бизнес-логика будет проверяться изолированно, не заботясь о том, добавлен ли новый адаптер или один из них удален.
Правильный ли этот подход? Буду ли я оставить что-то без тестирования таким образом? Или это все еще слишком много, и я должен просто доверять юнит-тестам?
Благодарю.
1 ответ
Ваше приложение и окружение звучат довольно сложно. Я определенно хотел бы интеграционные тесты. Я бы протестировал приложение снаружи-в следующем:
Напишите набор тестов дыма, который работает с приложением в реальной производственной среде. Огурец будет хорошим инструментом для использования. Этот набор должен выполнять только те операции, которые безопасны на производстве, и должны быть как можно меньшими, обеспечивая при этом уверенность в том, что приложение правильно установлено и настроено и что его интеграции с другими системами работают.
Напишите набор приемочных тестов, который работает со всем приложением в тестовой среде. Огурец был бы хорошим выбором и здесь.
Я ожидал бы, что среда приемочного тестирования будет включать сервер Tomcat с тестовыми версиями всех сервисов, существующих в вашем производственном Tomcat, и базу данных со схемой, хранимой процедурой и т. Д., Идентичными производственным (но не рабочим данным). Обрабатывайте внешние зависимости, которые вам не принадлежат, с помощью заглушек и насмешек, используя библиотеку записи / воспроизведения, такую как Betamax, и / или выполняя их тестовые версии самостоятельно. Приемочные тесты должны быть свободны для любых действий с данными, и им не нужно беспокоиться о доступности услуг, которыми вы не владеете.
Напишите достаточно приемочных тестов, чтобы как описать основные варианты использования приложения, так и проверить все важные взаимодействия между частями приложения (как подсистемами, так и классами). То есть используйте ваши приемочные тесты в качестве интеграционных тестов. Я обнаружил, что между целями приемочных и интеграционных тестов очень мало противоречий. Однако не пишите больше приемочных тестов, чем нужно для спецификации и интеграции, поскольку они относительно медленные.
Проведите юнит-тестирование каждого класса, который делает что-нибудь интересное, оставляя только те классы, которые полностью проверены вашими приемочными тестами Поскольку вы уже тестируете интеграцию, ваши юнит-тесты могут быть настоящими юнит-тестами, которые заглушают или высмеивают их зависимости. (Хотя нет ничего плохого в том, чтобы позволить классу, проверенному модулем, использовать реальные зависимости, которые достаточно просты, чтобы не вызывать проблем в модульных тестах).
Измерьте охват кода, чтобы убедиться, что комбинация приемочных и модульных тестов проверяет весь ваш код.