Утилита для расширенного взаимодействия с любым веб-сайтом и его страницами
Project description
core-page
Библиотека для автоматической работы с любыми веб-страницами и их элементами на базе Selenium. Вдохновлена статьёй на Хабр и упрощает написание автоматических тестов с реализацией паттерна PageObject. Ускорьте написание кода, а также сделайте его лаконичнее и яснее.
Описание
Зачем нужна эта библиотека, если есть Selenium из коробки, который и предоставляет методы для работы со страницами веб-сайтов? В процессе написания тестов, разработчик регулярно ищет элементы на странице, переходит на другие страницы, получает аттрибуты и т.д.. Все это, как правило, оборачивается в ожидания, чтобы избежать внезапных ошибок. Библиотека предоставляет базовый класс, методы которого позволяют скрыть часть этой логики, а также комбинируют в себе различные инструменты базового Selenium, тем самым расширяя функциональность. Благодаря этому, ускоряется написание тестов, их понимание и последующая поддержка.
Преимущества перед использованием Selenium из коробки:
- Простое использование, путем наследования от базового класса в классы конкретных страниц.
- Возможность установить настройки для теста, просто передав их в аргументах класса.
- Базовые методы поиска элементов расширены и включают в себя явное ожидание.
Оглавление
Установка
Установите core-page через pip:
pip install core-page
Использование библиотеки подразумевает, что на вашем компьютере уже имеется chromedriver. Если нет, то следует ознакомиться с руководством.
Быстрый старт:
Cоздаем файл для тестируемой страницы и импортируем класс BasePage.
Создаем класс страницы и наследуемся от BasePage. Теперь нам доступны все методы базового класса.
# main_page.py
from base_page.base_page import BasePage
class MainPage(BasePage):
pass
Далее, можем создать экземпляр нашего класса MainPage в тест-кейсе и передать необходимые настройки.
# test_main_page.py
from page_objects import MainPage
def test_main_page_title():
page = MainPage(base_url='https://example.com', window_size=(1366, 768))
page.go_to_site()
...
С более подробным примером можно ознакомится в разделе про Page Object.
Документация класса
Создание объекта
Все возможные аргументы класса:
- driver - объект WebDriver.
- driver_fabric - класс WebDriver.
- base_url - адрес страницы без относительного пути.
Перед адресом страницы должен быть указан протокол!
Пример:https://google.com - window_size - размер страницы браузера в формате
(ширина, высота). По умолчанию установлено значение (1920, 1080). - url_suffix - относительный путь к конкретной странице сайта. По умолчанию относительный путь отсутствует.
При создании объекта есть два варианта:
-
Без передачи собственного драйвера. В этом случае драйвер создается в конструкторе.
page = MainPage(base_url='https://google.com')
Обязательные аргументы:
- base_url;
Необязательные аргументы:
- driver_fabric;
- window_size;
- url_suffix;
По умолчанию будет создан драйвер для Chrome без опций. Если хотите использовать свой объект WebDriver, то воспользуйтесь следующим вариантом.
-
С передачей собственного объекта WebDriver.
Для примера создадим свой объект WebDriver и передадим ему опции:from selenium import webdriver options = webdriver.ChromeOptions() options.add_argument('--headless') driver = webdriver.Chrome(options=options) page = MainPage.with_driver(driver=driver, base_url='https://google.com')
Обязательные аргументы:
- driver;
- base_url;
Необязательные аргументы:
- window_size;
- url_suffix;
Метод go_to_site
Осуществляет переход по полному URL страницы (после объединения base_url и url_suffix).
Метод go_to_site ничего не принимает и не возвращает.
from page_objects import MainPage
def test_some_element():
page = MainPage(base_url='https://google.com', url_suffix='/doodles')
page.go_to_site() # Переход на сайт https://google.com/doodles
Метод find_element
Метод find_element ищет элемент на странице по локатору в течение определенного времени. Если элемент найден, то возвращает его.
Иначе выбрасывает TimeoutException.
Принимает следующие аргументы:
- locator - локатор элемента. Значения по умолчанию нет.
- duration - время в секундах, в течение которого будет осуществляться поиск элемента. Значение по умолчанию - 5 секунд.
from page_objects import MainPage
def test_some_element():
page = MainPage(base_url='https://google.com', url_suffix='/doodles')
page.go_to_site()
element = page.find_element(locator, duration=10)
Метод find_elements
Метод find_element ищет все элементы на странице по локатору
в течение определенного времени. Если элементы найдены, то возвращает список из этих элементов.
Иначе выбрасывает TimeoutException.
Принимает следующие аргументы:
- locator - локатор элементов. Значения по умолчанию нет.
- duration - время в секундах, в течение которого будет осуществляться поиск элементов. Значение по умолчанию - 5 секунд.
from page_objects import MainPage
def test_some_element():
page = MainPage(base_url='https://google.com', url_suffix='/doodles')
page.go_to_site()
element = page.find_elements(locator)
Метод custom_wait_until
Метод custom_wait_until позволяет задавать ожидания на основе пользовательских условий. В случае, когда условие
ожидания, которое нам нужно, не предусмотрено Selenium, пользователь может сам задать условие ожидания на основе какой-либо функции.
Принимает следующие аргументы:
- func_condition - функция предикат, в которой задано условие ожидания.
- duration - время в секундах, в течение которого будет выполняться ожидание.
from page_objects import MainPage
def test_some_element():
page = MainPage(base_url='https://google.com', url_suffix='/doodles')
page.go_to_site()
some_link = page.find_element(locator).click()
page.custom_wait_until(lambda browser: browser.current_url != page.url)
Метод move_to_element
Метод move_to_element имитирует наведение мыши на элемент. Комбинирует внутри себя создание объекта ActionChains,
наведение на элемент и выполнение действия (метод perform).
Метод принимает один аргумент:
- element - объект WebElement, на который нужно выполнить наведение мыши.
from page_objects import MainPage
def test_some_element():
page = MainPage(base_url='https://google.com', url_suffix='/doodles')
page.go_to_site()
dropdown_menu = page.find_element(locator)
page.move_to_element(dropdown_menu)
...
Использование в PageObject
Использование паттерна PageObject позволяет упростить написание, поддержку и масштабирование тестов. Базовый класс может в этом помочь.
Допустим, нужно протестировать сайт https://www.python.org/. Он содержит множество страниц и элементов.
Паттерн подразумевает, что каждая страница будет представлена как отдельный класс с методами страницы.
В таком случае, структура проекта может выглядеть следующим образом:
project/
├── page_object/
│ ├── __init__.py
│ ├── main_page.py
│ └── about_page.py
├── tests/
│ ├── __init__.py
│ ├── test_main_page.py
│ └── test_about_page.py
├── ...
└── ...
Рассмотрим файл about_page.py. Он должен описывать методы, содержащие поиск элементов и взаимодействие с ними.
Над классом страницы можно описать класс, содержащий локаторы элементов на странице.
В нашем случае, протестируем наличие поля для поиска по сайту.
# about_page.py
from base_page.base_page import BasePage
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException
class AboutPageLocators:
LOCATOR_SEARCH_FIELD = (By.ID, "id-search-field")
class AboutPage(BasePage):
def is_search_field(self):
try:
self.find_element(AboutPageLocators.LOCATOR_SEARCH_FIELD)
return True
except TimeoutException:
return False
Перейдем в файл test_about_page.py. Здесь мы создаем тест-кейс, в котором проверяем сценарий, описанный в классе страницы.
# test_about_page.py
from page_object.about_page import AboutPage
def test_search_field_exist():
page = AboutPage(base_url='https://www.python.org',
url_suffix='/about',)
page.go_to_site()
search_field_exist = page.is_search_field()
assert search_field_exist
Благодаря такой структуре проекта и использованию паттерна, мы можем легко поддерживать и писать гибкие сценарии. Даже при значительных изменениях тестируемой страницы, исправление тестов не займет много времени.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file core_page-0.1.1.tar.gz.
File metadata
- Download URL: core_page-0.1.1.tar.gz
- Upload date:
- Size: 7.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aee58158903a19ced71bf37a966b96d7fd89af144c65b86a9a4df9eed5baf213
|
|
| MD5 |
62f4f7bf9843b8767e31e563fcca3cd3
|
|
| BLAKE2b-256 |
a40a0ed6d5ba4354ea39e025cfadbf6953899e53f7d520160becec28c1baea86
|
File details
Details for the file core_page-0.1.1-py3-none-any.whl.
File metadata
- Download URL: core_page-0.1.1-py3-none-any.whl
- Upload date:
- Size: 8.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb562f57c83070fb373c2315c6b57e0050626d01710e90ad16c81f9da066e8dc
|
|
| MD5 |
13569f79afc7bf814d9a81e69626fe24
|
|
| BLAKE2b-256 |
0584d3a820bc42faa40c1f3422246b9b6f048e66a8283fa1e4bcafd177d11bd7
|