Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Игнорировать кэш Python
__pycache__/
*.pyc
*.pyo
*.pyd

# Игнорировать кэш pytest
.pytest_cache/
.coverage
htmlcov/

# Игнорировать временные файлы тестов
*.tmp
*.testdb
*.log

# Игнорировать локальные настройки
local_*.py
.env.test

# Игнорировать файлы IDE
.idea/
.vscode/
*.swp
Binary file modified README.md
Binary file not shown.
106 changes: 106 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# conftest.py
import pytest
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from urls import BASE_URL

@pytest.fixture(scope="function")
def driver():
"""Фикстура для инициализации и завершения работы драйвера"""
driver = webdriver.Chrome()
yield driver
driver.quit()

@pytest.fixture
def user_credentials():
"""Генерирует уникальные учетные данные пользователя"""
timestamp = int(time.time() * 1000)
return {
"name": f"TestUser{timestamp}",
"email": f"test{timestamp}@example.com",
"password": f"Password{timestamp % 10000}"
}

@pytest.fixture
def registered_user(driver, user_credentials):
"""Фикстура регистрации нового пользователя"""
driver.get(f"{BASE_URL}register")

# Ожидаем загрузку формы регистрации
WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.XPATH, "//h2[text()='Регистрация']"))
)

# Используем более надежные локаторы
name_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input"))
)
email_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input"))
)
password_input = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//input[@type='password']"))
)

# Заполнение формы
name_input.send_keys(user_credentials["name"])
email_input.send_keys(user_credentials["email"])
password_input.send_keys(user_credentials["password"])

# Отправка формы
driver.find_element(By.XPATH, "//button[text()='Зарегистрироваться']").click()

# Ожидание перехода на страницу входа
WebDriverWait(driver, 15).until(EC.url_contains("login"))
return user_credentials

@pytest.fixture
def login(driver, registered_user):
"""Фикстура для выполнения входа зарегистрированного пользователя"""
def _login():
driver.get(f"{BASE_URL}login")

# Ожидаем загрузку формы входа
WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))
)

# Находим поля с более надежными локаторами
email_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//input[@type='text' and contains(@name, 'name')]"))
)
password_field = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//input[@type='password']"))
)

# Заполняем поля
email_field.clear()
email_field.send_keys(registered_user["email"])
password_field.clear()
password_field.send_keys(registered_user["password"])

# Кликаем кнопку входа
login_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//button[text()='Войти']"))
)
login_button.click()

# Ожидаем успешного входа
WebDriverWait(driver, 15).until(
EC.visibility_of_element_located((By.XPATH, "//button[text()='Оформить заказ']"))
)
return _login

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()

if rep.when == "call" and rep.failed:
driver = item.funcargs.get('driver')
if driver is not None:
timestamp = time.strftime("%Y%m%d_%H%M%S")
driver.save_screenshot(f"failure_{item.name}_{timestamp}.png")
65 changes: 65 additions & 0 deletions helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def login(driver, base_url, test_credentials):
wait = WebDriverWait(driver, 10) # Ожидание до 10 секунд

# 1. Переход на страницу входа
driver.get(f"{base_url}login")

# 2. Ожидание появления формы входа (проверяем заголовок "Вход")
wait.until(
EC.visibility_of_element_located((By.XPATH, "//h2[text()='Вход']"))
)

# 3. Ввод email и пароля
email_field = wait.until(
EC.visibility_of_element_located((By.XPATH, "//input[@name='name']"))
)
email_field.send_keys(test_credentials["email"])

password_field = wait.until(
EC.visibility_of_element_located((By.XPATH, "//input[@type='password']"))
)
password_field.send_keys(test_credentials["password"])

# 4. Клик по кнопке "Войти"
login_button = wait.until(
EC.element_to_be_clickable((By.XPATH, "//button[text()='Войти']"))
)
login_button.click()

# 5. Ожидание успешного входа (например, появления кнопки "Оформить заказ" на главной)
wait.until(
EC.visibility_of_element_located((By.XPATH, "//button[text()='Оформить заказ']"))
)

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from locators import LoginPageLocators

class LoginHelper:
@staticmethod
def perform_login(driver, email, password):
"""Выполняет вход в систему"""
email_field = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(LoginPageLocators.EMAIL_INPUT)
)
email_field.clear()
email_field.send_keys(email)

password_field = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(LoginPageLocators.PASSWORD_INPUT)
)
password_field.clear()
password_field.send_keys(password)

login_button = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(LoginPageLocators.LOGIN_BUTTON)
)
login_button.click()

WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(LoginPageLocators.ORDER_BUTTON)
)
49 changes: 49 additions & 0 deletions locators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from selenium.webdriver.common.by import By


class MainPageLocators:
"""Локаторы главной страницы"""
LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти в аккаунт']")
ACCOUNT_BUTTON = (By.XPATH, "//a[@href='/account']")
LOGO = (By.CLASS_NAME, "AppHeader_header__logo__2D0X2")


class ConstructorPageLocators:
"""Локаторы конструктора"""
CONSTRUCTOR_BUTTON = (By.XPATH, "//p[text()='Конструктор']")
BUNS_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab')]//span[text()='Булки']/..")
SAUCES_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab')]//span[text()='Соусы']/..")
TOPPINGS_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab')]//span[text()='Начинки']/..")
ACTIVE_TAB = (By.XPATH, "//div[contains(@class, 'tab_tab_type_current')]/span")
BUNS_SECTION = (By.XPATH, "//h2[text()='Булки']/..")
SAUCES_SECTION = (By.XPATH, "//h2[text()='Соусы']/..")
TOPPINGS_SECTION = (By.XPATH, "//h2[text()='Начинки']/..")


class LoginPageLocators:
"""Локаторы страницы входа"""
LOGIN_HEADER = (By.XPATH, "//h2[contains(text(), 'Вход')]")
EMAIL_INPUT = (By.XPATH, "//input[@name='name']")
PASSWORD_INPUT = (By.XPATH, "//input[@type='password']")
LOGIN_BUTTON = (By.XPATH, "//button[text()='Войти']")
ORDER_BUTTON = (By.XPATH, "//button[text()='Оформить заказ']")


class RegistrationPageLocators:
"""Локаторы страницы регистрации"""
REGISTRATION_HEADER = (By.XPATH, "//h2[contains(text(), 'Регистрация')]")
NAME_INPUT = (By.XPATH, "//label[contains(text(), 'Имя')]/following-sibling::input")
EMAIL_INPUT = (By.XPATH, "//label[contains(text(), 'Email')]/following-sibling::input")
PASSWORD_INPUT = (By.XPATH, "//input[@type='password']")
SUBMIT_BUTTON = (By.XPATH, "//button[contains(text(), 'Зарегистрироваться')]")
PASSWORD_ERROR = (By.XPATH, "//p[contains(text(), 'Некорректный пароль')]")
LOGIN_LINK = (By.XPATH, "//a[text()='Войти']")


class ForgotPasswordLocators:
"""Локаторы страницы восстановления пароля"""
LOGIN_LINK = (By.XPATH, "//a[text()='Войти']")

class AccountPageLocators:
"""Локаторы страницы личного кабинета"""
LOGOUT_BUTTON = (By.XPATH, "//button[contains(text(), 'Выход')]")
77 changes: 77 additions & 0 deletions test_constructor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import pytest
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from urls import BASE_URL
from locators import ConstructorPageLocators


class TestConstructorNavigation:
"""Тесты навигации между разделами конструктора"""

def test_buns_section_by_default(self, driver):
"""Проверка, что по умолчанию активна вкладка 'Булки'"""
driver.get(BASE_URL)

active_tab = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB)
)
assert active_tab.text == "Булки", f"Ожидалась активная вкладка 'Булки', но получили '{active_tab.text}'"

def test_switch_between_buns_and_sauces(self, driver):
"""Тест переключения между разделами 'Булки' и 'Соусы'"""
driver.get(BASE_URL)

# Ожидаем загрузки конструктора
WebDriverWait(driver, 15).until(
EC.presence_of_element_located(ConstructorPageLocators.BUNS_SECTION)
)

# Проверяем начальное состояние
active_tab = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB)
)
assert active_tab.text == "Булки", "По умолчанию должна быть активна вкладка 'Булки'"

# Переключаемся на соусы
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(ConstructorPageLocators.SAUCES_TAB)
).click()

# Ждем активации вкладки "Соусы"
WebDriverWait(driver, 15).until(
EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Соусы")
)

# Возвращаемся на булки
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(ConstructorPageLocators.BUNS_TAB)
).click()

# Ждем активации вкладки "Булки" с увеличенным таймаутом
WebDriverWait(driver, 15).until(
EC.text_to_be_present_in_element(ConstructorPageLocators.ACTIVE_TAB, "Булки")
)

# Дополнительная проверка видимости раздела
WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(ConstructorPageLocators.BUNS_SECTION)
)
Comment on lines +56 to +58

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Необходимо исправить: этот тест ничего не проверяет, необходимо воспользоваться assert-инструкцией


def test_switch_to_toppings_section(self, driver):
"""Тест переключения на раздел 'Начинки'"""
driver.get(BASE_URL)

toppings_tab = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(ConstructorPageLocators.TOPPINGS_TAB)
)
toppings_tab.click()

# Ждем появления раздела начинок
WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(ConstructorPageLocators.TOPPINGS_SECTION)
)

active_tab = WebDriverWait(driver, 10).until(
EC.visibility_of_element_located(ConstructorPageLocators.ACTIVE_TAB)
)
assert active_tab.text == "Начинки", f"Ожидалась активная вкладка 'Начинки', но получили '{active_tab.text}'"
49 changes: 49 additions & 0 deletions test_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import pytest
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from urls import BASE_URL
from locators import (MainPageLocators, RegistrationPageLocators, ForgotPasswordLocators)
from helpers import LoginHelper

class TestLogin:
"""Тесты авторизации пользователя"""

def test_login_from_main_page_button(self, driver, registered_user):
"""Тест входа через кнопку на главной странице"""
driver.get(BASE_URL)
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(MainPageLocators.LOGIN_BUTTON)
).click()

LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"])
assert BASE_URL == driver.current_url

def test_login_from_personal_account_button(self, driver, registered_user):
"""Тест входа через кнопку личного кабинета"""
driver.get(BASE_URL)
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(MainPageLocators.ACCOUNT_BUTTON)
).click()

LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"])
assert BASE_URL == driver.current_url

def test_login_from_registration_form(self, driver, registered_user):
"""Тест входа через форму регистрации"""
driver.get(f"{BASE_URL}register")
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(RegistrationPageLocators.LOGIN_LINK)
).click()

LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"])
assert BASE_URL == driver.current_url

def test_login_from_forgot_password_form(self, driver, registered_user):
"""Тест входа через форму восстановления пароля"""
driver.get(f"{BASE_URL}forgot-password")
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable(ForgotPasswordLocators.LOGIN_LINK)
).click()

LoginHelper.perform_login(driver, registered_user["email"], registered_user["password"])
assert BASE_URL == driver.current_url
Loading