Самые сложные автотесты |
05.07.2023 00:00 | ||||||||||||||||||||||||
Автор: Александр Романов (Oleksandr Romanov) Действительно ли легко писать и поддерживать UI-тесты? Действительно ли юнит- и интеграционные тесты – самые сложные? Эта статья – о моих мыслях о том, какие тесты сложны и почему. Если вы согласны или несогласны с моей точкой зрения, давайте обсудим это в комментариях. С чего все началось? В начале моей карьеры в автоматизации я концентрировался исключительно на UI-тестах. Затем, по прошествии некоторого времени, я познакомился с дзеном API-уровня и начал писать эти тесты при любой возможности (везде, где API существовал). Настало время SOAP и REST HTTP-тестирования. Однако в первые годы вне зависимости от того, сколько автотестов я писал, я всегда полагал, что мои тесты были слишком простыми. Настоящие «хардкорные» разработчики писали сложные и пугающие юнит- и интеграционные тесты. Для создания этих юнит-тестов нужно очень глубоко знать язык программирования и фреймворки. Я думал об этом, пока не решил познакомиться с фреймворками для юнит-тестирования, а также с юнит-тестами для одного из рабочих проектов. Юнит-тестыС одной стороны кажется, что юнит-тесты сложно писать. Но все становится гораздо проще, как только понимаешь суть этих тестов и становишься мастером хотя бы базовых возможностей тест-фреймворка (любого, вроде JUnit) – как правило, когда пишешь фичи и тесты самостоятельно. В юнит-тестировании мы концентрируемся на уровне класса (или нескольких тесно связанных классов). Основная идея тут в тестировании бизнес-логики. Затем все внешние вызовы можно имитировать, используя фреймворк-имитатор вроде Mockito. Простые тестовые данные создаются в форме заглушек или фейков. Когда вы разобрались, как правильно писать имитаторы и тесты, скорость создания новых тестов зависит только от сложности бизнес-логики самого класса. Что касается поддержки таких тестов, то это тоже нетрудно: они тесно связаны с кодом продукта, поэтому часто меняются. Сложность внедрения юнит-тестов так же невелика, как издержки на поддержку. Вопрос тут только в том, каков уровень тестируемости кода фичи. В юнит-тестах критически важно то, что разработчик полностью контролирует окружение, тестовые данные и поведение зависимостей. Интеграционные тестыИнтеграционное тестирование – одна из самых противоречивых тем для инженеров. У всех свое понимание того, что такое уровень интеграции. Лично я понимаю под интеграционными тестами тестирование индивидуальных компонентов в изоляции от системы в целом. К примеру, если на бэкэнде у нас много микросервисов, интеграционный тест можно проводить как на уровне сервисов (мы проверяем бизнес-логику сервиса целиком), так и на более гранулярном уровне – мы проверяем взаимодействие сервиса с базой данных. В этом случае мы имитируем запросы к остальным сервисам или внешним компонентам при помощи Wiremock. Другие зависимости можно запускать локально, как контейнеры Docker (testcontainers), или в форме базы данных в оперативной памяти. Такие тесты дают более реалистичную картину деятельности части системы и ее компонентов. Сложность внедрения у таких тестов – средняя. Основная проблема тут в правильной конфигурации зависимостей для сервиса. Поддерживать их тоже нетрудно. Если тест и код фичи верно спроектированы, интерфейсы между компонентами будут стабильнее, нежели в юнит-тестах. Изменение в базе данных или брокере сообщений не должно сильно повлиять на внутреннюю логику системы или сервиса. Что касается контроля, то контроль разработчика над зависимостями ограничен. Можно настраивать базу данных или очередь сообщений. Можно также задать некоторые тестовые данные в качестве пред- или постусловий. Однако нельзя быть стопроцентно уверенным, что база данных правильно внедрена. End-to-end тестыПод end-to-end тестами я подразумеваю как тесты UI, так и тесты API системы. В этих тестах важно то, что мы работаем с системой как пользователи. При желании их можно назвать тестами черного ящика. Как только вы освоите API Selenium Webdriver и научитесь использовать паттерн Page Object (и прочие), внедрение end-to-end тестов становится очень простым. Конечно, тут есть исключения: очень сложная заковыристая логика, экзотические браузеры, нестандартные API. Создание новых UI-тестов для разработчика довольно тривиальная задача по сравнению с юнит- и интеграционными тестами. Поэтому все убеждены, что end-to-end тесты – это самое простое. Но тонкость тут в том, что автоматизированное тестирование – это не только внедрение новых тестов, это также их поддержка. Это дебаг и исправления. Тут и находится самое крупное препятствие, практически айсберг, для понимания end-to-end тестирования. МНОЖЕСТВО внешних и внутренних факторов влияет на производительность и стабильность таких тестов:
Учитывая все эти подвижные детали, бизнес, менеджмент и даже коллеги-тестировщики все еще ожидают от UI-тестов практически стопроцентной стабильности. Но реальность жестока. При падении любого UI-теста его нужно изолировать, проанализировать и тщательно исправить. Если у вас есть специализированная команда автоматизаторов, эти смелые ребята должны не только понимать, в какой момент теста появилась проблема. Им нужно еще и изолировать ее, и сообщить о ней соответствующей команде разработки, чтобы ее исправили. Иногда исправление будет на уровне UI-теста или фреймворка. Иногда это изменение в требованиях или срочная необходимость исправления тестовых данных. Однако в ряде случаев исправить тест немедленно нельзя, особенно если первопричина неясна и требует времени на изучение. У команды разработки есть свои задачи и приоритеты. Если о таких падениях и проблемах никто не знает, это повышает риск бага на проде. Но это, в любом случае, вопрос эффективности применения end-to-end тестирования в проекте. Как инженер-автоматизатор, вы не контролируете систему и ее зависимости. У вас есть ваш браузер – и на этом все! Итак, какие же автотесты наиболее сложны?
Я не хочу сказать, что некоторые тесты бессмысленны и не приносят пользы. Я хочу лишь подчеркнуть, что после первоначальных усилий, потраченных на обучение, внедрение юнит- и интеграционных тестов становится сравнительно простой задачей. Именно поэтому нам нужно больше тестов на этих уровнях. UI-тесты могут превратиться в настоящий кошмар, если они медленны и нестабильны. Однако они могут затормозить весь процесс разработки и релиза, если команда автоматизации отделена, и каждая группа разработки не посвящает часть своего времени этим тестам. End-to-end тесты могут принести пользу или быть наиболее сложными в поддержке автотестами. Это мощный источник фрустрации для инженеров-автоматизаторов. Ожидаете ли вы стабильных UI-тестов от вашей команды автоматизаторов? |