Страницы

Поиск по вопросам

пятница, 29 ноября 2019 г.

Почему при модульном тестировании изолируют зависимости?

#тестирование #юнит_тесты


Является ли обращение к БД напрямую из тестов плохим тоном? Или это частный случай
тестирования, когда нет необходимости проверять правильность добавления и удаления
данных в базу и из базы?
    


Ответы

Ответ 1



В модульных тестах это не просто "плохой тон" - это недопустимо. По хорошему, при модульном тестировании должны выполнятся все эти условия: Каждый тест должен проверять строго только одну теорию о поведении модуля Тестируемый класс должен быть изолирован от любых зависимостей - в том числе и от классов с которыми он работает(слава IoC!). И уж тем более, не должно присутствовать внепроектных зависимостей, таких как базы данных, время, сетевое и межпроцессное взаимодействие. Все зависимости при этом заменяют написанными вручную, либо автоматически сгенерированными заглушками. Тест должен никогда не выполнятся более одной секунды. Чем меньше времени выполняется каждый тест - тем лучше, т.к. иначе разработчикам будет просто лениво ждать выполнения всех тестов при каждом перестроении проекта, и из-за этого от модульного тестирования со временем откажутся. Использовать реальные зависимости нельзя из-за параллельной природы модульных тестов. Когда у вас в тестовом проекте появится больше одного теста с реальными зависимостями, между ними обязательно начнутся конфликты и ошибки взаимодействия. Скажем, у вас в базе есть таблица. В одном тесте вы из неё удаляете строки, во втором добавляете, а в третьем получаете. Да, вы можете в конце каждого теста возвращать эту таблицу в исходное состояние, однако в модульных тестах вам никто вам не гарантирует, что в момент получения из таблицы строк третьим тестом, первый тест нужные строки не удалит - сущий хаос. Хотите тестировать живую базу, живые зависимости - делайте это в интеграционных и/или функциональных тестах. Интеграционные тесты - по сути, те же самые модульные тесты, в которых используются реальные зависимости, и которые выполняются не параллельно, а поочередно, в одной строгой последовательности. В отличии от модульных тестов, их цель - протестировать поведение модулей в составе единой системы. Для них используют практически те же самые инструменты, что и для модульного тестирования. В проектах, использующих IoC-контейнеры, порой интеграционные и модульные тесты имеют общий код тестов - при интеграционном тестировании создают тестовое окружение(в чистую систему ставят нужные пакеты/приложения, изменяют необходимые настройки, развертывают базы данных), в IoC-контейнере заменяют заглушки реальными зависимостями, после чего выполняют тесты в нужной последовательности. Наиболее полезны интеграционные тесты при тестировании "невидимой" пользователю части проекта(бекенду). Функциональные тесты - имитируют действия реального человека, работающего с программным продуктом. При таком тестировании, на тестовых серверах/устройствах разворачивается полноценная, рабочая версия проекта, ничем не отличающаяся от той, с которой работают пользователи. Тесты загружают сайт проекта в браузере или запускают приложение на ПК/мобильных устройствах, и, к примеру, щелкают на кнопки, вводят текст, перетаскивают элементы интерфейса, и т.д. Таким образом проверяется соответствие внешнего поведения приложения тому, которое пользователь ждет от приложение, ну и корректность этого поведения(скажем - верно ли отображается html-страничка в десятке разных браузеров на разных платформах, да работают ли на них все заявленные функции?). Их выгодно использовать при наличии в проекте сложного и функционального пользовательского интерфейса(фронтенда).

Комментариев нет:

Отправить комментарий