🐛 Частые ошибки при работе с POM
⚡ Топ-5 ошибок POM
- 1. Локаторы прямо в тестах, а не в классе страницы — нарушает весь смысл POM
- 2. Инициализация элементов в
__init__—StaleElementReferenceException - 3. Нет
__init__.pyвpages/—ModuleNotFoundError - 4.
scope="class"+ тесты меняют состояние браузера — следующий тест падает - 5. Нет
WebDriverWaitв динамических страницах —NoSuchElementException
Ошибка 1: Локаторы прямо в тестах
Симптом: при изменении UI нужно обновлять каждый тестовый файл вручную.
# Плохо: локатор в тесте
def test_login(driver):
driver.find_element(By.ID, "user-name").send_keys("standard_user") # локатор в тесте!
driver.find_element(By.ID, "password").send_keys("secret_sauce")
driver.find_element(By.ID, "login-button").click()
# Хорошо: тест вызывает методы Page Object
def test_login(driver):
login_page = LoginPage(driver)
login_page.success_login("standard_user", "secret_sauce")
Ошибка 2: Инициализация элементов в __init__
Симптом:
StaleElementReferenceException при использовании поля, если страница обновилась.
# Плохо: элемент ищется при создании объекта
class LoginPage:
def __init__(self, driver):
self.driver = driver
self.username_input = driver.find_element(By.ID, "user-name") # ОШИБКА
def enter_username(self, text):
self.username_input.send_keys(text) # упадёт, если DOM обновился
# Хорошо: элемент ищется при вызове метода
class LoginPage(BasePage):
USERNAME_INPUT = (By.ID, "user-name")
def enter_username(self, text):
self.type_text(self.USERNAME_INPUT, text) # поиск происходит здесь
Ошибка 3: Отсутствие __init__.py
Симптом:
ModuleNotFoundError: No module named 'pages'
# Структура без __init__.py — ОШИБКА
pages/
login_page.py # нет __init__.py
# В тесте:
from pages.login_page import LoginPage # ModuleNotFoundError!
# Правильно: создать пустые __init__.py
pages/
__init__.py # пустой файл — делает pages/ пакетом
login_page.py
# Теперь импорт работает:
from pages.login_page import LoginPage # OK
Ошибка 4: scope="class" + грязное состояние
Симптом: второй тест падает из-за состояния, которое оставил первый тест.
# Плохо: test_add_to_cart не возвращает браузер в исходное состояние
class TestInventory(BaseTest):
def test_add_to_cart(self):
self.login_page.success_login("standard_user", "secret_sauce")
self.inventory_page.add_item_to_cart("Sauce Labs Backpack")
# Корзина теперь не пуста! Браузер остался на inventory.html
def test_cart_count_zero(self):
# ПАДАЕТ: корзина не пуста, берём счётчик — там 1
assert self.inventory_page.get_cart_count() == 0
# Хорошо: каждый тест начинает с известного состояния
class TestInventory(BaseTest):
def test_add_to_cart(self):
self.login_page.open()
self.login_page.success_login("standard_user", "secret_sauce")
self.inventory_page.add_item_to_cart("Sauce Labs Backpack")
def test_cart_count_zero(self):
# Явно открываем нужную страницу — не зависим от предыдущего теста
self.login_page.open()
self.login_page.success_login("standard_user", "secret_sauce")
assert self.inventory_page.get_cart_count() == 0
Ошибка 5: find_element вместо WebDriverWait
Симптом:
NoSuchElementException на динамических страницах (AJAX, SPA).
# Плохо: элемент ищется мгновенно, до загрузки
class InventoryPage:
def get_items(self):
return self.driver.find_elements(By.CLASS_NAME, "inventory_item") # могут не загрузиться
# Хорошо: явное ожидание через BasePage.find_all
class InventoryPage(BasePage):
INVENTORY_ITEMS = (By.CLASS_NAME, "inventory_item")
def get_items(self):
return self.find_all(self.INVENTORY_ITEMS) # ждёт appearance
Ошибка 6: Дублирование WebDriverWait в каждом методе
Симптом: код разбухает, тайм-аут указывается в разных местах по-разному.
# Плохо: WebDriverWait создаётся заново в каждом методе
class LoginPage:
def get_username_input(self):
return WebDriverWait(self.driver, 10).until(...) # дубль!
def get_password_input(self):
return WebDriverWait(self.driver, 10).until(...) # дубль!
# Хорошо: WebDriverWait создаётся один раз в BasePage
class BasePage:
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10) # один раз
def find(self, locator):
return self.wait.until(EC.presence_of_element_located(locator))
Ошибка 7: Сложная логика в методах тестов
Симптом: методы тестов содержат XPath и
find_element — при изменении UI ломается везде.
# Плохо: бизнес-логика в тесте
def test_backpack_price(self):
price = self.driver.find_element(
By.XPATH,
"//div[text()='Sauce Labs Backpack']/..//div[@class='inventory_item_price']"
).text # XPath в тесте — нарушение POM
# Хорошо: логика поиска цены в InventoryPage
# pages/inventory_page.py
def get_item_price(self, item_name):
xpath = f"//div[text()='{item_name}']/ancestor::div[@class='inventory_item']//div[@class='inventory_item_price']"
return self.find((By.XPATH, xpath)).text
# tests/test_inventory.py
def test_backpack_price(self):
price = self.inventory_page.get_item_price("Sauce Labs Backpack") # чисто