Python: Selenium
Теория: Page Object Model
Когда тестов становится много, каждая строчка find_element() превращается в потенциальную проблему. В один день разработчик меняет селектор — и десятки тестов падают. Чтобы избежать этого, применяют Page Object Model (POM) — архитектуру, где каждая страница сайта оформляется как отдельный класс.
Зачем нужен Page Object
Вместо того чтобы писать в тесте «найди элемент, кликни, введи текст», тест обращается к методам страницы:
а не
Теперь тест не зависит от конкретных локаторов. Если селектор изменился — правится только класс страницы, а не все тесты.
Структура проекта с POM
pages/— это библиотека, где каждая страница сайта — отдельный класс.base_page.py— хранит общие методы для всех страниц.login_page.py— описывает конкретные элементы и действия.
Базовый класс страницы
Базовый класс хранит все общие операции: открытие страницы, ввод текста, клик, получение текста. Теперь каждая конкретная страница наследует этот класс и добавляет свои локаторы.
Пример страницы авторизации
Каждый метод отражает одно действие пользователя. Если завтра на кнопке изменится CSS-селектор, правится только SUBMIT в этом файле — тесты трогать не нужно.
Тест с Page Object
## Пример с ошибочным входом
Тот же класс, другой сценарий. Страница одна, тестов может быть сколько угодно.
Расширение модели
Когда страниц становится много, проект растёт как библиотека. Например:
Можно выделять не только страницы, но и компоненты — например, шапку, меню, фильтр. Компонент — это тоже класс, который знает только свой кусок интерфейса.
Компонент можно использовать внутри других страниц — как конструктор.
Преимущества POM
- Чистый код. В тестах нет «find_element» — только логика действий.
- Минимум дублирования. Если локатор изменился, правится один файл.
- Переиспользование. Одинаковые блоки сайта можно описать один раз и использовать в разных тестах.
Вынесение локаторов и действий
Когда проект растёт, даже с Page Object Model внутри классов страниц начинает скапливаться слишком много деталей: десятки локаторов и вспомогательных методов. Чтобы не превращать каждый Page Object в «простыню» на сотни строк, код делят на более мелкие логические части: локаторы и действия (actions).
Идея простая:
- Локаторы — это описание элементов интерфейса (кнопки, поля, баннеры). Они не содержат логики, только селекторы.
- Действия — это шаги пользователя (ввести логин, нажать «отправить», выйти из аккаунта).
Пример структуры проекта
Локаторы выносятся в отдельные классы
Файл login_locators.py хранит только ссылки на элементы:
- сразу видно всю структуру страницы;
- проще искать ошибки при изменении DOM;
- можно переиспользовать одни и те же селекторы в нескольких классах.
Действия описываются отдельно
Этот класс — не страница, а «набор действий». Он ничего не знает о тестах, только умеет взаимодействовать с элементами.
Страница объединяет всё воедино
Теперь login_page.py становится тонким «контейнером», который объединяет локаторы и действия:
Теперь класс страницы просто связывает драйвер, локаторы и действия. Он отвечает за «высокоуровневые сценарии» вроде «войти» или «выйти».
Тест остаётся минимальным
Тест описывает только поведение, без деталей Selenium.
Пример добавления новой страницы
Если появляется страница профиля, нужно лишь:
- создать
profile_locators.py; - добавить
profile_actions.py; - собрать их в
profile_page.py.
Использование POM с Pytest
POM связывает тесты и интерфейс так, чтобы сценарий в тесте описывал поведение, а детали DOM жили внутри классов страниц. Pytest даёт фикстуры и параметризацию, поэтому Page Object удобно создавать в одном месте и переиспользовать во всех кейсах.
Каркас: базовая страница и LoginPage
Базовый класс инкапсулирует ожидания и типовые действия. Любая страница наследует его и хранит локаторы у себя. Так тест не знает о селекторах и опирается на методы высокого уровня.
Страница логина описывает элементы и даёт готовые шаги авторизации.
Фикстуры Pytest для драйвера, базового URL и фабрики страниц
Фикстура создаёт браузер с одинаковыми параметрами и закрывает его после теста. Базовый URL передаётся в конструктор страницы. Фабрика даёт удобный способ получать Page Object’ы без дублирования кода.
Тесты читают сценарий, а не DOM
Тест позитивной авторизации опирается на методы страницы. Проверка идёт по сообщению и адресу.
Тест негативных вариантов показывает силу параметризации. Данные подаются таблицей, а логика остаётся прежней.
Компоненты как части страницы
Повторно используемые блоки выносятся в отдельные классы и подключаются к страницам. Это удобно для хедера, сайдбара, фильтров.
Страница «Личный кабинет» включает компонент и отдаёт сценарии поверх него.
# pages/secure_page.py
from pages.base_page import BasePage
from pages.components.header import Header
class SecurePage(BasePage):
def header(self): return Header(self.driver, self.base_url)
Маркеры, структура и независимость
Маркеры группируют сценарии по областям и дают быстрый запуск подмножества. Независимость достигается тем, что каждый тест работает со своей сессией браузера и сам приводит страницу в нужное состояние вызовом методов Page Object. Если вход нужен часто, полезна фикстура «авторизованный пользователь», которая вызывает LoginPage.login() в подготовке и выполняет logout() в завершении.
Локаторы отдельно, действия отдельно, страница как фасад
Проекты среднего размера выигрывают от деления: локаторы в одном модуле, действия в другом, а страница собирает их как фасад. Это упрощает поиск проблем при смене верстки и облегчает ревью. Если меняется селектор, правится файл локаторов; если меняется сценарий, правятся действия; тесты не затрагиваются.
Хуки для артефактов при падении
Pytest-хук сохраняет скриншот и HTML только при неуспехе. Это ускоряет анализ без засорения артефактами.
POM с Pytest сводит��я к трём опорам: базовый класс с ожиданиями и типовыми действиями, страницы с методами уровня сценариев, фикстуры, которые создают драйвер, отдают фабрику страниц и собирают артефакты при падении. Тесты остаются короткими и стабильными, а изменения на фронтенде требуют правок в одном месте — внутри соответствующего Page Object.
LoginPage и DashboardPage
Чтобы показать, как Page Object Model работает в реальном проекте, разберём две связанные страницы — LoginPage и DashboardPage. Одна отвечает за вход в систему, другая — за проверку, что пользователь действительно попал в личный кабинет.
1. Базовый класс BasePage
Он содержит общие методы: открытие страницы, ввод текста, клик и ожидания. Все остальные страницы наследуют этот класс.
2. LoginPage — страница входа
Эта страница содержит поля логина и пароля, кнопку «Login» и сообщение о результате.
3. DashboardPage — страница после входа
После успешной авторизации пользователь попадает на /secure. Эта страница используется для проверки, что вход действительно прошёл.
4. Тест с использованием обеих страниц
В тесте создаются объекты страниц, и шаги записаны на «человеческом» уровне. Selenium-запросов нет — всё спрятано в Page Object’ах.
Что здесь важно
- Тест не знает о локаторах. Все селекторы и клики живут в классах страниц.
- Каждый шаг читается как сценарий:
login.login("user", "pass") → dashboard.is_opened() → dashboard.logout() - Если селекторы поменяются, правится только
login_page.pyилиdashboard_page.py. - Можно добавлять негативные проверки — те же классы будут использоваться повторно.
Расширение: фикстуры и параметры
Если нужно выполнять тест на разных браузерах или стендах, в conftest.py добавляют фикстуры:
И можно передавать базовый URL через переменные окружения (pytest --base-url=https://staging.site).


