Зарегистрируйтесь, чтобы продолжить обучение

Page Object Models Тестирование с Playwright

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

Для решения этой задачи придумано несколько решений, одно из которых называется Page Object Pattern. Его плюсом является универсальность, оно не завязано на конкретный фреймворк и может применяться везде.

Page Object Pattern (POP) — это шаблон проектирования, который используется для создания абстракции веб-страницы в виде объектов в коде теста. Каждый объект страницы представляет собой отдельную веб-страницу или компонент, инкапсулируя взаимодействия с элементами пользовательского интерфейса. Это позволяет сделать тесты более модульными и переиспользуемыми.

Основные характеристики Page Object Pattern:

  • Инкапсуляция: Все взаимодействия с элементами страницы (например, клики, ввод текста) инкапсулированы в одном классе, который представляет эту страницу.
  • Переиспользуемость: Один и тот же объект страницы может быть использован в нескольких тестах, что снижает дублирование. При изменении интерфейса веб-страницы необходимо обновить только соответствующий объект страницы, а не все тесты, что значительно упрощает поддержку.
  • Читаемость: Тесты становятся более читаемыми, так как высокоуровневые операции (например, "вход в систему") абстрагированы от низкоуровневых взаимодействий с элементами страницы.

Использование POP в Playwright не требует никаких специальных инструментов. Достаточно создать класс, который выставляет наружу методы, скрывающие работу с объектом page для данной страницы.

Преобразуем наш тест с использованием POP. Исходный тест:

test('test', async ({ page }) => {
  await page.goto('https://demo.playwright.dev/todomvc/')
  const input = page.getByPlaceholder('What needs to be done?')

  const taskName = 'Finish Hexlet\'s course'
  await input.fill(taskName)
  await input.press('Enter')

  await input.fill('second todo')
  await input.press('Enter')

  const item = page.getByTestId('todo-title').filter({ hasText: taskName })
  await expect(item).toBeVisible()
})

Для начала выделим класс, который описывает страницу. Его можно расположить например рядом с папкой тестов, внутри models/TodoMVCPage.js.

import { Page } from '@playwright/test'

export default class TodoMVCPage {
  /**
   * @param {Page} page
   */
  constructor(page) {
    this.page = page
    // Описываем нужные локаторы
    // Так как реальный поиск происходит во время использования,
    // то мы можем без проблем задать все нужные локаторы прямо в конструкторе
    this.inputForNewTodo = page.getByPlaceholder('What needs to be done?')
  }

  async goto() {
    await this.page.goto('https://demo.playwright.dev/todomvc/')
  }

  getTaskItemByName(taskName) {
    return this.page.getByTestId('todo-title').filter({ hasText: taskName })
  }

  async addTodo(text) {
    await this.inputForNewTodo.fill(text)
    await this.inputForNewTodo.press('Enter')
  }
}

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

И сам тест:

test('test', async ({ page }) => {
  const todoMvcPage = new TodoMVCPage(page)
  await todoMvcPage.goto()

  const taskName = 'Finish Hexlet\'s course'
  await todoMvcPage.addTodo(taskName)
  await todoMvcPage.addTodo('second todo')
  const item = todoMvcPage.getTaskItemByName(taskName)
  await expect(item).toBeVisible()
})

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


Дополнительные материалы

  1. playwright.dev

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff