🐛 Типичные ошибки: Page Object Model
⚡ Топ-5 ошибок POM
- Нет
__init__.pyвpages/→ModuleNotFoundError - Локаторы прямо в тестах, а не в классе страницы → нарушение POM
scope="class", но тесты зависят друг от друга → падает второй тест- Фикстура в методе класса без
selfкак первого аргумента login_page.error_message.text— обращение к атрибуту, которого нет
Ошибка 1: ModuleNotFoundError — нет __init__.py
Симптом:
ModuleNotFoundError: No module named 'pages'
# Ошибка: файл __init__.py отсутствует
saucedemo_tests/
├── pages/
│ ├── login_page.py # ← нет __init__.py!
│ └── inventory_page.py
# Импорт упадёт:
from pages.login_page import LoginPage # ModuleNotFoundError
Исправление: создайте пустые файлы __init__.py:
saucedemo_tests/
├── pages/
│ ├── __init__.py # ← создаём (пустой файл)
│ ├── login_page.py
│ └── inventory_page.py
└── tests/
├── __init__.py # ← тоже создаём
└── test_login.py
В PowerShell:
New-Item -Path "pages\__init__.py" -ItemType File
New-Item -Path "tests\__init__.py" -ItemType File
Ошибка 2: Локаторы в тестах (нарушение POM)
Симптом: тест содержит
driver.find_element(By.ID, ...) — POM не используется.
# Неправильно: локатор в тесте
def test_login(self):
self.driver.find_element(By.ID, "user-name").send_keys("standard_user") # ❌
Исправление: любой поиск элемента — только в классе страницы:
# Правильно: вызов метода страницы
def test_login(self):
self.login_page.enter_username("standard_user") # ✅
Ошибка 3: scope="class" при зависимых тестах
Симптом: второй тест падает с
AssertionError или NoSuchElementException, хотя код правильный.
# Неправильно: тесты зависят — второй видит состояние первого
class TestInventory(BaseTest): # scope="class" → один браузер на класс
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")
# Корзина теперь не пуста!
def test_cart_empty_at_start(self):
# ПАДАЕТ: корзина не пуста из-за предыдущего теста
self.login_page.success_login("standard_user", "secret_sauce")
assert self.inventory_page.get_cart_count() == 0 # ❌ упадёт
Исправление — вариант A: каждый тест начинает с чистого URL:
def test_cart_empty_at_start(self):
self.login_page.open() # открываем страницу заново — корзина пустая
self.login_page.success_login("standard_user", "secret_sauce")
assert self.inventory_page.get_cart_count() == 0 # ✅
Исправление — вариант B: использовать scope="function" если тесты действительно должны быть независимы:
# conftest.py
@pytest.fixture(scope="function") # новый браузер для каждого теста
def driver():
...
Ошибка 4: Фикстура в классе без self
Симптом:
fixture 'driver' not found или фикстура не получает self.
# Неправильно: фикстура класса без self
class TestInventory:
@pytest.fixture(scope="class")
def driver(): # ❌ — нет self!
d = webdriver.Chrome(...)
yield d
d.quit()
@pytest.fixture(scope="class")
def inventory_page(driver): # ❌ — нет self, не видит self.driver
return InventoryPage(driver)
Исправление: первый аргумент метода — всегда self:
class TestInventory:
@pytest.fixture(scope="class")
def driver(self): # ✅
d = webdriver.Chrome(...)
yield d
d.quit()
@pytest.fixture(scope="class")
def inventory_page(self, driver): # ✅
return InventoryPage(driver)
Ошибка 5: Обращение к несуществующему атрибуту страницы
Симптом:
AttributeError: 'LoginPage' object has no attribute 'error_message'
# Неправильно: в тесте обращаются к атрибуту, которого нет в LoginPage
def test_invalid_password(driver):
login_page = LoginPage(driver)
login_page.enter_username("standard_user")
login_page.enter_password("wrong")
login_page.click_login()
assert "do not match" in login_page.error_message.text # ❌ нет такого свойства!
Исправление: добавить метод get_error_message() в класс страницы:
# pages/login_page.py
def get_error_message(self):
return self.get_text(self.ERROR_MESSAGE) # ✅
# tests/test_login.py
assert "do not match" in login_page.get_error_message() # ✅
Ошибка 6: Неправильный XPath в методах InventoryPage
Симптом:
NoSuchElementException при попытке получить цену или добавить товар.
# Неправильно: имя товара не совпадает точно
inventory_page.get_item_price("Backpack") # ❌ — нет такого текста
inventory_page.add_item_to_cart("Bolt T-Shirt") # ❌ — должно быть "Sauce Labs Bolt T-Shirt"
Исправление: имя товара в XPath должно совпадать с текстом элемента страницы точно:
inventory_page.get_item_price("Sauce Labs Backpack") # ✅
inventory_page.add_item_to_cart("Sauce Labs Bolt T-Shirt") # ✅
Ошибка 7: conftest.py в неправильной директории
Симптом: фикстура
driver из conftest.py не видна в тестах.
# Неправильно: conftest.py внутри tests/, а тесты его не видят
saucedemo_tests/
└── tests/
├── conftest.py # ← pytest ищет здесь — OK для тестов в этой папке
└── test_login.py
Правило: conftest.py работает для тестов в своей директории и всех вложенных. Для проекта лучше разместить его в корне:
saucedemo_tests/
├── conftest.py # ✅ виден всем тестам в проекте
├── pages/
└── tests/
└── test_login.py