Найти тему

Что такое Page Object в Intellij IDEA JAVA и для чего он нужен?

Оглавление

В предыдущих статьях мы рассматривали подготовку к тестированию: что нужно сделать до начала тестов и после них, а также как сформировать отчёт о результатах тестирования. Обсудили различные виды аннотаций для тестов. Теперь постепенно переходим к основной теме — созданию тестов. Паттерн Page Object играет ключевую роль в процессе тестирования, и в этой статье мы объясним, почему это так важно.

Для чего нужен Page Object

Мы уже написали пару тестов с открытием браузера и вводом в поисковую строку запроса. Разберём на этом примере:

-2

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

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

Этот паттерн предполагает представление страниц (или экранов в мобильных приложениях) веб-приложения в виде отдельных классов, следуя принципам объектно-ориентированного программирования. Каждый класс экрана включает в себя:

  • поля, содержащие информацию о том, что экран «знает»;
  • методы, описывающие действия, которые экран «умеет» выполнять.

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

Важно отметить, что паттерн Page Object можно применять различными способами, в том числе создавая методы для конкретных локаторов. Рассмотрим это на примере.

Создание классов в Page Object

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

Для этого наследуемся от нашего абстрактного класса, где инициализируются нужные данные, в том числе driver.

Используем класс PageFactory, который предоставляет аннотации для удобного создания объектов страниц (Page Objects). Преимущество заключается в том, что все веб-элементы страницы объявляются как WebElement, а не через селектор, полями класса.

Инициализация происходит «лениво» (lazy initialization), то есть непосредственно в момент обращения к элементу. Это позволяет не беспокоиться об ElementNotFoundException, если на момент инициализации класса страницы некоторые элементы отсутствуют на экране.

-3

Далее во всех созданных классах нужно будет прописывать:

-4

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

Использование PageObject в тестах

1 вариант

Мы каждый раз создаём ссылку на наш класс:

-5

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

2 вариант

Мы создаём методы для наших локаторов, прописывая за ранее, что они будут делать:

-6

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

-7

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

3 вариант

Создаём ссылку на наш класс и даём ему название:

-8

Я считаю, что этот подход является оптимальным по нескольким причинам.

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

WebElement не всегда удобно

Помимо WebElement, вы можете сразу создать локатор и поместить его в переменную типа By. Это позволит вам обращаться к элементам страницы, используя заранее определённые локаторы.

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

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

Используя явные ожидания, мы можем контролировать время ожидания появления элемента и предотвратить падение теста из-за непредвиденных задержек.

-9

Время это максимальное время ожидания, то есть мы ждём 20 секунд появления элемента, если не появился кидаем в ошибку.

В тесте это будет выглядеть так:

-10

Но наш локатор SearchBar - это WebElement, поэтому будет ошибка. То есть нам нужно указать так:

wait.until(visibilityOfElementLocated(By.xpath("//input[@placeholder='найдётся всё']")));

Не совсем корректно, ведь мы создали PageObject, так что не используем локаторы в самом тесте.

  • visibilityOfElementLocated - подождать пока элемент появится
  • invisibilityOfElementLocated - подождать пока элемент пропадёт

Поэтому создаём переменную By и указываем нужный локатор:

-11

В тесте теперь это выглядит так:

-12

Методы и их использование

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

-13

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

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

Метод ClickElement будет сочетать в себе ожидание появления элемента и его последующее нажатие. Он сначала ждёт появления элемента, затем показывает его, немного ждёт (например, 1200 миллисекунд) и только после этого нажимает на элемент.

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

-14

И в итоге наш тест преобразился:

-15

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

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

Обучение тестированию