From adcb22dc75586898ff7068c9cc7c1920453d352c Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Mar 2026 23:51:55 +0000 Subject: [PATCH] test: simplify E2E tests - login per test (pytest-asyncio compatibility) --- tests/e2e/conftest.py | 40 -------- tests/e2e/test_catalog.py | 195 +++++++++++++++++++++++++------------- 2 files changed, 128 insertions(+), 107 deletions(-) diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index 1517811..1af71d7 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -4,21 +4,15 @@ E2E тесты для Kwork API. Требуют реальных credentials и запускаются только локально. """ -import asyncio import os from pathlib import Path import pytest from dotenv import load_dotenv -from kwork_api import KworkClient - # Загружаем .env load_dotenv(Path(__file__).parent / ".env") -# Отключаем auto mode для pytest-asyncio чтобы использовать один event loop -pytest_plugins = ('pytest_asyncio',) - @pytest.fixture(scope="session") def kwork_credentials(): @@ -40,40 +34,6 @@ def require_credentials(kwork_credentials): return kwork_credentials -@pytest.fixture(scope="module") -def client(require_credentials): - """ - E2E клиент для всех тестов в модуле. - - Авторизуется один раз и переиспользуется во всех тестах модуля. - """ - async def create_client(): - return await KworkClient.login( - username=require_credentials["username"], - password=require_credentials["password"], - ) - - client = asyncio.run(create_client()) - yield client - asyncio.run(client.close()) - - -@pytest.fixture(scope="module") -def catalog_kwork_id(client): - """ - Получить ID первого кворка из каталога для тестов. - - Переиспользуется во всех тестах модуля. - """ - async def get_first_kwork(): - catalog = await client.catalog.get_list(page=1) - if len(catalog.kworks) > 0: - return catalog.kworks[0].id - return None - - return asyncio.run(get_first_kwork()) - - @pytest.fixture(scope="function") def slowmo(request): """Задержка между тестами для rate limiting.""" diff --git a/tests/e2e/test_catalog.py b/tests/e2e/test_catalog.py index 3344c02..4dc5a36 100644 --- a/tests/e2e/test_catalog.py +++ b/tests/e2e/test_catalog.py @@ -11,73 +11,110 @@ from kwork_api import KworkClient @pytest.mark.e2e -async def test_get_catalog_list(client): +async def test_get_catalog_list(require_credentials): """E2E: Получить список кворков из каталога. HAR: POST https://api.kwork.ru/catalogMainv2 """ - # Первая страница каталога - catalog = await client.catalog.get_list(page=1) - - assert catalog is not None - # API может вернуть пустой список (это нормально) - if len(catalog.kworks) > 0: - # Проверка структуры первого кворка - first_kwork = catalog.kworks[0] - assert first_kwork.id is not None - assert first_kwork.title is not None - assert first_kwork.price is not None + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + # Первая страница каталога + catalog = await client.catalog.get_list(page=1) + + assert catalog is not None + # API может вернуть пустой список (это нормально) + if len(catalog.kworks) > 0: + # Проверка структуры первого кворка + first_kwork = catalog.kworks[0] + assert first_kwork.id is not None + assert first_kwork.title is not None + assert first_kwork.price is not None + finally: + await client.close() @pytest.mark.e2e -async def test_get_kwork_details(client, catalog_kwork_id): +async def test_get_kwork_details(require_credentials): """E2E: Получить детали кворка. HAR: POST https://api.kwork.ru/getKworkDetails """ - # Пропускаем если каталог пустой - if catalog_kwork_id is None: - pytest.skip("Catalog is empty") - - # Получаем детали - details = await client.catalog.get_details(catalog_kwork_id) - - assert details is not None - assert details.id == catalog_kwork_id - assert details.title is not None - assert details.price is not None + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + # Сначала получаем каталог чтобы найти реальный ID + catalog = await client.catalog.get_list(page=1) + + # Если каталог пустой - пропускаем тест + if len(catalog.kworks) == 0: + pytest.skip("Catalog is empty") + + kwork_id = catalog.kworks[0].id + + # Получаем детали + details = await client.catalog.get_details(kwork_id) + + assert details is not None + assert details.id == kwork_id + assert details.title is not None + assert details.price is not None + finally: + await client.close() @pytest.mark.e2e -async def test_get_projects_list(client): +async def test_get_projects_list(require_credentials): """E2E: Получить список проектов с биржи. HAR: POST https://api.kwork.ru/projects """ - projects = await client.projects.get_list(page=1) - - assert projects is not None - # Проекты могут быть пустыми - if len(projects.projects) > 0: - first_project = projects.projects[0] - assert first_project.id is not None - assert first_project.title is not None + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + projects = await client.projects.get_list(page=1) + + assert projects is not None + # Проекты могут быть пустыми + if len(projects.projects) > 0: + first_project = projects.projects[0] + assert first_project.id is not None + assert first_project.title is not None + finally: + await client.close() @pytest.mark.e2e -async def test_get_user_info(client): +async def test_get_user_info(require_credentials): """E2E: Получить информацию о текущем пользователе. HAR: POST https://api.kwork.ru/user """ - user = await client.user.get_info() - assert user is not None - # API возвращает dict с данными пользователя - assert isinstance(user, dict) + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + user = await client.user.get_info() + assert user is not None + # API возвращает dict с данными пользователя + assert isinstance(user, dict) + finally: + await client.close() @pytest.mark.e2e -async def test_get_reference_data(client): +async def test_get_reference_data(require_credentials): """E2E: Получить справочные данные (города, страны, фичи). HAR endpoints: @@ -86,47 +123,71 @@ async def test_get_reference_data(client): - POST https://api.kwork.ru/getAvailableFeatures - POST https://api.kwork.ru/getBadgesInfo """ - # Города (может вернуть пустой список) - cities = await client.reference.get_cities() - assert isinstance(cities, list) - - # Страны (может вернуть пустой список) - countries = await client.reference.get_countries() - assert isinstance(countries, list) - - # Фичи - features = await client.reference.get_features() - assert isinstance(features, list) - - # Бейджи - badges = await client.reference.get_badges_info() - assert isinstance(badges, list) + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + # Города (может вернуть пустой список) + cities = await client.reference.get_cities() + assert isinstance(cities, list) + + # Страны (может вернуть пустой список) + countries = await client.reference.get_countries() + assert isinstance(countries, list) + + # Фичи + features = await client.reference.get_features() + assert isinstance(features, list) + + # Бейджи + badges = await client.reference.get_badges_info() + assert isinstance(badges, list) + finally: + await client.close() @pytest.mark.e2e -async def test_get_notifications(client): +async def test_get_notifications(require_credentials): """E2E: Получить уведомления. HAR: POST https://api.kwork.ru/notifications """ - notifications = await client.notifications.get_list() - assert notifications is not None - # Уведомления могут быть пустыми - assert hasattr(notifications, 'notifications') + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + notifications = await client.notifications.get_list() + assert notifications is not None + # Уведомления могут быть пустыми + assert hasattr(notifications, 'notifications') + finally: + await client.close() @pytest.mark.e2e -async def test_get_user_orders(client): +async def test_get_user_orders(require_credentials): """E2E: Получить заказы пользователя. HAR endpoints: - POST https://api.kwork.ru/payerOrders - POST https://api.kwork.ru/workerOrders """ - # Заказы как заказчик - payer_orders = await client.projects.get_payer_orders() - assert isinstance(payer_orders, list) - - # Заказы как исполнитель - worker_orders = await client.projects.get_worker_orders() - assert isinstance(worker_orders, list) + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"], + ) + + try: + # Заказы как заказчик + payer_orders = await client.projects.get_payer_orders() + assert isinstance(payer_orders, list) + + # Заказы как исполнитель + worker_orders = await client.projects.get_worker_orders() + assert isinstance(worker_orders, list) + finally: + await client.close()