diff --git a/hw4/__init__.py b/hw4/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hw4/selenium/__init__.py b/hw4/selenium/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hw4/selenium/tests/__init__.py b/hw4/selenium/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/hw4/selenium/tests/conftest.py b/hw4/selenium/tests/conftest.py new file mode 100644 index 0000000..22424de --- /dev/null +++ b/hw4/selenium/tests/conftest.py @@ -0,0 +1,28 @@ +import pytest +from selenium.webdriver.chrome.options import Options +from selenium import webdriver +from selenium.webdriver.support.wait import WebDriverWait + + +@pytest.fixture +def chrome_options(): + options = Options() + options.add_argument("--window-size=1900x1000") + return options + + +@pytest.fixture +def driver(chrome_options): + driver = webdriver.Chrome(options=chrome_options) + driver.implicitly_wait(10) + driver.get('http://195.133.27.184/') + yield driver + driver.quit() + + +@pytest.fixture +def wait(driver): + wait = WebDriverWait(driver, timeout=10) + return wait + + diff --git a/hw4/selenium/tests/test.py b/hw4/selenium/tests/test.py new file mode 100644 index 0000000..32410c0 --- /dev/null +++ b/hw4/selenium/tests/test.py @@ -0,0 +1,162 @@ +import pytest +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC + + +def test_register_positive(driver, wait): + # main page + driver.get('http://195.133.27.184/') + assert driver.title == "Объявления" + + toggler_nav_locator = "//*[text()='Регистрация']" + driver.find_element(By.XPATH, toggler_nav_locator).click() + + # registration form + page_title_locator = "//h1[text() = 'Регистрация']" + page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator))) + assert page_title.text == "Регистрация" + + # input username + login_locator = "//*[@placeholder = 'Введите имя пользователя']" + driver.find_element(By.XPATH, login_locator).send_keys("Jerry") # John exists + + # input password + password_locator = "//*[@placeholder = 'Введите пароль']" + driver.find_element(By.XPATH, password_locator).send_keys("Iamateacher") # password is too spread + + # confirm password + confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']" + driver.find_element(By.XPATH, confirm_password_locator).send_keys("Iamateacher") + + # click check-box is_tutor + check_box_locator = "//*[@name = 'is_tutor']" + check_box = driver.find_element(By.XPATH, check_box_locator) + if not check_box.is_selected(): + check_box.click() + + # submit form + submit_btn_locator = "//*[@type = 'submit']" + driver.find_element(By.XPATH, submit_btn_locator).click() + + # new page opens + logout_btn_locator = "//*[text() = 'Выйти']" + logout_btn = wait.until(EC.element_to_be_clickable((By.XPATH, logout_btn_locator))) + assert logout_btn.is_displayed() + + +# NEGATIVE scenarios + +# FOR TEACHER + +def test_register_teacher_check_box(driver, wait): + + toggler_nav_locator = "//*[text()='Регистрация']" + driver.find_element(By.XPATH, toggler_nav_locator).click() + + # registration form + page_title_locator = "//h1[text() = 'Регистрация']" + page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator))) + assert page_title.text == "Регистрация" + + # input username + login_locator = "//*[@placeholder = 'Введите имя пользователя']" + driver.find_element(By.XPATH, login_locator).send_keys("Jerry") # John exists + + # input password + password_locator = "//*[@placeholder = 'Введите пароль']" + driver.find_element(By.XPATH, password_locator).send_keys("Iamateacher") # password is too spread + + # confirm password + confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']" + driver.find_element(By.XPATH, confirm_password_locator).send_keys("Iamateacher") + + # click check-box is_tutor + check_box_locator = "//*[@name = 'is_tutor']" + check_box = driver.find_element(By.XPATH, check_box_locator) + if not check_box.is_selected(): + check_box.click() + + # submit form + submit_btn_locator = "//*[@type = 'submit']" + driver.find_element(By.XPATH, submit_btn_locator).click() + + # new page opens + logout_btn_locator = "//*[text() = 'Выйти']" + logout_btn = wait.until(EC.element_to_be_clickable((By.XPATH, logout_btn_locator))) + assert logout_btn.is_displayed() + + +### FOR STUDENT +@pytest.mark.parametrize("username, password, confirm_password, expected", [ + ("", "", "", "Обязательное поле."), + ("Jerry", "", "", "Пользователь с таким именем уже существует."), + ("", "qwertyuiop", "qwertyuiop", "Обязательное поле."), + # ("123456", "qwertyuiop", "qwertyuiop", " ? ") # ? should be an error. In fact, it passes +]) +def test_register_student_username_negative(driver, wait, username, password, confirm_password, expected): + # main page + toggler_nav_locator = "//*[text()='Регистрация']" + driver.find_element(By.XPATH, toggler_nav_locator).click() + + # registration form + page_title_locator = "//h1[text() = 'Регистрация']" + page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator))) + assert page_title.text == "Регистрация" + + # input username + login_locator = "//*[@placeholder = 'Введите имя пользователя']" + driver.find_element(By.XPATH, login_locator).send_keys(username) + + # input password + password_locator = "//*[@placeholder = 'Введите пароль']" + driver.find_element(By.XPATH, password_locator).send_keys(password) + + # confirm password + confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']" + driver.find_element(By.XPATH, confirm_password_locator).send_keys(confirm_password) + + # submit form + submit_btn_locator = "//*[@type = 'submit']" + driver.find_element(By.XPATH, submit_btn_locator).click() + + error_message_locator = f"//*[text() = '{expected}']" + error_message = wait.until(EC.visibility_of_element_located((By.XPATH, error_message_locator))) + assert error_message.text == expected + + +@pytest.mark.parametrize("username, password, confirm_password, expected", [ + ("Nina", "qwertyuiop", "qwertyuiop", "Введённый пароль слишком широко распространён."), + ("Nina", "12345678", "12345678", "Введённый пароль слишком широко распространён."), + ("Nina", "poiuytre", "poiuytr", "Введенные пароли не совпадают."), + ("Nina", "poiuytre", "poiuytree", "Введенные пароли не совпадают."), + ("Nina", "qwertyu", "qwertyu", "Введённый пароль слишком короткий. Он должен содержать как минимум 8 символов.") +]) +def test_register_student_password_negative(driver, wait, username, password, confirm_password, expected): + # main page + toggler_nav_locator = "//*[text()='Регистрация']" + driver.find_element(By.XPATH, toggler_nav_locator).click() + + # registration form + page_title_locator = "//h1[text() = 'Регистрация']" + page_title = wait.until(EC.visibility_of_element_located((By.XPATH, page_title_locator))) + assert page_title.text == "Регистрация" + + # input username + login_locator = "//*[@placeholder = 'Введите имя пользователя']" + driver.find_element(By.XPATH, login_locator).send_keys(username) + + # input password + password_locator = "//*[@placeholder = 'Введите пароль']" + driver.find_element(By.XPATH, password_locator).send_keys(password) + + # confirm password + confirm_password_locator = "//*[@placeholder = 'Подтвердите пароль']" + driver.find_element(By.XPATH, confirm_password_locator).send_keys(confirm_password) + + # submit form + submit_btn_locator = "//*[@type = 'submit']" + driver.find_element(By.XPATH, submit_btn_locator).click() + + error_message_locator = f"//*[text() = '{expected}']" + error_message = wait.until(EC.visibility_of_element_located((By.XPATH, error_message_locator))) + assert error_message.text == expected diff --git a/lesson1/api_tests/services/case/data.py b/lesson1/api_tests/services/case/data.py index d9e7670..33feca1 100644 --- a/lesson1/api_tests/services/case/data.py +++ b/lesson1/api_tests/services/case/data.py @@ -6,3 +6,39 @@ "steps": ["шаг 1", "шаг 2", "шаг 3"], "expected_result": "Задание выполнено", } + + +schema_response_empty_data = { +"detail": [ + { + "type": "missing", + "loc": ["body", "name"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "description"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "steps"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "expected_result"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "priority"], + "msg": "Field required", + "input": {}, + }, + ] +} \ No newline at end of file diff --git a/lesson1/api_tests/services/case/pom.py b/lesson1/api_tests/services/case/pom.py index 0d6ff88..16bb5eb 100644 --- a/lesson1/api_tests/services/case/pom.py +++ b/lesson1/api_tests/services/case/pom.py @@ -1,6 +1,65 @@ -from utils.api_client import client +from lesson1.api_tests.utils.api_client import client +from lesson1.api_tests.services.case.data import create_case_dict def create_case(json={}): response = client.make_request(handle="/testcases", method="POST", json=json) return response + + +def get_read_root(): + response = client.make_request( + handle="/", + method="GET" + ) + return response + + +def read_cases(): + response = client.make_request( + handle="/testcases", + method="GET", + ) + return response + + +def read_case(): + response = create_case(json=create_case_dict) + case_id = response.get_value_with_key("id") + response = client.make_request( + handle=f"/testcases/{case_id}", + method="GET", + ) + return response + + +def get_case_id(): + response = create_case(json=create_case_dict) + case_id = response.get_value_with_key("id") + return case_id + + +def update_case(): + case_id = get_case_id() + response = client.make_request( + handle=f"/testcases/{case_id}", + method="PUT", + json={ + "id": 5, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + ) + return response + + +def delete_case(): + case_id = create_case(json=create_case_dict).get_value_with_key("id") + response = client.make_request( + handle=f"/testcases/{case_id}", + method="DELETE", + ) + return response diff --git a/lesson1/api_tests/tests/test_case.py b/lesson1/api_tests/tests/test_case.py index 2e5b45a..488b7e8 100644 --- a/lesson1/api_tests/tests/test_case.py +++ b/lesson1/api_tests/tests/test_case.py @@ -1,6 +1,6 @@ -from services.case.pom import create_case -from services.case.data import create_case_dict -from services.case.models import Case +from lesson1.api_tests.services.case.pom import create_case +from lesson1.api_tests.services.case.data import create_case_dict +from lesson1.api_tests.services.case.models import Case def test_create_case(): diff --git a/lesson1/api_tests/tests/test_cases_les1.py b/lesson1/api_tests/tests/test_cases_les1.py new file mode 100644 index 0000000..3af2ded --- /dev/null +++ b/lesson1/api_tests/tests/test_cases_les1.py @@ -0,0 +1,339 @@ +from lesson1.api_tests.services.case.data import create_case_dict +from lesson1.api_tests.utils.api_client import client + + +### Get Read Root - GET +def test_get_read_root(): + response = client.make_request(handle="/", method="GET") + response.status_code_should_be_eq(200) + response.json_should_be_eq({"Hello": "World"}) + + +### Get all TCs - GET +def test_get_testcases(): + response = client.make_request( + handle="/testcases", + method="GET", + ) + response.status_code_should_be_eq(200) + # not clear how to verify the list ? + + +### Create Test Case - POST +def test1_create_case(): + response = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 3, + "name": "Имя", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + }, + ) + response.status_code_should_be_eq(200) + response.json_should_contains({"id": 3}) + + +# OR +def test1_create_case1(): + response = client.make_request( + handle="/testcases", method="POST", json=create_case_dict + ) + response.status_code_should_be_eq(200) + response.value_with_key("id").should_be_eq(0) + + +def test2_create_case_empty_data(): + """ + negative - body is empty + """ + response = client.make_request(handle="/testcases", method="POST", json={}) + response.status_code_should_be_eq(422) + response.json_should_be_eq( + { + "detail": [ + { + "type": "missing", + "loc": ["body", "name"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "description"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "steps"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "expected_result"], + "msg": "Field required", + "input": {}, + }, + { + "type": "missing", + "loc": ["body", "priority"], + "msg": "Field required", + "input": {}, + }, + ] + } + ) + + +def test3_create_case_missed_priority_data(): + """ + negative - key "priority" is missing in the body + """ + response = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 0, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + }, + ) + response.status_code_should_be_eq(422) + response.json_should_contains( + { + "detail": [ + { + "type": "missing", + "loc": ["body", "priority"], + "msg": "Field required", + "input": { + "id": 0, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + }, + } + ] + } + ) + +### Get TC ID - GET +def test1_get_case_id(): + response1 = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 4, + "name": "Tom", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + }, + ) + + case_id = response1.get_value_with_key("id") + response2 = client.make_request(handle=f"/testcases/{case_id}", method="GET") + response2.status_code_should_be_eq(200) + response2.json_should_be_eq( + { + "id": 4, + "name": "Tom", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + } + ) + + +def test2_get_case_not_existing_id(): + """ + negative - id is not exist + """ + response2 = client.make_request(handle=f"/testcases/455", method="GET") + response2.status_code_should_be_eq(404) + response2.json_should_be_eq({"detail": "Test case not found."}) + + +# not clear how to get Validation Error 422 ? + + +### To update TC data - PUT +def test1_update_case(): + response1 = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 4, + "name": "Tom", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + }, + ) + + case_id = response1.get_value_with_key("id") + response2 = client.make_request( + handle=f"/testcases/{case_id}", + method="PUT", + json={ + "id": 5, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + ) + response2.status_code_should_be_eq(200) + response2.json_should_be_eq( + { + "id": 5, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + } + ) + + +def test2_update_case_empty_id(): + """ + negative = update to "id": "" + """ + response1 = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 4, + "name": "Tom", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + }, + ) + + case_id = response1.get_value_with_key("id") + response2 = client.make_request( + handle=f"/testcases/{case_id}", + method="PUT", + json={ + "id": "", + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + ) + response2.status_code_should_be_eq(422) + response2.json_should_be_eq( + { + "detail": [ + { + "type": "int_parsing", + "loc": ["body", "id"], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "", + } + ] + } + ) + + +def test3_update_case_missed_description(): + """ + negative - description is missing in update body + """ + response1 = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 4, + "name": "Tom", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + }, + ) + + case_id = response1.get_value_with_key("id") + response2 = client.make_request( + handle=f"/testcases/{case_id}", + method="PUT", + json={ + "id": 2, + "name": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + ) + response2.status_code_should_be_eq(422) + response2.json_should_be_eq( + { + "detail": [ + { + "type": "missing", + "loc": ["body", "description"], + "msg": "Field required", + "input": { + "id": 2, + "name": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + } + ] + } + ) + + +### Delete TC +def test1_delete_case(): + response1 = client.make_request( + handle="/testcases", + method="POST", + json={ + "id": 4, + "name": "Tom", + "description": "Описание", + "steps": ["Шаг 1", "Шаг 2", "Шаг 3"], + "expected_result": "Ожидаемый результат", + "priority": "низкий", + }, + ) + response1.status_code_should_be_eq(200) + case_id = response1.get_value_with_key("id") + response2 = client.make_request( + handle=f"/testcases/{case_id}", + method="DELETE", + ) + response2.status_code_should_be_eq(200) + response2.json_should_be_eq({"detail": "Test case deleted."}) + + +def test2_delete_not_existing_case(): + """ + negative - delete not existing case + """ + response2 = client.make_request( + handle=f"/testcases/455", + method="DELETE", + ) + response2.status_code_should_be_eq(404) + response2.json_should_be_eq({"detail": "Test case not found."}) diff --git a/lesson1/api_tests/tests/test_cases_les1_optimization.py b/lesson1/api_tests/tests/test_cases_les1_optimization.py new file mode 100644 index 0000000..6b40584 --- /dev/null +++ b/lesson1/api_tests/tests/test_cases_les1_optimization.py @@ -0,0 +1,189 @@ +from lesson1.api_tests.services.case.pom import create_case, get_read_root, read_cases, get_case_id, update_case, \ + delete_case +from lesson1.api_tests.services.case.data import create_case_dict, schema_response_empty_data +from lesson1.api_tests.services.case.models import Case +from lesson1.api_tests.utils.api_client import client + + +### Get Read Root - GET +def test_get_read_root(): + response = get_read_root() + response.status_code_should_be_eq(200) + response.json_should_be_eq({"Hello": "World"}) + + +### Get all TCs - GET +def test_get_testcases(): + response = read_cases() + response.status_code_should_be_eq(200) + + +### Create Test Case - POST +def test_create_case(): + response = create_case(Case(**create_case_dict).model_dump()) + response.status_code_should_be_eq(200) + response.json_should_be_eq(create_case_dict) + response.schema_should_be_eq(Case(**create_case_dict).model_json_schema()) + + +def test2_create_case_empty_data(): + """ + negative - body is empty + """ + response = create_case() + response.status_code_should_be_eq(422) + response.json_should_be_eq(schema_response_empty_data) + + +def test3_create_case_missed_priority_data(): + """ + negative - key "priority" is missing in the body + """ + response = create_case(json={ + "id": 0, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string" + }, ) + + response.status_code_should_be_eq(422) + response.json_should_contains( + { + "detail": [ + { + "type": "missing", + "loc": ["body", "priority"], + "msg": "Field required", + "input": { + "id": 0, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + }, + } + ] + } + ) + + +### Get TC ID - GET +def test1_get_case_id(): + response = read_cases() + response.status_code_should_be_eq(200) + # response.schema_should_be_eq(Case(**create_case_dict).model_json_schema()) + + +def test2_get_case_not_existing_id(): + """ + negative - id is not exist + """ + response2 = client.make_request(handle=f"/testcases/455", method="GET") + response2.status_code_should_be_eq(404) + response2.json_should_be_eq({"detail": "Test case not found."}) + + +### To update TC data - PUT +def test1_update_case(): + response = update_case() + response.status_code_should_be_eq(200) + response.json_should_be_eq( + { + "id": 5, + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + } + ) + + +def test2_update_case_empty_id(): + """ + negative = update to "id": "" + """ + case_id = get_case_id() + + response = client.make_request( + handle=f"/testcases/{case_id}", + method="PUT", + json={ + "id": "", + "name": "string", + "description": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + ) + response.status_code_should_be_eq(422) + response.json_should_be_eq( + { + "detail": [ + { + "type": "int_parsing", + "loc": ["body", "id"], + "msg": "Input should be a valid integer, unable to parse string as an integer", + "input": "", + } + ] + } + ) + + +def test3_update_case_missed_description(): + """ + negative - description is missing in body update + """ + case_id = get_case_id() + response = client.make_request( + handle=f"/testcases/{case_id}", + method="PUT", + json={ + "id": 2, + "name": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + ) + response.status_code_should_be_eq(422) + response.json_should_be_eq( + { + "detail": [ + { + "type": "missing", + "loc": ["body", "description"], + "msg": "Field required", + "input": { + "id": 2, + "name": "string", + "steps": ["string"], + "expected_result": "string", + "priority": "низкий", + }, + } + ] + } + ) + + +### Delete TC +def test1_delete_case(): + response = delete_case() + response.status_code_should_be_eq(200) + response.json_should_be_eq({"detail": "Test case deleted."}) + + +def test2_delete_not_existing_case(): + """ + negative - delete not existing case + """ + response2 = client.make_request( + handle=f"/testcases/455", + method="DELETE", + ) + response2.status_code_should_be_eq(404) + response2.json_should_be_eq({"detail": "Test case not found."}) diff --git a/lesson1/api_tests/utils/api_client.py b/lesson1/api_tests/utils/api_client.py index 1565074..d3a75ce 100644 --- a/lesson1/api_tests/utils/api_client.py +++ b/lesson1/api_tests/utils/api_client.py @@ -3,11 +3,11 @@ import allure import requests from allure_commons.types import AttachmentType -from services.config import settings +from lesson1.api_tests.services.config import settings from curlify2 import Curlify # Curlify2 работает и с httpx и с requests. from loguru import logger from requests import Response -from utils.api_response import APIResponse +from lesson1.api_tests.utils.api_response import APIResponse # Inspired by https://github.com/qa-guru/knowledge-base/wiki/17.-REST-API.-%D0%A7%D0%B0%D1%81%D1%82%D1%8C-II.-%D0%9F%D1%80%D0%BE%D0%B4%D0%BE%D0%BB%D0%B6%D0%B0%D0%B5%D0%BC-%D0%B8%D0%B7%D1%83%D1%87%D0%B0%D1%82%D1%8C diff --git a/lesson1/api_tests/utils/api_response.py b/lesson1/api_tests/utils/api_response.py index 7e14a90..cfdcbc4 100644 --- a/lesson1/api_tests/utils/api_response.py +++ b/lesson1/api_tests/utils/api_response.py @@ -10,13 +10,13 @@ def __init__(self, response: Response): def status_code_should_be_eq(self, expected_status): assert ( - self.response.status_code == expected_status + self.response.status_code == expected_status ), f"Ожидали {expected_status}, но получили {self.response.status_code}" return self def len_of_json_should_be_eq(self, expected_len): assert ( - len(self.response.json()) == expected_len + len(self.response.json()) == expected_len ), f"Ожидали {expected_len}, но получили {len(self.response.json())}" return self @@ -116,6 +116,6 @@ def get_value_with_key(self, key_name): def should_be_eq(self, expected_value): assert ( - self._current_value == expected_value + self._current_value == expected_value ), f"Ожидали {expected_value}, но получили {self._current_value}" return self diff --git a/lesson2/requirements.txt b/lesson2/requirements.txt index 537ba9d..d5fdcb6 100644 --- a/lesson2/requirements.txt +++ b/lesson2/requirements.txt @@ -1,4 +1,24 @@ +attrs==24.2.0 +certifi==2024.8.30 +Faker==32.1.0 +h11==0.14.0 +idna==3.10 +iniconfig==2.0.0 +loguru==0.7.2 +outcome==1.3.0.post0 +packaging==24.2 +pluggy==1.5.0 +PySocks==1.7.1 pytest==8.3.3 +python-dateutil==2.9.0.post0 ruff==0.7.1 selenium==4.25.0 -loguru==0.7.2 \ No newline at end of file +six==1.16.0 +sniffio==1.3.1 +sortedcontainers==2.4.0 +trio==0.27.0 +trio-websocket==0.11.1 +typing_extensions==4.12.2 +urllib3==2.2.3 +websocket-client==1.8.0 +wsproto==1.2.0 diff --git a/lesson2/simple_example.py b/lesson2/simple_example.py index ba92fed..22dd944 100644 --- a/lesson2/simple_example.py +++ b/lesson2/simple_example.py @@ -1,9 +1,17 @@ from selenium import webdriver from selenium.webdriver.common.by import By +import time browser = webdriver.Chrome() browser.get("http://195.133.27.184/") + +time.sleep(4) + + element = browser.find_element(By.XPATH, "//a[@href='/2/']") +element.is_displayed() +# element.click() +# assert browser.current_url == "http://195.133.27.184/2/", "Wrong URL" element.click() assert browser.current_url == "http://195.133.27.184/3/", "Wrong URL" \ No newline at end of file diff --git a/lesson3/__init__.py b/lesson3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson3/example1/tests/test_example.py b/lesson3/example1/tests/test_example.py index e1a0475..f30be9b 100644 --- a/lesson3/example1/tests/test_example.py +++ b/lesson3/example1/tests/test_example.py @@ -1,7 +1,9 @@ from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC + def test_visible_after_with_explicit_waits_with_selenium(driver, wait): driver.get('https://demoqa.com/dynamic-properties') - visible_after_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']"))) + visible_after_button = wait.until( + EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']"))) assert visible_after_button.text == 'Visible After 5 Seconds' diff --git a/lesson3/example2/tests/test_example.py b/lesson3/example2/tests/test_example.py index a87eb5b..f79ea8f 100644 --- a/lesson3/example2/tests/test_example.py +++ b/lesson3/example2/tests/test_example.py @@ -4,4 +4,4 @@ def test_visible_after_with_explicit_waits_with_selene(): browser.open('https://demoqa.com/dynamic-properties') browser.element('//button[text()="Visible After 5 Seconds"]'). \ - should(have.exact_text('Visible After 5 Secon')) \ No newline at end of file + should(have.exact_text('Visible After 5 Seconds')) diff --git a/lesson3/example3/tests/test_example.py b/lesson3/example3/tests/test_example.py index dce255b..eb79288 100644 --- a/lesson3/example3/tests/test_example.py +++ b/lesson3/example3/tests/test_example.py @@ -1,5 +1,16 @@ -from playwright.sync_api import Page, expect +from playwright.sync_api import Page, expect, sync_playwright + def test_visible_after_with_explicit_waits_with_playwright(page: Page): page.goto('https://demoqa.com/dynamic-properties') - expect(page.locator('//button[text()="Visible After 5 Seconds"]')).to_have_text('Visible After 5 Seconds') \ No newline at end of file + expect(page.locator('//button[text()="Visible After 5 Seconds"]')).to_have_text('Visible After 5 Seconds') + + +def test_my_visible_after_with_explicit_waits_with_playwright(): + with sync_playwright() as p: + browser = p.chromium.launch(headless=False) + page = browser.new_page() + page.goto('https://demoqa.com/dynamic-properties') + expect(page.locator('//button[text()="Visible After 5 Seconds"]')).to_have_text('Visible After 5 Seconds', + timeout=15000) + browser.close() diff --git a/lesson3/requirements.txt b/lesson3/requirements.txt index 5a0b33c..87845cc 100644 --- a/lesson3/requirements.txt +++ b/lesson3/requirements.txt @@ -3,11 +3,13 @@ allure-python-commons==2.13.5 attrs==24.2.0 certifi==2024.8.30 charset-normalizer==3.4.0 +Faker==32.1.0 future==1.0.0 greenlet==3.1.1 h11==0.14.0 idna==3.10 iniconfig==2.0.0 +loguru==0.7.2 outcome==1.3.0.post0 packaging==24.1 playwright==1.48.0 @@ -17,10 +19,13 @@ PySocks==1.7.1 pytest==8.3.3 pytest-base-url==2.1.0 pytest-playwright==0.5.2 +python-dateutil==2.9.0.post0 python-slugify==8.0.4 requests==2.32.3 +ruff==0.7.1 selene==2.0.0rc9 selenium==4.26.1 +six==1.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 text-unidecode==1.3 diff --git a/lesson3/waits/__init__.py b/lesson3/waits/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson3/waits/hw3/__init__.py b/lesson3/waits/hw3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson3/waits/hw3/selenium/__init__.py b/lesson3/waits/hw3/selenium/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson3/waits/hw3/selenium/test_wait_expl.py b/lesson3/waits/hw3/selenium/test_wait_expl.py new file mode 100644 index 0000000..84ff61a --- /dev/null +++ b/lesson3/waits/hw3/selenium/test_wait_expl.py @@ -0,0 +1,72 @@ +from selenium.webdriver.common.by import By +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait +from selenium import webdriver +from selenium.webdriver.chrome.options import Options +import pytest + + +@pytest.fixture +def chrome_options(): + options = Options() + options.add_argument("--incognito") + options.add_argument("--window-size=1920,1080") + return options + + +@pytest.fixture +def driver(chrome_options): + driver = webdriver.Chrome(options=chrome_options) + yield driver + driver.quit() + + +@pytest.fixture +def wait(driver): + wait = WebDriverWait(driver, timeout=10) + return wait + + +def test_registration(driver, wait): + # Перейти по URL: Открыть в браузере указанный URL сайта https://victoretc.github.io/selenium_waits/ + # Проверить заголовок: Убедиться, что текст в теге + driver.get("https://victoretc.github.io/selenium_waits/") + title = driver.find_element(By.XPATH, "//h1[text()= 'Практика с ожиданиями в Selenium']") + assert title.text == 'Практика с ожиданиями в Selenium' + + # Дождаться появления кнопки "Начать тестирование" + # Найти кнопку: Найти на странице кнопку с текстом "Начать тестирование". + begin_test_btn = wait.until(EC.visibility_of_element_located((By.XPATH, "//button[@id='startTest']"))) + assert begin_test_btn.is_displayed() + assert begin_test_btn.text == 'Начать тестирование' + + # Кликнуть по кнопке "Начать тестирование". + begin_test_btn.click() + login = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[@for='login']"))) + + assert login.is_displayed() + + # Ввести "login" в поле для логина. + login_field = driver.find_element(By.XPATH, "//*[@id='login']") + login_field.send_keys("email") + + # Ввести "password" в поле для пароля. + password_field = driver.find_element(By.XPATH, "//*[@id='password']") + password_field.send_keys("password") + + # Установить флажок в чекбокс "Согласен со всеми правилами". + check_box_agree = driver.find_element(By.XPATH, "//*[@id='agree']") + check_box_agree.click() + + # Нажать кнопку "Зарегистрироваться". + registration_btn = driver.find_element(By.XPATH, "//*[@id='register']") + registration_btn.click() + + # Удостовериться, что появился индикатор загрузки. + loader_indicator = driver.find_element(By.XPATH, "//*[@id='loader']") + assert loader_indicator.is_displayed() + + # Убедиться, что после завершения загрузки появилось сообщение "Вы успешно зарегистрированы". + success_registration = wait.until(EC.visibility_of_element_located((By.XPATH, "//*[@id='successMessage']"))) + assert success_registration.is_displayed() + assert success_registration.text == 'Вы успешно зарегистрированы!' diff --git a/lesson3/waits/hw3/selenium/test_wait_impl.py b/lesson3/waits/hw3/selenium/test_wait_impl.py new file mode 100644 index 0000000..fe346cd --- /dev/null +++ b/lesson3/waits/hw3/selenium/test_wait_impl.py @@ -0,0 +1,116 @@ +import time + +from selenium.webdriver.common.by import By +from selenium import webdriver +from selenium.webdriver.chrome.options import Options +import pytest + + +@pytest.fixture +def chrome_options(): + options = Options() + options.add_argument("--incognito") + options.add_argument("--window-size=1920,1080") + return options + + +@pytest.fixture +def driver(chrome_options): + driver = webdriver.Chrome(options=chrome_options) + driver.implicitly_wait(10) + yield driver + driver.quit() + + +def test_registration(driver): + # Перейти по URL: Открыть в браузере указанный URL сайта https://victoretc.github.io/selenium_waits/ + # Проверить заголовок: Убедиться, что текст в теге + driver.get("https://victoretc.github.io/selenium_waits/") + title = driver.find_element(By.XPATH, "//h1[text()= 'Практика с ожиданиями в Selenium']") + assert title.text == 'Практика с ожиданиями в Selenium' + + # Дождаться появления кнопки "Начать тестирование" + # Найти кнопку: Найти на странице кнопку с текстом "Начать тестирование". + # Кликнуть по кнопке "Начать тестирование". + start_test_btn = driver.find_element(By.XPATH, "//button[@id='startTest']") + start_test_btn.click() + + login = driver.find_element(By.XPATH, "//*[@for='login']") + assert login.is_displayed() + + # Ввести "login" в поле для логина. + login_field = driver.find_element(By.XPATH, "//*[@id='login']") + login_field.send_keys("email") + + # Ввести "password" в поле для пароля. + password_field = driver.find_element(By.XPATH, "//*[@id='password']") + password_field.send_keys("password") + + # Установить флажок в чекбокс "Согласен со всеми правилами". + check_box_agree = driver.find_element(By.XPATH, "//*[@id='agree']") + check_box_agree.click() + + # Нажать кнопку "Зарегистрироваться". + registration_btn = driver.find_element(By.XPATH, "//*[@id='register']") + registration_btn.click() + + # Удостовериться, что появился индикатор загрузки. + loader_indicator = driver.find_element(By.XPATH, "//*[@id='loader']") + assert loader_indicator.is_displayed() + + time.sleep(5) + + # Убедиться, что после завершения загрузки появилось сообщение "Вы успешно зарегистрированы". + success_registration = driver.find_element(By.XPATH, "//*[@id='successMessage']") + assert success_registration.is_displayed() + assert success_registration.text == 'Вы успешно зарегистрированы!' + + +def test_registration1(driver): + try: + # 1. Переходим на сайт + driver.get('https://victoretc.github.io/selenium_waits/') + + # 2. Проверяем заголовок страницы + assert "Практика Selenium" in driver.title, "Заголовок страницы не совпадает" + + # 3. Ждем появления кнопки "Начать тестирование" + # Убедимся, что кнопка присутствует на странице + start_testing_button = driver.find_element(By.XPATH, "//button[text()='Начать тестирование']") + + # 4. Кликаем по кнопке "Начать тестирование" + start_testing_button.click() + + # 5. Вводим логин в поле для логина + login_field = driver.find_element(By.XPATH, "//*[@id='login']") + login_field.send_keys('login') + + # 6. Вводим пароль в поле для пароля + password_field = driver.find_element(By.XPATH, "//*[@id='password']") + password_field.send_keys('password') + + # 7. Устанавливаем флажок "Согласен со всеми правилами" + agree_checkbox = driver.find_element(By.XPATH, "//*[@id='agree']") + if not agree_checkbox.is_selected(): + agree_checkbox.click() + + # 8. Нажимаем кнопку "Зарегистрироваться" + register_button = driver.find_element(By.XPATH, "//*[@id='register']") + register_button.click() + + # 9. Проверяем наличие индикатора загрузки + loading_indicator = driver.find_element(By.XPATH, "//*[@id='loader']") # Пример ID для индикатора + assert loading_indicator.is_displayed(), "Индикатор загрузки не отображается" + + # 10. Ждем завершения загрузки и появления сообщения о успешной регистрации + time.sleep(5) # Ожидаем, что индикатор загрузки исчезнет + + # 11. Проверяем сообщение о успешной регистрации + success_message = driver.find_element(By.XPATH, "//*[@id='successMessage']") + assert success_message.is_displayed(), "Сообщение об успешной регистрации не появилось" + + print("Тест прошел успешно!") + + finally: + # Закрываем браузер + driver.quit() diff --git a/lesson3/waits/hw3/selenium/test_wait_time_sleep.py b/lesson3/waits/hw3/selenium/test_wait_time_sleep.py new file mode 100644 index 0000000..2682515 --- /dev/null +++ b/lesson3/waits/hw3/selenium/test_wait_time_sleep.py @@ -0,0 +1,53 @@ +import time +from selenium.webdriver.common.by import By + + +def test_registration(driver): + # Перейти по URL: Открыть в браузере указанный URL сайта https://victoretc.github.io/selenium_waits/ + # Проверить заголовок: Убедиться, что текст в теге + driver.get("https://victoretc.github.io/selenium_waits/") + title = driver.find_element(By.XPATH, "//h1[text()= 'Практика с ожиданиями в Selenium']") + assert title.text == 'Практика с ожиданиями в Selenium' + time.sleep(5) + + # Дождаться появления кнопки "Начать тестирование" + # Найти кнопку: Найти на странице кнопку с текстом "Начать тестирование". + begin_test_btn = driver.find_element(By.XPATH, "//button[@id='startTest']") + assert begin_test_btn.is_displayed() + assert begin_test_btn.text == 'Начать тестирование' + + # Кликнуть по кнопке "Начать тестирование". + begin_test_btn.click() + time.sleep(5) + login = driver.find_element(By.XPATH, "//*[@for='login']") + assert login.is_displayed() + + # Ввести "login" в поле для логина. + login_field = driver.find_element(By.XPATH, "//*[@id='login']") + login_field.send_keys("email") + time.sleep(3) + + # Ввести "password" в поле для пароля. + password_field = driver.find_element(By.XPATH, "//*[@id='password']") + password_field.send_keys("password") + time.sleep(3) + + # Установить флажок в чекбокс "Согласен со всеми правилами". + check_box_agree = driver.find_element(By.XPATH, "//*[@id='agree']") + check_box_agree.click() + time.sleep(3) + + # Нажать кнопку "Зарегистрироваться". + registration_btn = driver.find_element(By.XPATH, "//*[@id='register']") + registration_btn.click() + time.sleep(2) + + # Удостовериться, что появился индикатор загрузки. + loader_indicator = driver.find_element(By.XPATH, "//*[@id='loader']") + assert loader_indicator.is_displayed() + time.sleep(5) + + # Убедиться, что после завершения загрузки появилось сообщение "Вы успешно зарегистрированы". + success_registration = driver.find_element(By.XPATH, "//*[@id='successMessage']") + assert success_registration.is_displayed() + assert success_registration.text == 'Вы успешно зарегистрированы!' diff --git a/lesson3/waits/hw3/selenium/test_waits_practice.py b/lesson3/waits/hw3/selenium/test_waits_practice.py new file mode 100644 index 0000000..e08df42 --- /dev/null +++ b/lesson3/waits/hw3/selenium/test_waits_practice.py @@ -0,0 +1,147 @@ +import time +import requests + +import pytest +from selenium.webdriver.chrome.options import Options +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC + + +@pytest.fixture +def chrome_options(): + options = Options() + options.add_argument("--window-size=1900x1000") + return options + + +@pytest.fixture +def driver(chrome_options): + driver = webdriver.Chrome(options=chrome_options) + driver.implicitly_wait(10) + yield driver + driver.quit() + + +@pytest.fixture +def wait(driver): + wait = WebDriverWait(driver, timeout=10) + return wait + + +def test1(driver, wait): + driver.get("https://www.selenium.dev/selenium/web/dynamic.html") + add_box_locator = "//*[@value = 'Add a box!']" + box_locator = "//div[contains(@id, 'box')]" + + add_box = wait.until(EC.visibility_of_element_located((By.XPATH, add_box_locator))) + assert add_box.is_displayed() + assert add_box.get_attribute("value") == 'Add a box!' + + lst = [] + add_box.click() + box = wait.until(EC.visibility_of_element_located((By.XPATH, box_locator))) + lst.append(box) + count = 1 + + add_box.click() + lst.append(box) + count += 1 + assert len(lst) == count + + +def test2(driver, wait): + driver.get("https://demoqa.com/dynamic-properties") + will_enable_5sec_locator = "//*[@id = 'enableAfter']" + + will_enable_5sec_btn = wait.until(EC.visibility_of_element_located((By.XPATH, will_enable_5sec_locator))) + assert will_enable_5sec_btn.is_displayed() + + +def test3(driver, wait): + driver.get("https://the-internet.herokuapp.com/dynamic_loading") + assert driver.title == "The Internet" + + hidden_element_locator = "//*[contains(text(), 'Element on page that is hidden')]" + start_btn_locator = "//*[contains(text(), 'Start')]" + loading_indicator_locator = "//*[@id = 'loading']" + hello_world_locator = "//*[contains(text(), 'Hello World!')]" + + hidden_element = wait.until(EC.element_to_be_clickable((By.XPATH, hidden_element_locator))) + hidden_element.click() + + start_btn = wait.until(EC.element_to_be_clickable((By.XPATH, start_btn_locator))) + assert start_btn.is_enabled() + start_btn.click() + + loading_indicator = wait.until(EC.visibility_of_element_located((By.XPATH, loading_indicator_locator))) + assert loading_indicator.is_displayed() + + hello_world = wait.until(EC.visibility_of_element_located((By.XPATH, hello_world_locator))) + assert hello_world.is_displayed() + + +# 1. (Необходимо создать и удалить элемент) +def test4(driver, wait): + driver.get("https://the-internet.herokuapp.com/add_remove_elements/") + add_element_btn_locator = "//*[@onclick= 'addElement()']" + delete_btn_locator = "//*[@onclick= 'deleteElement()']" + add_element = wait.until(EC.element_to_be_clickable((By.XPATH, add_element_btn_locator))) + add_element.click() + delete_btn = wait.until(EC.element_to_be_clickable((By.XPATH, delete_btn_locator))) + delete_btn.click() + assert wait.until(EC.invisibility_of_element_located((By.XPATH, delete_btn_locator))) + + +# 2. (Необходимо пройти базовую авторизацию) +# (NOT CLEAR) +def test5(driver, wait): + username = "admin" + password = "admin" + + url = f"http://{username}:{password}@the-internet.herokuapp.com/basic_auth" + title_locator = "//*[text()='Basic Auth']" + + driver.get(url) + time.sleep(2) + title = wait.until(EC.visibility_of_element_located((By.XPATH, title_locator))) + assert title.text == "Basic Auth" + + +# 3. (Необходимо найти сломанные изображения) +# (NOT CLEAR) +def test6(driver, wait): + driver.get("https://the-internet.herokuapp.com/broken_images") + + image_locator = "//div/img" + images = wait.until(EC.visibility_of_all_elements_located((By.XPATH, image_locator))) + + broken_images = [] + + for i in images: + src = i.get_attribute("src") + + response = requests.get(src) + if response.status_code != 200 or response.status_code == 404: + broken_images.append(src) + + assert len(broken_images) == 2 + + +# 4. (Практика с чек боксами) +def test7(driver, wait): + driver.get("https://the-internet.herokuapp.com/checkboxes") + + check_boxs_locator = "//*[@type = 'checkbox']" + check_boxs = wait.until(EC.visibility_of_all_elements_located((By.XPATH, check_boxs_locator))) + + for check_box in check_boxs: + if not check_box.is_selected(): + check_box.click() + assert check_box.is_selected() + + for check_box in check_boxs: + check_box.click() + assert not check_box.is_selected() + time.sleep(2) diff --git a/lesson3/waits/test_expl.py b/lesson3/waits/test_expl.py index 2ca066a..a24801e 100644 --- a/lesson3/waits/test_expl.py +++ b/lesson3/waits/test_expl.py @@ -1,3 +1,4 @@ +# Явные ожидания from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By @@ -5,28 +6,28 @@ from selenium.webdriver.support import expected_conditions as EC import pytest + @pytest.fixture def chrome_options(): options = Options() options.add_argument('--start-maximized') return options + @pytest.fixture def driver(chrome_options): driver = webdriver.Chrome(options=chrome_options) return driver + @pytest.fixture def wait(driver): wait = WebDriverWait(driver, timeout=10) return wait + def test_visible_after_with_explicit_waits(driver, wait): driver.get('https://demoqa.com/dynamic-properties') - visible_after_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']"))) + visible_after_button = wait.until( + EC.element_to_be_clickable((By.XPATH, "//button[text()='Visible After 5 Seconds']"))) assert visible_after_button.text == 'Visible After 5 Seconds' - - - - - diff --git a/lesson3/waits/test_impl.py b/lesson3/waits/test_impl.py index 2db0c4a..a62c723 100644 --- a/lesson3/waits/test_impl.py +++ b/lesson3/waits/test_impl.py @@ -1,14 +1,17 @@ +# неявные ожидания from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By import pytest + @pytest.fixture def chrome_options(): options = Options() options.add_argument('--start-maximized') return options + @pytest.fixture def driver(chrome_options): driver = webdriver.Chrome(options=chrome_options) @@ -16,12 +19,20 @@ def driver(chrome_options): yield driver driver.quit() + def test_visible_after_with_implicit_wait(driver): driver.get('https://demoqa.com/dynamic-properties') vissible_after_button = driver.find_element(By.XPATH, "//button[text()='Visible After 5 Seconds']") assert vissible_after_button.is_displayed() +def test_will_enable_5sec_implicit_wait(driver): + driver.get('https://demoqa.com/dynamic-properties') + will_enable_5_sec = driver.find_element(By.XPATH, "//*[@id='enableAfter']") + assert will_enable_5_sec.is_displayed() - +def test_color_change_btn_implicit_wait(driver): + driver.get('https://demoqa.com/dynamic-properties') + color_change_btn = driver.find_element(By.XPATH, "//button[@id='colorChange']") + assert color_change_btn.is_displayed() diff --git a/lesson4/__init__.py b/lesson4/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lesson4/components/header.py b/lesson4/components/header.py index 65d84e2..53a8df8 100644 --- a/lesson4/components/header.py +++ b/lesson4/components/header.py @@ -1,17 +1,23 @@ from selene import by, be, have, browser -from core.settings import settings +from lesson4.core.settings import settings +import allure + +@allure.step("Открываем Хэдер на главной странице") def visit(): browser.open('/') +@allure.step("Проверяем открытие Хэдера") def should_be_opened(): browser.should(have.url(settings.base_url)) +@allure.step("Открываем фщрму регистрации") def open_registration_component(): browser.element(by.text('Регистрация')).click() +@allure.step("Проверяем видимость кнопки создания объявления") def create_post_button_should_be_visible(): - browser.element(by.text('Создать объявление')).should(be.visible) \ No newline at end of file + browser.element(by.text('Создать объявление')).should(be.visible) diff --git a/lesson4/components/register.py b/lesson4/components/register.py index b79ace1..ee426bf 100644 --- a/lesson4/components/register.py +++ b/lesson4/components/register.py @@ -1,40 +1,39 @@ from selene import be, have, browser +import allure +@allure.step("Открываем форму регистрации") def visit(): browser.open('/signup/') +@allure.step("Проверяем открытие формы регистрации") def should_be_opened(): browser.should(have.url('/signup/')) +@allure.step("Вводим логин") def type_login(login): browser.element('#id_username').type(login) +@allure.step("Вводим пароль") def type_password(password): browser.element('#id_password1').type(password) +@allure.step("Вводим подтверждение пароля") def type_confirm_password(password): browser.element('#id_password2').type(password) +@allure.step("Выбираем роль учителя") def choose_tutor_role(): checkbox = browser.element('#id_is_tutor') checkbox.click() checkbox.should(be.selected) +@allure.step("Нажимаем кнопку регистрации") def click_register_button(): browser.element('button[type="submit"]').click() - - - - - - - - - diff --git a/lesson4/core/settings.py b/lesson4/core/settings.py index 15280a3..d076dcc 100644 --- a/lesson4/core/settings.py +++ b/lesson4/core/settings.py @@ -1,4 +1,8 @@ from pydantic_settings import BaseSettings, SettingsConfigDict +import os +from dotenv import load_dotenv + +load_dotenv() class Settings(BaseSettings): @@ -12,3 +16,4 @@ class Settings(BaseSettings): settings = Settings() +# settings = Settings(base_url="http://195.133.27.184/", register_password="Pknewbkj1212234112****") diff --git a/lesson4/pytest.ini b/lesson4/pytest.ini index a06f653..dadbce1 100644 --- a/lesson4/pytest.ini +++ b/lesson4/pytest.ini @@ -1,3 +1,8 @@ [pytest] -addopts = -s -vv --alluredir=allure-results --clean-alluredir \ No newline at end of file +addopts = -s -vv --alluredir=allure-results --clean-alluredir + + +# посмотреть репорт allure serve + +# почистить алюр rm -r allure-result \ No newline at end of file diff --git a/lesson4/requirements.txt b/lesson4/requirements.txt index 5c407df..2bcb0e1 100644 --- a/lesson4/requirements.txt +++ b/lesson4/requirements.txt @@ -1,23 +1,39 @@ allure-pytest==2.13.5 allure-python-commons==2.13.5 +annotated-types==0.7.0 attrs==24.2.0 certifi==2024.8.30 +charset-normalizer==3.4.0 Faker==30.8.2 future==1.0.0 +greenlet==3.1.1 h11==0.14.0 idna==3.10 iniconfig==2.0.0 +loguru==0.7.2 outcome==1.3.0.post0 packaging==24.2 +playwright==1.48.0 pluggy==1.5.0 +pydantic==2.9.2 +pydantic-settings==2.6.1 +pydantic_core==2.23.4 +pyee==12.0.0 PySocks==1.7.1 pytest==8.3.3 +pytest-base-url==2.1.0 +pytest-playwright==0.5.2 python-dateutil==2.9.0.post0 +python-dotenv==1.0.1 +python-slugify==8.0.4 +requests==2.32.3 +ruff==0.7.1 selene==2.0.0rc9 selenium==4.26.1 six==1.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 +text-unidecode==1.3 trio==0.27.0 trio-websocket==0.11.1 typing_extensions==4.12.2 diff --git a/lesson4/tests/conftest.py b/lesson4/tests/conftest.py index cb42485..098d201 100644 --- a/lesson4/tests/conftest.py +++ b/lesson4/tests/conftest.py @@ -2,11 +2,11 @@ from selene import browser, support from selenium import webdriver import allure_commons -import allure +import allure + @pytest.fixture(autouse=True) def browser_management(): - options = webdriver.ChromeOptions() # options.add_argument('--headless') browser.config.driver_options = options @@ -18,7 +18,7 @@ def browser_management(): browser.config._wait_decorator = support._logging.wait_with( context=allure_commons._allure.StepContext ) - + yield allure.attach( diff --git a/lesson4/tests/test_register.py b/lesson4/tests/test_register.py index 0fe644b..7c974f4 100644 --- a/lesson4/tests/test_register.py +++ b/lesson4/tests/test_register.py @@ -1,8 +1,12 @@ +from lesson4.components import header, register +from lesson4.core.settings import settings +import allure from faker import Faker + fake = Faker() -from components import header, register -from core.settings import settings + +@allure.title("Регистрация") def test_register(): # main page header.visit()