-
Notifications
You must be signed in to change notification settings - Fork 0
Add tests #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add tests #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| __pycache__/ | ||
| *.pyc | ||
| .pytest_cache/ | ||
| .venv/ | ||
| venv/ | ||
| .idea/ | ||
| .env |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,54 @@ | ||
| # Sprint_5 | ||
| # Sprint_5 — автотесты Stellar Burgers | ||
|
|
||
| Проект содержит автотесты для сервиса Stellar Burgers: | ||
| https://stellarburgers.education-services.ru/ | ||
|
|
||
| Тестирование выполнено с использованием: | ||
| - Python | ||
| - Selenium | ||
| - Pytest | ||
| - Google Chrome / Mozilla Firefox | ||
|
|
||
| ## Проверяемый функционал | ||
| ### Регистрация | ||
| - Успешная регистрация | ||
| - Ошибка при коротком пароле | ||
|
|
||
| ### Авторизация | ||
| - Вход через кнопку «Войти в аккаунт» на главной странице | ||
| - Вход через кнопку «Личный кабинет» | ||
| - Вход через кнопку в форме регистрации | ||
| - Вход через кнопку в форме восстановления пароля | ||
|
|
||
| ### Навигация | ||
| - Переход в личный кабинет | ||
| - Переход из личного кабинета в конструктор (по кнопке «Конструктор») | ||
| - Переход в конструктор по клику на логотип Stellar Burgers | ||
|
|
||
| ### Выход | ||
| - Выход из аккаунта через кнопку «Выйти» в личном кабинете | ||
|
|
||
| ### Конструктор | ||
| - Переключение вкладок: | ||
| - Булки | ||
| - Соусы | ||
| - Начинки | ||
|
|
||
| ## Структура проекта | ||
| │-- tests/ | ||
| │ ├─ test_login.py | ||
| │ ├─ test_logout.py | ||
| │ ├─ test_registration.py | ||
| │ ├─ test_constructor.py | ||
| │ └─ test_navigation.py | ||
| │-- locators.py | ||
| │-- conftest.py | ||
| │-- config.py | ||
| │-- data.py | ||
| │-- .gitignore | ||
| │-- README.md | ||
|
|
||
| ## Генерация тестовых данных | ||
| Email генерируется автоматически в формате: | ||
| `eva_test_17_XXX@yandex.ru` | ||
| Пароль генерируется автоматически и содержит минимум 6 символов. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| BASE_URL = "https://stellarburgers.education-services.ru/" | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import pytest | ||
| import random | ||
| from selenium import webdriver | ||
| from selenium.webdriver.support.ui import WebDriverWait | ||
| from selenium.webdriver.support import expected_conditions as EC | ||
|
|
||
| from config import BASE_URL | ||
| from locators import Locators | ||
| from data import TEST_EMAIL, TEST_PASSWORD | ||
|
|
||
|
|
||
| def pytest_addoption(parser): | ||
| parser.addoption( | ||
| "--browser", | ||
| action="store", | ||
| default="chrome", | ||
| help="Choose browser: chrome or firefox" | ||
| ) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def driver(request): | ||
| browser = request.config.getoption("--browser") | ||
|
|
||
| if browser == "chrome": | ||
| driver = webdriver.Chrome() | ||
| elif browser == "firefox": | ||
| driver = webdriver.Firefox() | ||
| else: | ||
| raise ValueError("Browser not supported") | ||
|
|
||
| driver.maximize_window() | ||
| yield driver | ||
| driver.quit() | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def wait(driver): | ||
| return WebDriverWait(driver, 10) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def authorized_user(driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| wait.until(EC.element_to_be_clickable(Locators.LOGIN_BUTTON_MAIN)).click() | ||
|
|
||
| wait.until(EC.visibility_of_element_located( | ||
| Locators.LOGIN_EMAIL_INPUT)).send_keys(TEST_EMAIL) | ||
|
|
||
| wait.until(EC.visibility_of_element_located( | ||
| Locators.LOGIN_PASSWORD_INPUT)).send_keys(TEST_PASSWORD) | ||
|
|
||
| wait.until(EC.element_to_be_clickable( | ||
| Locators.LOGIN_BUTTON)).click() | ||
|
|
||
| wait.until(EC.url_to_be(BASE_URL)) | ||
| return driver | ||
|
|
||
| @pytest.fixture | ||
| def random_user(): | ||
| number = random.randint(100, 999) | ||
| email = f"eva_test_17_{number}@yandex.ru" | ||
| password = f"Pass{random.randint(100000, 999999)}" | ||
| return email, password |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| TEST_EMAIL = "EvaWunder@yandex.ru" | ||
| TEST_PASSWORD = "parol123" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| from selenium.webdriver.common.by import By | ||
|
|
||
|
|
||
| class Locators: | ||
| # Главная страница | ||
| LOGIN_BUTTON_MAIN = (By.XPATH, "//button[text()='Войти в аккаунт']") | ||
| PERSONAL_ACCOUNT_BUTTON = (By.CSS_SELECTOR, "a[href='/account']") | ||
| LOGO = (By.CSS_SELECTOR, "div.AppHeader_header__logo__2D0X2 a") | ||
| CONSTRUCTOR_BUTTON = (By.XPATH, "//p[text()='Конструктор']") | ||
|
|
||
| # Регистрация / Вход | ||
| REGISTER_LINK = (By.LINK_TEXT, "Зарегистрироваться") | ||
| FORGOT_PASSWORD_LINK = (By.LINK_TEXT, "Восстановить пароль") | ||
| # Внутри формы регистрации | ||
| LOGIN_LINK_IN_REGISTER = (By.LINK_TEXT, "Войти") | ||
|
|
||
| # Внутри формы восстановления | ||
| LOGIN_LINK_IN_FORGOT = (By.LINK_TEXT, "Войти") | ||
|
|
||
| # Поля регистрации | ||
| REGISTER_NAME_INPUT = (By.XPATH, "(//input[@type='text'])[1]") | ||
| REGISTER_EMAIL_INPUT = (By.XPATH, "(//input[@type='text'])[2]") | ||
| REGISTER_PASSWORD_INPUT = (By.NAME, "Пароль") | ||
| REGISTER_BUTTON = (By.XPATH, "//button[normalize-space()='Зарегистрироваться']") | ||
|
|
||
| # Логин | ||
| LOGIN_EMAIL_INPUT = (By.XPATH, "//input[@type='text']") | ||
| LOGIN_PASSWORD_INPUT = (By.NAME, "Пароль") | ||
| LOGIN_BUTTON = (By.XPATH, "//button[normalize-space()='Войти']") | ||
|
|
||
| PASSWORD_ERROR = (By.XPATH, "//p[contains(text(),'Некорректный пароль')]") | ||
|
|
||
| # Личный кабинет | ||
| LOGOUT_BUTTON = (By.XPATH, "//button[contains(text(),'Выход')]") | ||
|
|
||
| # Конструктор | ||
| BUNS_TAB = (By.XPATH, "//span[text()='Булки']") | ||
| SAUCES_TAB = (By.XPATH, "//span[text()='Соусы']") | ||
| FILLINGS_TAB = (By.XPATH, "//span[text()='Начинки']") | ||
|
|
||
| # Overlay | ||
| MODAL_OVERLAY = (By.CSS_SELECTOR, "div.Modal_modal_overlay__x2ZCr") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| from selenium.webdriver.support import expected_conditions as EC | ||
| from locators import Locators | ||
| from config import BASE_URL | ||
|
|
||
|
|
||
| class TestConstructor: | ||
|
|
||
| def click_tab(self, driver, wait, locator): | ||
| tab = wait.until(EC.element_to_be_clickable(locator)) | ||
| driver.execute_script("arguments[0].click();", tab) | ||
| return tab | ||
|
|
||
| def test_switch_to_sauces(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| tab = self.click_tab(driver, wait, Locators.SAUCES_TAB) | ||
| parent = tab.find_element("xpath", "..") | ||
|
|
||
| assert "current" in parent.get_attribute("class") | ||
|
|
||
| def test_switch_to_fillings(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| tab = self.click_tab(driver, wait, Locators.FILLINGS_TAB) | ||
| parent = tab.find_element("xpath", "..") | ||
|
|
||
| assert "current" in parent.get_attribute("class") | ||
|
|
||
| def test_switch_to_buns(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| self.click_tab(driver, wait, Locators.SAUCES_TAB) | ||
|
|
||
| tab = self.click_tab(driver, wait, Locators.BUNS_TAB) | ||
| parent = tab.find_element("xpath", "..") | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нужно исправить: этот таб активен по умолчанию Для проверки тебе нужно сначала переключится на другой |
||
| assert "current" in parent.get_attribute("class") | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| from selenium.webdriver.support import expected_conditions as EC | ||
| from selenium.webdriver.common.by import By | ||
| from locators import Locators | ||
| from config import BASE_URL | ||
| from data import TEST_EMAIL, TEST_PASSWORD | ||
|
|
||
|
|
||
| class TestLogin: | ||
|
|
||
| def login(self, driver, wait): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Можно улучшить: большая часть дублирует фикстуру authorized_user. Возможно стоит убрать из фикстуры точку входа в форму логина, тогда не понадобится отдельный метод для тестирования разных точек входа. В идеале - передавать данные для входа в метод, тогда оя регистрации нового пользователя тоже не придется писать отдельный код |
||
| wait.until( | ||
| EC.visibility_of_element_located(Locators.LOGIN_EMAIL_INPUT) | ||
| ).send_keys(TEST_EMAIL) | ||
|
|
||
| wait.until( | ||
| EC.visibility_of_element_located(Locators.LOGIN_PASSWORD_INPUT) | ||
| ).send_keys(TEST_PASSWORD) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.LOGIN_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until( | ||
| EC.text_to_be_present_in_element( | ||
| (By.XPATH, "//button[contains(text(),'Оформить заказ')]"), | ||
| "Оформить заказ" | ||
| ) | ||
| ) | ||
|
|
||
| def test_login_from_main_button(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.LOGIN_BUTTON_MAIN) | ||
| ).click() | ||
|
|
||
| self.login(driver, wait) | ||
|
|
||
| def test_login_from_personal_account(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.PERSONAL_ACCOUNT_BUTTON) | ||
| ).click() | ||
|
|
||
| self.login(driver, wait) | ||
|
|
||
| def test_login_from_forgot_password(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.PERSONAL_ACCOUNT_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.FORGOT_PASSWORD_LINK) | ||
| ).click() | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.LOGIN_LINK_IN_FORGOT) | ||
| ).click() | ||
|
|
||
| self.login(driver, wait) | ||
|
|
||
| def test_login_from_registration_form(self, driver, wait): | ||
| driver.get(BASE_URL) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.PERSONAL_ACCOUNT_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.REGISTER_LINK) | ||
| ).click() | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.LOGIN_LINK_IN_REGISTER) | ||
| ).click() | ||
|
|
||
| self.login(driver, wait) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| from selenium.webdriver.support import expected_conditions as EC | ||
| from locators import Locators | ||
|
|
||
|
|
||
| class TestLogout: | ||
|
|
||
| def test_logout(self, authorized_user, wait): | ||
| driver = authorized_user | ||
|
|
||
| wait.until(EC.element_to_be_clickable( | ||
| Locators.PERSONAL_ACCOUNT_BUTTON)).click() | ||
|
|
||
| wait.until(EC.url_contains("/account")) | ||
|
|
||
| wait.until(EC.element_to_be_clickable( | ||
| Locators.LOGOUT_BUTTON)).click() | ||
|
|
||
| wait.until(EC.url_contains("login")) | ||
|
|
||
| assert "login" in driver.current_url |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| from selenium.webdriver.support import expected_conditions as EC | ||
| from locators import Locators | ||
| from config import BASE_URL | ||
|
|
||
|
|
||
| class TestNavigation: | ||
|
|
||
| def test_go_to_personal_account(self, authorized_user, wait): | ||
| driver = authorized_user | ||
|
|
||
| wait.until( | ||
| EC.invisibility_of_element_located(Locators.MODAL_OVERLAY) | ||
| ) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.PERSONAL_ACCOUNT_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until(EC.url_contains("/account")) | ||
|
|
||
| assert "/account" in driver.current_url | ||
|
|
||
|
|
||
| def test_go_to_constructor_via_button(self, authorized_user, wait): | ||
| driver = authorized_user | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.PERSONAL_ACCOUNT_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until(EC.url_contains("/account")) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.CONSTRUCTOR_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until(EC.url_to_be(BASE_URL)) | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нужно исправить: не проверен переход по лого |
||
| assert driver.current_url == BASE_URL | ||
|
|
||
|
|
||
| def test_go_to_constructor_via_logo(self, authorized_user, wait): | ||
| driver = authorized_user | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.PERSONAL_ACCOUNT_BUTTON) | ||
| ).click() | ||
|
|
||
| wait.until(EC.url_contains("/account")) | ||
|
|
||
| wait.until( | ||
| EC.element_to_be_clickable(Locators.LOGO) | ||
| ).click() | ||
|
|
||
| wait.until(EC.url_to_be(BASE_URL)) | ||
|
|
||
| assert driver.current_url == BASE_URL | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Нужно исправить: все тесты должны быть разделены на тестовые классы