Skip to main content

Библиотека на базе Selenium с расширенным функционалом. Предназначена для работы с любым веб-сайтом и его страницами

Project description

pageo

lib-tests PyPI version codecov

Библиотека на базе Selenium с расширенным функционалом. Предназначена для автоматической работы с любыми веб-страницами и их элементами. Вдохновлена статьёй на Хабре и упрощает написание автоматических тестов с реализацией паттерна PageObject. Ускорьте написание кода, а также сделайте его лаконичнее и яснее.

Описание

Зачем нужна эта библиотека, если есть Selenium из коробки, который и предоставляет методы для работы со страницами веб-сайтов? В процессе написания тестов, разработчик регулярно ищет элементы на странице, переходит на другие страницы, получает аттрибуты и т.д.. Все это, как правило, оборачивается в ожидания, чтобы избежать внезапных ошибок. Библиотека предоставляет базовый класс, методы которого позволяют скрыть часть этой логики, а также комбинируют в себе различные инструменты базового Selenium, тем самым расширяя функциональность. Благодаря этому ускоряется написание тестов, их понимание и последующая поддержка.

Преимущества перед использованием Selenium из коробки:

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

Оглавление

Установка

Установите core-page через pip:

pip install pageo

Использование библиотеки подразумевает, что на вашем компьютере уже имеется chromedriver. Если нет, то следует ознакомиться с руководством.

Быстрый старт:

Cоздаем файл для тестируемой страницы и импортируем класс BasePage.
Создаем класс страницы и наследуемся от BasePage. Теперь нам доступны все методы базового класса. Также импортируем класс локатора IdLocator. С его помощью будет выполняться поиск элемента.

# about_page.py

from pageo import BasePage
from pageo.locators import IdLocator


class AboutPage(BasePage):
    search_field_element = IdLocator("id-search-field")

    def is_search_field(self):
        return True if self.search_field_element else False

Далее, можем создать экземпляр нашего класса AboutPage в тест-кейсе и передать необходимые настройки.

# test_about_page.py

from selenium import webdriver

from about_page import AboutPage


def test_search_field_exist():
    page = AboutPage(
        driver=webdriver.Chrome(),
        base_url='https://www.python.org',
        url_suffix='/about',
    )

    search_field_exist = page.is_search_field()
    print(page.is_search_field())
    assert search_field_exist

Подробнее этот пример описан в разделе про Page Object.

Документация базового класса

Создание объекта

Все возможные аргументы класса:

  • driver - объект WebDriver. Обязательный аргумент.
  • base_url - адрес страницы без относительного пути. Перед адресом страницы должен быть указан протокол!
    Пример: https://google.com
  • window_size - размер страницы браузера в формате (ширина, высота). По умолчанию установлено значение (1920, 1080).
  • url_suffix - относительный путь к конкретной странице сайта. По умолчанию относительный путь отсутствует. \

Рекомендуется предварительно создавать свой объект WebDriver.
Для примера создадим свой объект WebDriver и передадим ему опции:

from selenium import webdriver
  
from main_page import MainPage
    
  
options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)
 
page = MainPage(driver=driver, base_url='https://google.com')

Можно передавать его непосредственно в класс (без предварительного создания):

from selenium import webdriver
  
from main_page import MainPage


page = MainPage(driver=webdriver.Chrome(), base_url='https://google.com')

Метод find_element

Метод find_element ищет элемент на странице по локатору в течение определенного времени. Если элемент найден, то возвращает его. Иначе выбрасывает TimeoutException.

Принимает следующие аргументы:

from selenium.webdriver.common.by import By

from page_objects import MainPage


def test_some_element():
    page = MainPage(base_url='https://google.com', url_suffix='/doodles')
      
    element = page.find_element(By.ID, 'about-link')

Метод find_elements

Метод find_element ищет все элементы на странице по локатору в течение определенного времени. Если элементы найдены, то возвращает список из этих элементов. Иначе выбрасывает TimeoutException.

Принимает следующие аргументы:

from selenium.webdriver.common.by import By

from page_objects import MainPage


def test_some_element():
    page = MainPage(base_url='https://google.com', url_suffix='/doodles')
  
    element = page.find_elements(By.ID, 'nav-list')

Метод custom_wait_until

Метод custom_wait_until позволяет задавать ожидания на основе пользовательских условий. В случае, когда условие ожидания, которое нам нужно, не предусмотрено Selenium, пользователь может сам задать условие ожидания на основе какой-либо функции.

Принимает следующие аргументы:

  • func_condition - функция предикат, в которой задано условие ожидания.
  • duration - время в секундах, в течение которого будет выполняться ожидание.
from selenium.webdriver.common.by import By

from page_objects import MainPage


def test_some_element():
    page = MainPage(base_url='https://google.com', url_suffix='/doodles')
  
    page.find_element(By.ID, 'about-link').click()
    page.custom_wait_until(lambda browser: browser.current_url != page.url)

    ...

Метод move_to_element

Метод move_to_element имитирует наведение мыши на элемент. Комбинирует внутри себя создание объекта ActionChains, наведение на элемент и выполнение действия (метод perform).

Метод принимает один аргумент:

  • element - объект WebElement, на который нужно выполнить наведение мыши.
from selenium.webdriver.common.by import By

from page_objects import MainPage


def test_some_element():
    page = MainPage(base_url='https://google.com', url_suffix='/doodles')
  
    about_button = page.find_element(By.ID, 'about-link')
    page.move_to_element(about_button)
    
    ...

Классы локаторов

Вспомогательные классы локаторов для BasePage, инкапсулирующие логику поиска элементов по локаторам. Каждый класс наследуется от абстрактного класса AbstractLocator. Использование классов локаторов позволяет объявлять их в классах страницы как аттрибуты класса. Если селектор изменится или нужно изменить стратегию поиска элемента, то достаточно просто изменить сам класс-стратегию или селектор элемента в аргументах.

Принимаемые аргументы:

  • by - стратегия поиска элемента (например, по аттрибуту ID). Обязательный аргумент.
  • locator - сам локатор. Обязательный аргумент.

Каждый класс локатора возвращает объект WebElement.

class_name_locator

Класс локатора, выполняющий поиск на основе имени класса элемента.

from pageo import BasePage
from pageo import ClassNameLocator 


class SomePage(BasePage):
    some_element = ClassNameLocator("some-class-name")

    ...

css_locator

Класс локатора, выполняющий поиск на основе css-локатора элемента.

from pageo import BasePage
from pageo import CSSLocator


class SomePage(BasePage):
    some_element = CSSLocator("some-css-locator")

    ...

id_locator

Класс локатора, выполняющий поиск на основе аттрибута id у тега элемента.

from pageo import BasePage
from pageo import IdLocator


class SomePage(BasePage):
    some_element = IdLocator("some-id-attribute")

    ...

link_text_locator

Класс локатора, выполняющий поиск на основе текста внутри ссылки элемента.

from pageo import BasePage
from pageo import LinkTextLocator


class SomePage(BasePage):
    some_element = LinkTextLocator("some-link-text")

    ...

name_locator

Класс локатора, выполняющий поиск на основе аттрибута name у тега элемента.

from pageo import BasePage
from pageo import NameLocator


class SomePage(BasePage):
    some_element = NameLocator("some-name-attribute")

    ...

partial_link_text_locator

Класс локатора, выполняющий поиск на основе вхождения текста внутри ссылки элемента.

from pageo import BasePage
from pageo import PartialLinkTextLocator


class SomePage(BasePage):
    some_element = PartialLinkTextLocator("some-partial-link-text")

    ...

tag_name_locator

Класс локатора, выполняющий поиск на основе имени тега элемента.

from pageo import BasePage
from pageo import TagNameLocator


class SomePage(BasePage):
    some_element = TagNameLocator("some-tag-name")

    ...

xpath_locator

Класс локатора, выполняющий поиск на основе пути XPath до элемента.

from pageo import BasePage
from pageo import XPATHLocator


class SomePage(BasePage):
    some_element = XPATHLocator("some-xpath")

    ...

Использование в 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. Он должен описывать методы, содержащие поиск элементов и взаимодействие с ними.
В нашем случае, протестируем наличие поля для поиска по сайту. Для поиска элемента на сайте будет использоваться IdLocator.

# about_page.py

from pageo import BasePage
from pageo import IdLocator

    
class AboutPage(BasePage):
    search_field_element = IdLocator("id-search-field")
    
    def is_search_field(self):
        return True if self.search_field_element else False

Перейдем в файл test_about_page.py. Здесь мы создаем тест-кейс, в котором проверяем сценарий, описанный в классе страницы.

# test_about_page.py

from selenium import webdriver

from page_object.about_page import AboutPage


def test_search_field_exist():
  page = AboutPage(
      driver=webdriver.Chrome(),
      base_url='https://www.python.org', 
      url_suffix='/about', 
  )

  search_field_exist = page.is_search_field()
  assert search_field_exist

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pageo-0.1.2.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

pageo-0.1.2-py3-none-any.whl (19.1 kB view details)

Uploaded Python 3

File details

Details for the file pageo-0.1.2.tar.gz.

File metadata

  • Download URL: pageo-0.1.2.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for pageo-0.1.2.tar.gz
Algorithm Hash digest
SHA256 274274d84ce6bd5dc94899ba152142248fb2ba29004cdd3a27e79fef66c6c0ad
MD5 382e92c13146a5a44dca59912ce30db2
BLAKE2b-256 5e5c2e7b160b3092320df1a4ec1a3777c875dfde143a161c4e4b7c855a0896c5

See more details on using hashes here.

File details

Details for the file pageo-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: pageo-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 19.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for pageo-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 462a48e6d614746b7a29e71998db165e7b890f4bb62d0e09b24ce3ee7f5eeffa
MD5 e6c8a594227a78579a71588dccf33497
BLAKE2b-256 f7bf07f1448eeabddeaa97cf1ea30df3472d28dd88e6f61ae63817347cfb8a44

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page