page object что это
Несколько советов по созданию page object классов здорового человека
И снова здравствуйте. В преддверии старта курса «Java QA Engineer» подготовили перевод еще одной полезной статьи.
Это начало нового года, и многие люди во всем мире принимают решение уделять больше внимания своему здоровью. Это прекрасно! На самом деле, ваши тесты для фронтенда также нуждаются в таком решении.
Самым популярным паттерном проектирования, используемым в кодовых базах тестирования веб-UI, является паттерн Page Object Model (POM). Этот паттерн предполагает моделирование класса для представления одной страницы тестируемой системы. На основе этой модели, класс будет содержать свойства, которые представляют элементы страницы пользовательского интерфейса и методы, которые взаимодействуют с этими элементами.
Взяв за пример эту страницу входа в наше приложение, давайте обсудим советы по созданию класса с использованием POM.
Класс
Мы создаем единственный класс в нашей среде автоматизации для представления этой страницы. Рекомендуется убедиться, что имя класса соответствует странице в приложении, чтобы другие разработчики могли быстро найти класс, связанный с данной страницей пользовательского интерфейса.
Итак, в этом примере мы создадим класс с именем LoginPage.
Свойства
LoginPage должен содержать свойства для каждого из элементов на странице, которые будут использоваться в ваших тестах. Значения этих свойств являются указателями на элементы на реальной странице. Определяя эти локаторы в одном месте, вам не нужно будет хардкодить их в каждом месте, где вы их используете — таким образом, устраняя дублирование.
Методы
В дополнение к свойствам, класс должен также содержать методы, позволяющие тесту взаимодействовать с приложением, такие как заполнение полей ввода и нажатие кнопок. Вот несколько советов по разработке этих методов для оптимального использования в ваших тестах.
Добавьте геттеры и сеттеры
Целью POM классов является установка (set) и получение (get) состояния вашего приложения.Так что вам понадобятся соответствующие методы для этого.
Например, нам обязательно нужно установить поля username и password, поэтому необходимо добавить для них сеттеры.
Добавляйте только то, что нужно в настоящее время
Обратите внимание, мы не добавляли геттеры и сеттеры для каждого поля, потому что они не нужны нам в наших тестах. Добавляйте только то, что нужно в данный момент. Вы всегда можете добавить больше, если это потребуется для нового теста. Это избавит вас от необходимости поддерживать неиспользуемый код.
Переходы должны возвращать новые объекты
Вам также понадобятся методы для нажатия кнопок и ссылок. Однако, когда ваш клик приводит к смене страницы, ваш метод должен возвращать дескриптор класса, представляющего страницу пользовательского интерфейса, на которую вы перешли.
Например, если нажатие кнопки входа ведет к главной странице вашего приложения, тогда ваш метод должен вернуть дескриптор класса, представляющего эту главной страницу.
Благодаря поддержке данной рекомендации, все вызывающие тесты будут знать, что при вызове этого метода произойдет переход, и у теста есть дескриптор необходимого объекта для продолжения взаимодействия с приложением.
Не бойтесь создавать методы для удобства
Прямо сейчас для входа в приложение потребуется вызвать как минимум три метода (setUsername, setPassword и clickSignInButton). Поскольку они обычно используются вместе, имеет смысл предоставить в вашем классе удобный метод входа, чтобы ваши тесты могли вызывать только один метод.
Обратите внимание, что мы не реализовали логику в этом методе, а вместо этого просто вызвали отдельные методы. Важно, чтобы эти методы были доступны по отдельности, чтобы их можно было использовать в негативном тестировании (например, установить имя пользователя, но не пароль).
Учитывайте состояния
Для чекбокс-элементов (или других переключателей) простое нажатие на них может не соответствовать желаемому замыслу теста. Например, что если ваш тест хочет, чтобы чекбокс был установлен, но он уже установлен? Вызов метода клика в таком случае даст вам противоположный результат. Вместо этого сделайте свой метод более сложным, внедрив логику, которая будет ставить флажок только в том случае, если именно такой результат необходим пользователю. Чтобы сделать это, вместо слепого клика, примите аргумент, который указывает намерение (т. е. нам нужно, чтобы он был выбран или нет) и действовал соответственно.
Сохраняйте нейтральность POM классов
Ваш POM класс должен быть нейтральным объектом, который взаимодействует и собирает информацию о вашем приложении. Постарайтесь, чтобы ваши методы были нейтральными и убедитесь, что они достаточно универсальны, чтобы их можно было использовать в любом тесте, который хочет взаимодействовать со страницей. Это означает, что в эти методы не должны входить утверждения.
Например, что если наш метод, который получает сообщение об ошибке, также не проходит тест, если сообщение является видимым?
Я не могу повторно использовать этот метод для тестов, в которых я хочу убедиться, что отображается сообщение об ошибке, если имя пользователя или пароль неверны или не указаны. Это связано с тем, что POM класс взял на себя задачу определить, что отображение сообщения об ошибке является ошибкой; в то время как в этих случаях это не так. Вместо этого просто верните состояние и позвольте тесту определить, что оно означает.
Здоровый код предшествует здоровым тестам
Эти советы должны помочь вам разработать хорошие работоспособные классы, реализующие паттерн проектирования Page Object Model. Использование этого паттерна способствует разделению полномочий (например, тесты и управлением состоянием), уменьшает дублирование кода и предоставляет повторно используемые методы. Удачного тестирования!
Приглашаем всех на бесплатный вебинар, в рамках которого вы узнаете все подробности о курсе. А также мы займемся практикой и соберем из подручных средств заглушку для третьей системы и поговорим, как ее адаптировать для целей тестирования.
Автоматизируем UI-тесты Android приложения с использование паттерна Page Object
Паттерн Page Object появился в тестировании web и очень хорошо себя там зарекомендовал. Когда я начал автоматизировать тесты для android приложения, то первым делом подумал про него. Поискал информацию в сети, поспрашивал коллег и, в принципе, не нашел доводов не попробовать. Предлагаю посмотреть, что из этого вышло.
Классический Page Object подразумевает два уровня абстракции: элементы страницы и тесты. Я выделяю еще один — бизнес-логика. Отмечу, что то, как вы построите ваш фреймворк, будет очень сильно влиять на простоту написания тестов в будущем, а так же на их поддержку. Я стараюсь делать так, чтобы код теста выглядел как будто это обычный тест-кейс, написанный рядовым тестером. Т.е. начинаю с конца:
Итак, входные данные:
Подготовка проекта
Слой тестов
Как писал выше, будем автоматизировать тест на логин в приложении. Помним, что код должен выглядеть так же, как обычный тест-кейс:
Precondition: запустить приложение.
Step 1: осуществить логин под учетной записью myLogin/myPassword.
Step 2: проверить имя текущего пользователя.
Expected Result: текущий пользователь «Иванов Иван».
Небольшой дисклеймер: согласно лучшим практикам тест дизайна, в предусловии нужно создать/найти учетную запись. Я этот момент опустил для простоты примера.
Наш класс будет выглядеть так:
Бизнес-логика
У экземпляра нашего класса будет две переменные:
Замечание: запуск приложения через android.content.Context.getTargetContext() подходит только в том случае, если ваши тесты в одном проекте с самим приложением. Если отдельно, то необходимо будет запускать через меню.
Бизнес-логика теста — это конкретные шаги, которые должен совершить пользователь для получения какого-либо значимого (для пользователя) результата. Осуществление входа под своей УЗ — значимый результат. Шаги: клик на кнопку «Login», ввести имя пользователя в поле «Login», ввести пароль в поле «Password», кликнуть на кнопку «Sign In». Таким образом, наш метод наполняется шагами:
Для получения текущего пользователя все проще, просто получаем значение поля:
А для закрытия приложения просто нажмем на кнопку Home:
Описание элементов страницы
Концепция данного слоя — он должен возвращать готовые к использованию элементы (в нашем контексте это класс android.support.test.uiautomator.UiObject2 ). Т. е., потребитель не должен переживать на счет состояния объекта, если он вернулся, то с ним сразу же можно взаимодействовать: кликать, заполнять или считывать текст. Отсюда важное следствие — в этом слое будем реализовывать ожидания:
Инспекцию интерфейса удобно производить в утилите uiautomatorviewer, входящей в пакет tools (устанавливали в разделе Подготовка):
Запуск тестов
На этом все, осталось запустить. Для начала подключаемся к устройству или стартуем эмулятор. Проверим подключение командой adb devices (утилита adb входит в состав platform-tools):
Если у вас gradle, то далее делаем
и наслаждаемся как «вкалывают роботы, а не человек» (с).
Революция или эволюция Page Object Model?
Всем привет! Меня зовут Артём Соковец. Хочу поделиться переводом своей статьи об Atlas: реинкарнации фреймворка HTML Elements, где представлен совершенно иной подход работы с Page Object.
Перед тем, как перейти к деталям, хочу спросить: сколько обёрток для Page Object вы знаете? Page Element, ScreenPlay, Loadable Component, Chain of invocations…
А что будет, если взять Page Object с реализацией на интерфейсе, прикрутить Proxy Pattern и добавить немного функциональности Java 8?
Если интересно, предлагаю перейти под кат.
Введение
При использовании стандартного шаблона проектирования PageObject возникает ряд проблем:
Здесь блок Header используется в различных классах PageObject.
Отсутствие параметризации у элементов
В этом примере описываются элементы страницы редактирования настроек пользователя. Два элемента TextBlock содержат практически идентичный локатор с разницей только в текстовом значении («Text_1» и «Text_2»).
В повседневной работе можно встретить Page Object, состоящие из множества строк кода с однотипными элементами. В дальнейшем такие классы «неудобно» поддерживать.
Большой класс с шагами (steps)
Со временем разрастается класс шагов для работы с элементами. Требуется более пристальное внимание, чтобы не было дубликатов методов.
Ваш путеводитель в мире Page Object
Реинкарнация фреймворка HTML Elements направлена на решение вышеописанных проблем, уменьшение количество строк кода тестового проекта, более продуманную работу со списками и ожиданиями, а также тонкую настройку инструмента под себя благодаря системе расширений.
Atlas — Java-фреймворк нового поколения для разработки UI-автотестов с реализацией паттерна Page Object через интерфейсы. Данный подход предоставляет возможность множественного наследования при построении дерева элементов, что в итоге обеспечивает лаконичный код ваших автотестов.
Основным нововведением фреймворка является использование интерфейсов вместо стандартных классов.
Вот так выглядит описание главной страницы github.com:
В приведённом коде описывается главная страница сайта GitHub с одним элементом и множественным наследованием от слоёв WebPage и WithHeader (пример дан исключительно для учебных целей, поэтому большинство веб-элементов опущено).
Архитектура фреймворка
На текущий момент Atlas состоит из трёх модулей:
Два других модуля atlas-webdriver и atlas-appium используются для разработки автоматизированных скриптов UI web и UI mobile. Основной точкой входа для описания web-страниц является интерфейс WebPage, а для мобильных экранов — Screen. Концептуально atlas-webdriver и atlas-appium построены на расширениях (пакет *.extension).
Элементы
В поставке инструмента идут два специализированных класса для работы с UI-элементами (аналог класса WebElement).
AtlasWebElement и AtlasMobileElement дополнены методами should и waitUntil. (рассмотрение данных методов будет далее в статье).
Инструмент предоставляет возможность создания своих компонентов с помощью расширения вышеуказанных классов, что позволяет создать кроссплатформенный элемент.
Основные возможности
Рассмотрим подробнее функциональность инструмента:
Интерфейсы вместо классов
При описании стандартных PageObject используются интерфейсы вместо классов.
В данном примере описывается ссылка на стартовой странице GitHub.
Представим, что у нас есть форма с полями:
Чтобы её описать, требуется создать 11 переменных с аннотацией @FindBy и, при необходимости, объявить getter.
Используя Atlas, потребуется лишь один параметризованный элемент AtlasWebElement.
Код автоматизированного теста выглядит следующим образом:
Обращаемся к нужной странице, вызываем метод с параметром и выполняем требуемые действия с элементом. Метод с параметром описывает конкретное поле.
Ранее упоминалось, что блок (например, Header), который используется в разных Page Object — это дублирование кода.
Есть header GitHub.
Опишем данный блок (большинство веб-элементов опущено):
Далее создадим слой, который можно подключить к любой странице:
Расширяем главную страницу блоком header.
В целом можно создать больше слоёв и подключить их к нужной странице. В примере ниже подключаем с главной странице слои header, footer, sidebar.
Пойдём дальше. Header содержит 4 кнопки, 3 выпадающих меню и одно поле поиска:
Создадим собственный элемент Button, и одним элементом опишем четыре кнопки.
Подключим кнопку button к слою header. Таким образом расширим функциональность шапки GitHub.
Отдельный элемент Button можно подключать к различным слоям веб-сайта и быстро получить на нужной странице требуемый элемент.
Во второй строке теста происходит обращение к шапке сайта, далее вызываем параметризированную кнопку со значением «Pricing» и выполняем клик.
На тестируемом сайте может быть довольно много элементов, которые повторяются от страницы к странице. Чтобы не описывать их все с помощью стандартного подхода Page Object, можно описать их один раз и подключать там, где требуется. Экономия времени и количества строк кода налицо.
Методы по умолчанию
В Java 8 появились методы по умолчанию, которые используются, чтобы заранее определить нужную функциональность.
Допустим, у нас есть «вредный» элемент: например, чекбокс, который то включен, то выключен. Через него проходит много сценариев. Требуется включать чекбокс, если он выключен:
Чтобы не хранить весь этот код в классе шагов, возможно поместить его рядом с элементом в виде метода по умолчанию.
Теперь шаг в тесте будет выглядеть так:
Другой пример, в котором требуется совместить очистку и ввод символов в поле.
Определим метод, который очищает поле и возвращает сам элемент:
В тестовом методе шаг выглядит следующим образом:
Таким образом можно запрограммировать требуемое поведение в элементе.
Повторные попытки (Retry)
В Atlas есть встроенные повторные попытки. Вам не нужно заботиться о таких исключениях, как NotFoundException, StaleElementReferenceException и WebDriverException, а также можно забыть о применении явных и неявных ожиданий Selenium API.
Если на каком-то этапе цепочки вы поймали исключение, фаза повторяется с начала.
Есть возможность самостоятельно настраивать интервал времени, в течение которого можно выполнять повторение, или частоту повторения.
Ожидаем в течение трёх секунд c частотой опроса раз в секунду.
Также можем настроить ожидание для конкретного элемента с помощью аннотации Retry. Для всех элементов поиск будет происходить в течение 3 секунд, а в случае с одним составит 20.
Работа со списками
Из коробки инструмент предоставляет работу со списками. Что это значит? Есть поле с тегом input, куда вводим текст, далее появляется выпадающий список, элементы появляются не сразу.
Для таких случаев есть сущность ElementsCollection. С её помощью происходит работа со списками.
Также есть возможность фильтровать элементы и конвертировать их в список другого вида.
Как ранее упоминалось, в сущностях AtlasWebElement и AtlasMobileElement используются методы should, waitUntil для работы с проверками (утверждениями).
Метод | Описание |
---|---|
should(…) | Выполняет различные утверждения (проверки) с элементом. Бросает AssertionError |
waitUntil(…) | Выполняет различные утверждения (проверки) с элементом. Бросает RuntimeException |
Для чего это сделано? Чтобы сэкономить время при разборе отчётов прогона автоматизированных сценариев. Большинство функциональных проверок выполняются в конце сценария: они интересны специалисту функционального тестирования, а промежуточные проверки – специалисту автоматизированного тестирования. Следовательно, если функциональность продукта не работает, логично бросать исключение AssertationError, в ином случае — RuntimeException.
В Allure сразу будет видно, с чем мы имеем дело: либо у нас дефект продукта (в работу берёт специалист ФТ), либо сломался автотест (разбирается специалист АТ).
У пользователя есть возможность переопределить базовый функционал инструмента либо внедрить свой функционал. Модель расширения Atlas похожа на модель расширения JUnit 5. Модули atlas-webdriver и atlas-appium построены на расширениях. Если вам интересно, посмотрите исходный код.
Разберём абстрактный пример: требуется разработать UI-автотесты для браузера Internet Explorer 11 (кое-где он ещё используется). Бывают моменты, когда стандартный клик по элементам не отрабатывает, тогда можно воспользоваться JS-кликом. Вы решаете на время переопределить клик на всём тестовом проекте.
Создаём расширение, которое реализует интерфейс MethodExtension.
Переопределяем два метода. В методе test() задаём, что переопределяем метод click. Метод invoke реализует требуемую логику. Теперь клик по элементу будет происходить через JavaScript.
Подключаем расширение следующим образом:
С помощью расширений возможно создать поиск локаторов для элементов в БД и реализовать другие интересные возможности — всё зависит от вашей фантазии и потребностей.
Единая точка входа к PageObject’ам (WebSite)
Инструмент позволяет хранить все ваши Pages в одном месте и в дальнейшем работать только через сущность Site.
Дополнительно Page’ам возможно задавать быстрый url, query-параметры и path-сегменты.
В строчке выше передаются два path-сегмента (qameta и atlas), что преобразовывается в адрес github.com/qameta/atlas/tree/master. Основное преимущество такого подхода в том, что возможно сразу открыть требуемую страницу без прокликивания до неё.
Работа с мобильным элементом
Работа с мобильным элементом (AtlasMobileElement) происходит аналогично работе с веб-элементом AtlasWebElement. Дополнительно в AtlasMobileElement добавлены три метода: скролл экрана вверх/вниз (scrollUp/scrollDown) и клик на элемент с удержанием (longPress).
Приведу пример главного экрана приложения Wikipedia. Один элемент описывается как для платформы iOS, так и для Android. Также описывают параметризованную кнопку.
Тесты выглядят аналогичным образом:
В примере выше мы открываем главную страницу Wikipedia, щёлкаем по поисковой строке, вводим текст Atlas, далее прокручиваем до элемента списка со значением Atlas LV-3B и переходим в его представление. Последняя строчка проверяет, что заголовок отображается и содержит требуемое значение.
Логирование событий возможно реализовать с помощью специального листенера (интерфейс Listener). Каждый метод при вызове имеет четыре события: Before, Pass, Fail. After.
Используя данный интерфейс, можно организовать отчётность. Ниже представлен пример Allure Listener, который можно найти по ссылке.
Далее подключаем слушатель при инициализации класса Atlas.
Вышеуказанным способом возможно создать listener для различных систем репортинга (например, для ReportPortal).
Подключение
Для автоматизации UI web достаточно прописать зависимость atlas-webdriver и указать последнюю актуальную версию (на момент написания этого текста актуальна версия 1.6.0).
Аналогичным образом поступаем, если требуется автоматизировать UI Mobile.
Использование
После подключения зависимости в свой проект необходимо инициализировать инстанс класса Atlas.
В конструктор Atlas передаем инстанс конфигураци, а также драйвер.
На текущий момент есть две конфигурации: WebDriverConfiguration и AppiumDriverConfiguration. Каждая конфигурация содержит определенные расширения по умолчанию.
Далее определим метод, который будет создавать все PageObject.
Пример простенького тестового сценария:
Открываем сайт, обращаемся к слою header, в нём ищем текстовое поле (search input), вводим текст и нажимаем ввод.
Итоги
В заключение хочу отметить, что Atlas — это гибкий инструмент с большими возможностями. Его можно настроить под конкретный тестовый проект так, как удобно вашей команде и вам. Заняться разработкой кроссплатформенных тестов и т.д.
Доступны видеозаписи докладов о нём с конференций Heisenbug, Selenium Camp и Nexign QA Meetup. Есть Telegram-чат @atlashelp.
С помощью данного инструмента вы сможете сократить значительное количество строк кода (проверено на проектах таких компаний, как Яндекс, СберТех и Тинькофф).
Page Object — путь к совершенным автотестам
Всем, доброго времени суток!
Этот топик о том как мы тестируем веб-интерфейс нашего продукта Plus1 WapStart. Мы используем Page Object, т.к. этот паттерн имеет много общего с реальными задачами и позволяет писать автотесты простыми для чтения и понимания.
Что такое Page Object
Установка Ruby и gems
Для запуска примеров понадобиться последняя версия Ruby и gems:
Hello, Page Object!
Создаем RegistrationPage для страницы регистрации — для этого включаем модуль PageObject, указываем адрес страницы и описываем элементы:
На странице описаны шесть методов, каждый из которых дополнительно сгенерирует еще несколько, об этом далее… Добавляем данные по умолчанию:
Создаем метод для заполнения только обязательных полей:
Все базовые page objects определены, используем их в автотесте. Выберем драйвер selenium-webdriver, передав его в конструктор PageObject:
Аргумент true открывает page_url, если мы попадаем на эту страницу кликом по ссылке, то его можно не передавать. Запустим пример:
Таким образом в автотестах уходим от использования find_element и локаторов, код легко читаемый и повторно используемый.
Динамическая генерация методов доступа к элементам страницы
Accessors — методы класса, добавленные на страницу, подключением модуля PageObject. Методы генерируют еще один набор методов, которые обеспечивают доступ к элементам веб-страницы:
Пример полностью описанной страницы регистрации:
Пример автотеста для проверки валидности партнерского кода: