Comments 19
Очень понравилась статья. Прикольная фишка с динамическими локаторами. Раньше только selenium пользовался и задавался вопросом в чем принципиальные отличия от playwright, а тут как раз эта статья.
Хорошая статья.
Спасибо автору, что продвигает здоровый автотестинг в массы - на ООП, и без codegen :)
Тоже пишу в аналогичном стиле на PW, только на Java, есть свои плюсы тоже.
Спасибо за статью!
Но есть же ещё puppeteer, его не упомянули. Он конечно только на ноде, но в этом может быть кому то только плюс.
Спасибо! Очень познавательно!
Использовал аналогичные подходы на Java. Было интересно как это реализовано на Python.
Если планируете продолжение - не могли бы описать параллельное выпонление тестов?
Спасибо за комментарий! А про параллельное выполнение тестов уже описывал в статье по API тестам, для UI тестов отличий никаких. Все решается установкой библиотеки pytest-xdist
и добавлением флага --numprocesses {number_of_workers}
к команде запуска
Что вы делаете с авторизацией при параллельном запуске? Вы же не можете два теста запустить с логином под одним пользователем, иначе они будут мешать друг другу. Есть какой-то пул пользователей или как это реализовано?
Спасибо за вопрос!
Если тесты мешают друг другу при запуске под одним пользователем — это уже первый красный флаг. Значит, между ними есть нежелательные зависимости, и они не изолированы. А это не баг, а фича плохого дизайна тестов/тестового фреймворка.
В идеале каждый тест должен работать в "песочнице": свои данные, своя сессия, никакой пересечки. Это достигается, как описано в статье, с помощью грамотно написанных фикстур, которые поднимают всё необходимое под капотом и изолируют окружение.
Но да, бывают случаи, когда тесты вынужденно гоняются под одним и тем же юзером — например, если у тебя пул аккаунтов ограничен. Тогда в ход идёт pytest.mark.xdist_group
. С ним можно сгруппировать тесты, которые не могут идти параллельно, и они будут исполняться в одном воркере, последовательно. Остальные при этом запустятся параллельно — и ты не жертвуешь всей скоростью.
Но это — скорее "аварийный выход". Основной путь — делать независимые и изолированные тесты. Тогда и таких вопросов не возникнет
Что вы делаете с авторизацией при параллельном запуске? Вы же не можете два теста запустить с логином под одним пользователем, иначе они будут мешать друг другу.
1) В файле button.py видимо ошибка два раза повторяется expect(locator).to_be_disabled() в двух методах. И вот не понятно с чекбоксом как быть? его не нужно выделять в отдельный тоже файл? или это считается как button
2) Как правильно и где объявлять кастомный data-testid, если по умолчанию web разработчики используют просто "id"? Если я не ошибаюсь, то это нужно сделать в fixtures в settings в chromium_page?
В файле button.py видимо ошибка два раза повторяется expect(locator).to_be_disabled() в двух методах
Спасибо за замечание! Действительно, этот вызов повторялся дважды — уже исправил.
И вот не понятно с чекбоксом как быть? его не нужно выделять в отдельный тоже файл? или это считается button
Чекбокс — это всё же отдельный элемент, у него своя семантика и поведение. Поэтому его лучше выносить в отдельный файл/класс. Он не является частью button
, даже несмотря на визуальную схожесть.
Как правильно и где объявлять кастомный data-testid, если по умолчанию web разработчики используют просто "id"? Если я не ошибаюсь, то это нужно сделать в fixtures в settings в chromium_page?
Да, вы всё верно поняли. Если на проекте используются обычные id
, и нет возможности повлиять на появление data-testid
, можно переопределить селектор по умолчанию. Это делается один раз в начале (например, в фикстуре chromium_page
) с помощью:
playwright.selectors.set_test_id_attribute("id")
осле этого можно использовать привычный синтаксис:
login_button = page.get_by_test_id("login-button")
login_button.click()
Спасибо за ответ, статья очень полезная мне как новичку.
Пробовал по разному импортировать, но добраться до set_test_id_attribute не удалось.
GPT тоже не смог подсказать, пробовал на разных python консолях и переустанавливал.
Пришлось перейти на обычный page.locator
Продолжил изучать вашу статью, репозиторий и обнаружил:
В статье рассказывается про navbar_component.py, но нет информации о sidebar_component.py который в свою очередь ссылается на:from components.navigation.sidebar_list_item_component import SidebarListItemComponent
В репозитории не смог обнаружить этот компонент, не совсем понятно как построена логика компонента SidebarListItemComponent, можете пояснить?
Спасибо за ответ, статья очень полезная мне как новичку.Пробовал по разному импортировать, но добраться до set_test_id_attribute не удалось.GPT тоже не смог подсказать, пробовал на разных python консолях и переустанавливал.Пришлось перейти на обычный page.locator
Делается это очень просто, вот пример:
from playwright.sync_api import sync_playwright
with sync_playwright() as playwright:
playwright.selectors.set_test_id_attribute("my-qa-id")
email_input = page.get_by_test_id('login-form-email-input').locator('input')
email_input.focus()
Продолжил изучать вашу статью, репозиторий и обнаружил:В статье рассказывается про navbar_component.py, но нет информации о sidebar_component.py который в свою очередь ссылается на:
from components.navigation.sidebar_list_item_component import SidebarListItemComponent
В репозитории не смог обнаружить этот компонент, не совсем понятно как построена логика компонента SidebarListItemComponent, можете пояснить?
Спасибо, что обратили внимание! В рамках статьи SidebarComponent не планировался, он попал в репозиторий по ошибке. Я удалил его из проекта — теперь структура репозитория соответствует содержанию статьи. В самой статье всё должно быть корректно.
В названии PageFactory что же всё-таки Factory? А статье вы описываете базовые элементы, которые используются в компонентах, которые собираются в PageObject. Тут все четко и понятно. Но где же Factory?
Справедливости ради, после беглого чтения https://www.toolsqa.com/selenium-webdriver/page-factory-in-selenium/ тоже не стало понятнее.
Спасибо за вопрос! Название PageFactory
действительно может вызывать вопросы — особенно если смотреть на него с точки зрения классического паттерна Factory из GoF. В контексте Selenium (а особенно Java/WebDriver), PageFactory
— это скорее "брендированное" название утилиты инициализации WebElement'ов через аннотации. Это не классическая фабрика, а скорее инструмент для "ленивой" инициализации, которую за нас делает фреймворк.
В статье я фокусировался на Python-версии, где аналогичного PageFactory
из коробки нет, но подход к структурированию и переиспользованию элементов сохраняется. Термин PageFactory
прижился в индустрии, особенно в Java-мире.
UI автотесты на Python с запуском на CI/CD и Allure отчетом. PageObject, PageComponent, PageFactory