как разбить приложение на модули для тестирования

Общая картина модульного тестирования

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Это не руководство, какие символы нужно ввести в редакторе кода, чтобы получились модульные тесты. Это — пища для ума, которую необходимо употребить до того, как предпринимать упомянутые действия.

Тема модульного тестирования не так проста, как может показаться. Многие из нас, разработчиков, приходят в модульное тестирование под давлением клиентов, сотрудников, коллег, своих кумиров и так далее. Мы быстро понимаем его ценность, и, закончив технические приготовления, забываем об общей картине, если вообще когда-либо её понимали. В этой статье я вкратце расскажу о том, чем является и чем не является модульное тестирование как в целом, так и в PHP, а заодно опишу, какое место занимает модульное тестирование в сфере QA.

Что такое тестирование?

Прежде чем углубляться в модульные тесты, нужно изучить теорию самого тестирования, чтобы не делать ошибок вроде той, что совершили авторы одного из самых популярных PHP-фреймворков: на своём сайте они показали интеграционные тесты и назвали их модульными. Нет, Laravel, это не модульные тесты. Хотя это не мешает мне всё ещё любить этот фреймворк.

Тестирование ПО определяется как «расследование, проведённое с целью предоставления заинтересованным сторонам информации о качестве продукта». Этому противопоставляется «тестирование ПО — это пустая трата бюджета проекта разработчиками, которые не делают ничего важного, а затем просят ещё времени и денег, потому что «ничего» может быть весьма дорогим». Тут ничего нового.

Вот моя краткая история становления тестирования:

Чем на самом деле является тестирование?

Есть разные классификации тестирования ПО. Чтобы лучше понимать место модульного тестирования, упомяну лишь о наиболее широкораспространённых подходах.

Тесты бывают: статические и динамические, «ящичные» (белый ящик, чёрный ящик, серый ящик), уровни и типы. В рамках каждого подхода используются разные критерии классификации.

Статическое и динамическое тестирование

Статическое тестирование проводится без исполнения кода. Сюда относится корректура, проверка, ревизия кода (при наблюдении за работой другого / парном программировании), критический анализ, инспекции и так далее.

Динамическое тестирование для получения корректных результатов требует исполнять код. Например, для модульных тестов, интеграционных, системных, приёмочных и прочих тестов. То есть тестирование проводится с использованием динамических данных, входных и выходных.

«Ящичный» подход

Согласно этому подходу, все тесты ПО делятся на три вида ящиков:

Уровни тестирования

Их количество варьируется, обычно, в диапазоне от 4 до 6, и все они полезны. Названия тоже бывают разные, в зависимости от принятой в компании культуры вы можете знать «интеграционные» тесты как «функциональные», «системные» тесты как «автоматизированные», и так далее. Для простоты я опишу 5 уровней:

Типы тестирования

Каждый тип тестирования, вне зависимости от его уровня, также может подразделяться на другие типы. Существует больше 20 общепринятых типов. Самые распространённые:

Теперь вы знаете, что модульные тесты являются динамическими, относятся к классу «белый ящик», выполняются на уровне модулей, представляют собой регрессионные тесты, но при этом под модульными тестами можно понимать многие разновидности тестов. Так что же такое на самом деле модульные тесты?

Что такое модульное тестирование?

V-модель — это графическое представление вышеупомянутых уровней, типов и их назначения в жизненном цикле разработки ПО.

как разбить приложение на модули для тестирования. zskeemvq28. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-zskeemvq28. картинка как разбить приложение на модули для тестирования. картинка zskeemvq28.

После проверки и утверждения подробных требований к продукту, когда уже начали писать код, первой линией защиты от любых несоответствий становятся модульные тесты. Поэтому компании, понимающие, что они делают, заставляют разработчиков использовать модульные тесты или даже TDD, поскольку гораздо дешевле исправить баги на начальных этапах, чем на более поздних.

И это справедливо. У модульных тестов масса достоинств. Они:

Я часто обсуждал с коллегами и клиентами, что такое хороший модульный тест. Он:

Что нужно подвергать модульному тестированию?

В нормальных системах модульные тесты нужно писать для:

Так что вы сами можете определять, что для вас является модулем. Или можете тестировать методы один за другим, упростив жизнь тому парню, что потом будет работать с кодом.

Если вы не проводите модульное тестирование, предлагаю заняться этим после возникновения следующего большого бага. Проверьте, с каким методом он будет связан, напишите сбойный тест с правильными аргументами и результатом, исправьте баг, снова запустите модульный тест. Если он будет пройден, то можете быть уверены, что этот баг пришлось исправлять в последний раз (с учётом ваших определённых входных сценариев).

Такой подход помогает легче понять модульное тестирование. Проанализируйте отдельно каждый метод. Поставщики данных могут помочь определить входные и выходные данные для любых сценариев, которые могут прийти вам в голову, поэтому что бы ни произошло, вы будете знать, чего ожидать.

Что НЕ нужно тестировать

Чуть сложнее определить, что тестировать не нужно. Я постарался собрать список элементов, которые не нужно подвергать модульному тестированию:

Как писать модульные тесты?

Но ответить на первый вопрос (как писать код, пригодный для модульного тестирования) гораздо легче, и вряд ли ситуация сильно изменится со временем:

В заключение: модульные тесты очень важны как для разработчиков, так и для бизнеса. Их нужно писать, существуют отработанные методики, которые помогут вам легко покрыть модули тестами, в основном с помощью подготовки самих модулей. Но все эти методики не имеют смысла без знания теории тестирования, описанной в этой статье. Нужно уметь отличать модульные тесты от тестов других типов. И когда у вас в голове будет ясное понимание, то и писать тесты вам станет гораздо легче.

Источник

Обзор модульного и интеграционного тестирования Spring Boot

С чего начать мои усилия по тестированию?

Как Spring Boot может помочь мне в написании эффективных тестов?

Какие библиотеки мне использовать?

В этом блоге вы получите обзор того, как модульное и интеграционное тестирование работает со Spring Boot. Кроме того, вы узнаете, на каких функциях и библиотеках Spring следует сосредоточиться в первую очередь. Эта статья действует как агрегатор, и в нескольких местах вы найдете ссылки на другие статьи и руководства, которые более подробно объясняют концепции.

Модульное тестирование с помощью Spring Boot

Модульные тесты составляют основу вашей стратегии тестирования. Каждый проект Spring Boot, который вы запускаете с помощью Spring Initializr, имеет прочную основу для написания модульных тестов. Настраивать практически нечего, так как Spring Boot Starter Test включает в себя все необходимые строительные блоки.

Помимо включения и управления версией Spring Test, этот Spring Boot Starter включает и управляет версиями следующих библиотек:

Библиотеки проверки утверждений, такие как AssertJ, Hamcrest, JsonPath и т. Д.

В большинстве случаев ваши модульные тесты не нуждаются в какой-либо конкретной функции Spring Boot или Spring Test, поскольку они будут полагаться исключительно на JUnit и Mockito.

С помощью модульных тестов вы изолированно тестируете, например, свои *Service классы и имитируете каждого сотрудника тестируемого класса:

Как видно из раздела import тестового класса выше, Spring вообще не включается. Следовательно, вы можете применять методы и знания, полученные из модульного тестирования любого другого приложения Java.

Вот почему важно изучить основы JUnit 4/5 и Mockito, чтобы максимально использовать возможности модульного тестирования.

Для некоторых частей вашего приложения модульное тестирование не принесет особой пользы. Хорошими примерами для этого являются уровень персистентности или тестирование HTTP-клиента. Тестируя такие части вашего приложения, вы в конечном итоге почти копируете свою реализацию, поскольку вам приходится имитировать много взаимодействий с другими классами.

Лучшим подходом здесь является работа с нарезанным контекстом Spring, который можно легко автоматически настроить с помощью аннотаций теста Spring Boot.

Тесты фрагментов Spring Context

В дополнение к традиционным модульным тестам вы можете писать тесты с помощью Spring Boot, которые нацелены на определенные части (фрагменты) вашего приложения. TestContext Spring фреймворка вместе с Spring Boot адаптирует Spring контекст с достаточным количеством компонентов для конкретного теста.

Как назвать такие тесты? На мой взгляд, они не попадают на 100% в категорию модульных или интеграционных тестов. Некоторые разработчики называют их модульными тестами, потому что они тестируют, например, один контроллер изолированно. Другие разработчики относят их к интеграционным тестам, поскольку в них задействована поддержка Spring. Как бы вы их ни называли, убедитесь, что у вас есть общее понимание, по крайней мере, в вашей команде.

Все они автоматически настраивают фрагменты Spring TestContext и включают только компоненты Spring, относящиеся к тестированию определенной части вашего приложения. Я посвятил целую статью представлению наиболее распространенных из этих аннотаций и объяснению их использования.

Две наиболее важные аннотации (сначала изучите их):

Также доступны аннотации для других нишевых частей вашего приложения:

При их использовании важно понимать, какие компоненты входят в состав, TestContext а какие нет. Документация Javadoc каждой аннотации объясняет выполненную автоконфигурацию и цель.

Вы всегда можете расширить контекст автонастройки для своего теста, явно импортировав компоненты с помощью @Import или определив дополнительные компоненты Spring Beans, используя @TestConfiguration :

Вы можете найти дополнительные методы устранения потенциальных исключений NoSuchBeanDefinitionException, с которыми вы можете столкнуться при таких тестах, в этом сообщении в блоге.

Ловушка JUnit 4 и JUnit 5

Важно следить за импортом, особенно за @Test аннотацией:

С помощью JUnit 5 vintage-engine ваш набор тестов может содержать как тесты JUnit 3/4, так и JUnit Jupiter, но каждый тестовый класс может использовать только одну конкретную версию JUnit. Рассмотрите возможность миграции существующих тестов, чтобы использовать различные новые функции JUnit Jupiter (параметризованные тесты, распараллеливание, модель расширения и т. д.). Вы можете постепенно мигрировать свой набор тестов, так как вы можете запускать тесты JUnit 3/4 рядом с тестами JUnit 5.

Документация JUnit включает советы по миграции JUnit 4, а также имеются инструменты (JUnit Pioneer или эта функция IntelliJ) для автоматической миграции тестов (например, импорт или проверки утверждений).

После того, как вы мигрировали свой набор тестов на JUnit 5, важно исключить любое появление устаревшей версии JUnit. Не все в вашей команде могут постоянно обращать пристальное внимание на импорт библиотек тестирования. Чтобы избежать случайного смешивания разных версий JUnit, исключение их из вашего проекта помогает всегда выбирать правильный импорт:

Кроме Spring Boot Starter Test другие зависимости тестования также могут включать более старые версии JUnit:

Чтобы избежать (случайного) включения зависимостей JUnit 4 в будущем, вы можете использовать Maven Enforcer Plugin и определить его как запрещенную зависимость. Это приведет к сбою сборки, как только кто-то включит новую тестовую зависимость, которая транзитивно потянет JUnit 4.

Обратите внимание, что, начиная с Spring Boot 2.4.0, зависимость Spring Boot Starter Test больше не включает vintage-engine файл по умолчанию.

Интеграционные тесты с Spring Boot: @SpringBootTest

Вы можете переопределить это поведение, указав либо, DEFINE_PORT либо RANDOM_PORT :

Для интеграционных тестов, которые запускают встроенный контейнер сервлетов, вы можете затем внедрить порт своего приложения и получить к нему доступ извне, используя TestRestTemplate или WebTestClient :

Поскольку TestContext Spring фреймворка будет заполнять весь контекст приложения, вы должны убедиться, что присутствуют все зависимые компоненты инфраструктуры (например, база данных, очереди сообщений и т. д.).

Здесь в игру вступают Testcontainers. Testcontainers будет управлять жизненным циклом любого Docker контейнера для вашего теста:

Для ознакомления с Testcontainers рассмотрите следующие ресурсы:

Если ваше приложение обменивается данными с другими системами, вам нужно решение для имитации этого HTTP-взаимодействия. Это довольно часто бывает, когда вы, например, получаете данные из удаленного REST API или токенов доступа OAuth2 при запуске приложения. С помощью WireMock вы можете заглушить и подготовить HTTP-ответы для имитации удаленной системы.

Кроме того, TestContext Spring фреймворк имеет удобную функцию кеширования и повторного использования, а также уже запущенный контекст. Это может помочь сократить время сборки и значительно улучшить циклы обратной связи.

Сквозные тесты с Spring Boot

Целью сквозных (E2E) тестов является проверка системы с точки зрения пользователя. Сюда входят тесты для основных сценариев работы пользователя (например, размещение заказа или создание нового клиента). По сравнению с интеграционными тестами такие тесты обычно включают пользовательский интерфейс (если он есть).

Вы также можете выполнить тесты E2E для развернутой версии приложения, например, в среде dev или staging прежде чем приступить к развертыванию в рабочей среде.

Для приложений, которые используют рендеринг на стороне сервера (например, Thymeleaf) или автономной системы, когда серверная часть Spring Boot обслуживает интерфейс, вы можете использовать @SpringBootTest для этих тестов.

Следующий тест демонстрирует, как получить доступ и протестировать общедоступную страницу приложения Spring Boot с помощью Selenide:

Вы можете найти больше информации о Selenide в этом сообщении в блоге.

Для компонентов инфраструктуры, которые необходимо запустить для тестов E2E, Testcontainers играет большую роль. Если вам нужно запустить несколько Docker контейнеров, вам пригодится модуль Docker Compose из Testcontainers :

Резюме

Spring Boot предлагает отличную поддержку как для модульного, так и для интеграционного тестирования. Это делает тестирование первоклассным гражданином, поскольку каждый проект Spring Boot включает в себя Spring Boot Starter Test. Этот стартер подготовит ваш базовый набор инструментов для тестирования с необходимыми библиотеками тестирования.

Кроме того, аннотации Spring Boot test упрощают написание тестов для различных частей вашего приложения. Вы получите специально созданный Spring TestContext только с соответствующими Spring beans.

Чтобы познакомиться с модульными и интеграционными тестами для ваших проектов Spring Boot, рекомендуются следующие шаги:

Избегайте ловушки JUnit 4 и JUnit 5.

Ознакомьтесь с различными аннотациями тестирования Spring Boot, которые автоматически настраивают фрагменты контекста.

Узнайте, как Spring TestContext Caching может помочь сократить общее время выполнения вашего набора тестов.

Удачного модульного и интеграционного тестирования с помощью Spring Boot,

Источник

Автоматизация тестирования мобильных приложений. Часть 1: проверки, модули и базовые действия

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Приложениями Badoo и Bumble пользуются миллионы людей по всему миру, и мы стремимся доставлять им новую функциональность как можно быстрее. Но важно, чтобы высокий темп нашей работы не сказывался негативно на качестве работы приложений. В этой статье мы расскажем о роли автоматизации в наших процессах и поделимся практиками, которые позволяют быстро писать стабильные тесты.

Меня зовут Дмитрий Макаренко, я Mobile QA Engineer в Badoo и Bumble: занимаюсь тестированием новой функциональности вручную и покрытием её автотестами. В подготовке этой статьи мне помогал коллега Виктор Короневич: вместе мы делали доклад на конференции Heisenbug.

Примеры, которые мы разберём в этой статье, актуальны как для тех, кто только начинает внедрять автоматизацию тестирования в своём проекте, так и для тех, кто уже активно её использует.

Начнём с короткого рассказа о процессах тестирования и фреймворке автоматизации в нашей компании.

Место автоматизации в наших процессах

Раньше за тестирование новой функциональности у нас отвечали команды мобильного тестирования: отдельно iOS- и Android-, и проводили тесты они вручную. А создание и поддержка end-to-end-тестов (именно о них и пойдёт речь в этой статье) находились в зоне ответственности выделенной команды автоматизации. При этом ручным тестированием занимались около 30 человек, а автоматизацией — десять. Последним, конечно, было сложно всё успевать: улучшать фреймворк, инфраструктуру и автоматизировать то, что тестируют руками больше 20 человек.

За последние два года процессы сильно изменились. Сегодня релиз новой функциональности невозможен без покрытия её тестами разных уровней, в том числе end-to-end-тестами (про это можно подробнее узнать из доклада Катерины Спринсян). Их теперь у нас создают и поддерживают команды мобильного тестирования. А команда автоматизации уделяет больше времени работе с фреймворком и инфраструктурой.

Вместе с изменением процессов изменились и требования к автоматизации. Нам важно иметь возможность писать тесты быстро, чтобы не задерживать релизы. При этом тесты должны быть стабильными. Мы постоянно стремимся улучшать эти показатели, и со временем у нас сложился набор практик, которые нам в этом помогают.

Прежде чем перейти к их описанию, скажу пару слов о нашем фреймворке, чтобы контекст примеров был понятен.

Фреймворк

Наши приложения Badoo и Bumble — нативные. То есть Android-приложения разрабатываются одной командой на Kotlin и Java, а iOS- — другой командой на Swift и Objective C.

При этом функциональность Android- и iOS-приложений во многом схожа. Именно поэтому одним из главных критериев выбора фреймворка автоматизации для нас была возможность переиспользования сценариев. Руководствуясь этим, мы выбрали кросс-платформенный фреймворк для автоматизации Calabash. Мы пишем тесты на Ruby, а для написания сценариев пользуемся фреймворком Cucumber.

Неважно, какой фреймворк вы используете. Мы обобщили наши рекомендации, чтобы вы тоже могли их применять.

Практика №1. Где и как писать проверки

Чтобы понять, где можно писать проверки, рассмотрим структуру тестов. Она состоит из трёх уровней.

Первый уровень – сценарий. Здесь сам тест написан на человекочитаемом языке Gherkin, описаны все необходимые действия и проверки.

Второй уровень — определение шагов. В соответствии с действиями или проверками с первого уровня ставится Ruby-код, который их выполняет.

Третий уровень — уровень страниц. Здесь описываются экраны нашего приложения и действия, которые мы можем на них совершить — например, получить текст выбранного элемента, нажать на выбранную кнопку и т. д.

Переходим к практике. У нас есть задача: создать проверку какого-либо элемента. Это слишком общая формулировка, поэтому рассмотрим конкретный пример. Это будет проверка сообщения о пропущенном видеозвонке.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.Диалог с тестовым пользователем

Начнём со сценария для проверки этого сообщения.

В тексте сценария вы можете заметить аббревиатуру QAAPI. Это API, с помощью которого мы можем менять состояние системы во время тестирования. Например, можно отправлять сообщения или загружать фото профиля тестовым пользователям, используя обычные клиент-серверные запросы. Более подробно про QAAPI мы рассказывали в этой статье и докладе.

Сфокусируемся на шаге для проверки сообщения (последний шаг в примере кода).

Определим, что нам необходимо проверить. Это текст сообщения и кнопка «Перезвонить». Разберём первый возможный подход.

В этом примере на уровне определения шагов мы создаём объект класса ChatPage и вызываем метод await для ожидания загрузки нужного экрана. Потом вызываем метод verify_missed_video_call, чтобы проверить отображение необходимых элементов.

На уровне страницы реализация этого метода выглядит следующим образом. Сначала мы формируем ожидаемый результат лексемы. Его мы берём из статического метода, объявленного в модуле CallLexemes, используя class как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.Диалог с тестовым пользователем

Зону диалога мы разделили на модули поменьше, например для разных типов сообщений: текстовых, аудио, GIF-картинок и фото.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.Диалог с тестовым пользователем

Модуль поля ввода также состоит из более мелких модулей, таких как поля для отправки фотографий, текста, GIF-картинок и аудиосообщений.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.Диалог с тестовым пользователем

После этого мы создали структуру модулей, подобную той, которую вы видите на скриншоте ниже, для Android и для iOS.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

После этого нам стало легче создать классы страниц чата в обоих приложениях. По сути, единственное различие заключается в использовании разных базовых страниц, потому что у приложений они немного отличаются.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader. как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Теперь мы просто подключаем к странице каждого приложения необходимые модули. Причём речь идёт только об актуальных для приложения модулей. В Badoo, например, это может быть сообщение о подарке, которого нет в Bumble:

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Зато в Bumble есть другой тип сообщений, которого нет в Badoo, — реакции:

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Наличие такого компонента позволит нам создать страницу чата в любом другом приложении, если оно появится в нашей компании, буквально за пару минут.

Для обоих приложений мы также используем одни и те же шаги. Здесь мы возвращаемся к методам получения текста сообщения о пропущенном видеозвонке и кнопки «Перезвонить». Они находятся в модуле для типа сообщения о видеозвонке.

Этот модуль подключается как для Bumble, так и для Badoo. То есть он написан один раз для каждой из платформ, а проверить сообщение в четырёх наших приложениях (Badoo для iOS и Android и Bumble для iOS и Android) можно с использованием всего одного шага. Так что написать новые тесты для проверки чата в разных приложениях не составляет большого труда.

Мы создаём подобные компоненты и в тех случаях, когда нам не требуется их переиспользовать в разных приложениях, например для экранов с большим количеством UI-элементов. Такой подход в одном приложении позволяет избежать появления в коде так называемых God objects (больше информации здесь и здесь) классов с большим количеством свойств и методов. Поддерживать разбитые на модули страницы гораздо проще, так же как расширять их с появлением новой функциональности.

Подводя итоги этого примера, отметим, что использование компонентов помогает нам:

создавать тесты для разных приложений, используя уже существующие шаги, и экономить на этом много времени;

поддерживать и расширять классы страниц для экранов с большим количеством UI-элементов

Обобщённая рекомендация: для объектов с большим количеством свойств и методов создавать компоненты, состоящие из логически разделённых модулей.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Практика №3. Шаги для базовых действий

Начнём разбирать новый пример с того, что обозначим, какие действия мы считаем базовыми. Это, например, ожидание открытия страницы, верификация страницы, закрытие страницы или переход назад с какой-либо страницы. Мы называем их базовыми, потому что они актуальны практически для любой страницы наших приложений.

Задача, решение которой мы будем рассматривать: реализовать базовые действия для разных страниц.

Представим ситуацию: два тестировщика создали шаги для ожидания открытия страниц чата и профиля:

Мы видим здесь следующие проблемы:

шаги называются немного по-разному, поэтому их сложно будет найти, когда нам понадобится использовать их в новых сценариях;

реализация шагов отличается только классами объектов: ChatPage и OwnProfile. Учитывая, что экранов в наших приложениях намного больше, чем два, создание разных шагов для ожидания открытия каждого из них приведёт к дубликации большого количества кода.

Рассмотрим ещё пример с реализацией шагов для перехода назад с какой-либо страницы:

Тут можно заметить ещё одну проблему: на страницах появились методы (tap_back, go_back, press_back), которые отвечают за одно и то же действие, но называются по-разному. Это произошло потому, что разные люди добавили их в разные места репозитория.

Таким образом, общая проблема этих примеров — дубликация кода, которая существенно замедляет разработку тестов. Мы видим дублирование как в самих шагах, так и в реализации действий на страницах. Это затрудняет переиспользование шагов для базовых действий в разных тестах, так как запомнить все возможные вариации таких шагов практически невозможно.

Как решить эту проблему? Перейдём от простого подхода к более сложному, общему. Мы можем создать объект класса страницы, используя строку из параметра шага. Для этого мы сделали метод page_object_by.

Реализация метода page_object_by выглядит следующим образом:

Мы формируем имя класса из названия страницы, переданного в шаги. Потом, если у нас такой класс описан, то возвращаем объект этого класса. В противном случае — выбрасываем ошибку.

Таким образом, для ожидания открытия любой страницы нам нужно написать всего один шаг. Аналогичный подход мы используем и для всех остальных базовых действий. И это сильно упрощает разработку.

От дубликации методов для базовых действий на страницах мы также избавились, выделив общие методы, например press_back.

Реализация этого метода находится на страницах AndroidBumbleBase, IOSBumbleBase, AndroidBadooBase и IOSBadooBase, от которых наследуются классы остальных страниц в наших тестах. Стоит отметить, что это не совсем правильно. При таком подходе страницы, на которых нет кнопки «Назад», могут использовать метод нажатия на эту кнопку. Правильнее было бы выделить нажатие на кнопку «Назад» в отдельный модуль, например Navigation::Back, и добавить его на все необходимые страницы. Но мы не использовали подобный модуль, потому что нам пришлось бы добавлять его практически на все страницы в нашем проекте, — мы решили немного упростить себе жизнь.

Итак, в контексте этого примера мы рекомендуем:

создавать общие шаги для базовых действий;

создавать общие методы для реализации базовых действий на страницах (переход назад и т. д.).

В прошлом разделе мы рекомендовали создавать модули и переиспользовать их на страницах. А здесь говорим, что надо создавать методы на страницах. Может показаться, что мы немного противоречим сами себе. Но это не так.

Если у вас действительно много методов на странице или если вам нужно переиспользовать код лишь на некоторых страницах, имеет смысл выделить модули и добавить их на необходимые страницы.

Если же у вас есть действие, актуальное для всех страниц, следует выделить его в отдельный метод и определить в классе, являющемся основой для всех страниц в ваших тестах.

Обобщённая рекомендация: если у вас много однотипного кода, выделяйте общие методы.

как разбить приложение на модули для тестирования. image loader. как разбить приложение на модули для тестирования фото. как разбить приложение на модули для тестирования-image loader. картинка как разбить приложение на модули для тестирования. картинка image loader.

Эта рекомендация может показаться очевидной, но мы хотим отметить важность её применения. Напомню, что у нас около 40 человек активно занимаются разработкой end-to-end-тестов. Нам было важно с самого начала выбрать правильный подход, чтобы избежать рефакторинга огромного количества однотипных шагов и методов в будущем.

Что мы узнали

Мы рассмотрели три примера решения различных задач, возникающих при создании автотестов. На их основании мы сформулировали следующие обобщенные рекомендации:

выделяйте общие методы для переиспользования однотипного кода — как в шагах, так и в методах на страницах;

создавайте проверки на самом высоком уровне — там, где вы пишете тело теста;

делайте объект тестирования простым;

создавайте компоненты, состоящие из логически разделённых модулей, для объектов с большим количеством свойств и методов.

Возможно, эти советы кому-то покажутся очевидными. Но мы хотим обратить ваше внимание на то, что применять их можно (и нужно) в разных ситуациях.

Во второй части статьи мы разберём ещё четыре примера решения других задач, дополним список наших рекомендаций и поделимся доступом к тестовому проекту со всеми практиками. Оставайтесь с нами!

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *