test: use E2EClient wrapper for proper event loop management

This commit is contained in:
root 2026-03-30 00:11:01 +00:00
parent 6b86767606
commit 83d6c7d774
2 changed files with 34 additions and 21 deletions

View File

@ -17,6 +17,21 @@ from kwork_api import KworkClient
load_dotenv(Path(__file__).parent / ".env") load_dotenv(Path(__file__).parent / ".env")
class E2EClient:
"""Wrapper for KworkClient that manages event loop lifecycle."""
def __init__(self, client: KworkClient):
self.client = client
self.loop = asyncio.new_event_loop()
def __getattr__(self, name):
return getattr(self.client, name)
def close(self):
self.loop.run_until_complete(self.client.close())
self.loop.close()
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def kwork_credentials(): def kwork_credentials():
"""Credentials для тестового аккаунта.""" """Credentials для тестового аккаунта."""
@ -44,7 +59,7 @@ def e2e_client(require_credentials):
Используется во всех тестах кроме test_auth.py (там тестируем сам логин). Используется во всех тестах кроме test_auth.py (там тестируем сам логин).
""" """
import asyncio loop = asyncio.new_event_loop()
async def create(): async def create():
return await KworkClient.login( return await KworkClient.login(
@ -52,9 +67,11 @@ def e2e_client(require_credentials):
password=require_credentials["password"], password=require_credentials["password"],
) )
client = asyncio.new_event_loop().run_until_complete(create()) client = loop.run_until_complete(create())
yield client wrapper = E2EClient(client)
asyncio.new_event_loop().run_until_complete(client.close()) yield wrapper
wrapper.close()
loop.close()
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
@ -64,15 +81,13 @@ def catalog_kwork_id(e2e_client):
Выполняется ОДИН РАЗ в начале модуля и переиспользуется. Выполняется ОДИН РАЗ в начале модуля и переиспользуется.
""" """
import asyncio
async def get(): async def get():
catalog = await e2e_client.catalog.get_list(page=1) catalog = await e2e_client.catalog.get_list(page=1)
if len(catalog.kworks) > 0: if len(catalog.kworks) > 0:
return catalog.kworks[0].id return catalog.kworks[0].id
return None return None
return asyncio.new_event_loop().run_until_complete(get()) return e2e_client.loop.run_until_complete(get())
@pytest.fixture(scope="function") @pytest.fixture(scope="function")

View File

@ -1,15 +1,13 @@
""" """
E2E тесты для каталога и проектов. E2E тесты для каталога и проектов.
Используют session-scoped e2e_client fixture - логин ОДИН РАЗ для всех тестов. Используют module-scoped e2e_client fixture - логин ОДИН РАЗ для всех тестов модуля.
Все тесты read-only - ничего не изменяют на сервере. Все тесты read-only - ничего не изменяют на сервере.
Endpoints основаны на HAR анализе (mitmproxy + har-analyzer skill). Endpoints основаны на HAR анализе (mitmproxy + har-analyzer skill).
""" """
import pytest import pytest
from kwork_api import KworkClient
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_catalog_list(e2e_client): async def test_get_catalog_list(e2e_client):
@ -18,7 +16,7 @@ async def test_get_catalog_list(e2e_client):
HAR: POST https://api.kwork.ru/catalogMainv2 HAR: POST https://api.kwork.ru/catalogMainv2
""" """
# Первая страница каталога # Первая страница каталога
catalog = await e2e_client.catalog.get_list(page=1) catalog = await e2e_client.client.client.catalog.get_list(page=1)
assert catalog is not None assert catalog is not None
# API может вернуть пустой список (это нормально) # API может вернуть пустой список (это нормально)
@ -41,7 +39,7 @@ async def test_get_kwork_details(e2e_client, catalog_kwork_id):
pytest.skip("Catalog is empty") pytest.skip("Catalog is empty")
# Получаем детали # Получаем детали
details = await e2e_client.catalog.get_details(catalog_kwork_id) details = await e2e_client.client.catalog.get_details(catalog_kwork_id)
assert details is not None assert details is not None
assert details.id == catalog_kwork_id assert details.id == catalog_kwork_id
@ -55,7 +53,7 @@ async def test_get_projects_list(e2e_client):
HAR: POST https://api.kwork.ru/projects HAR: POST https://api.kwork.ru/projects
""" """
projects = await e2e_client.projects.get_list(page=1) projects = await e2e_client.client.projects.get_list(page=1)
assert projects is not None assert projects is not None
# Проекты могут быть пустыми # Проекты могут быть пустыми
@ -71,7 +69,7 @@ async def test_get_user_info(e2e_client):
HAR: POST https://api.kwork.ru/user HAR: POST https://api.kwork.ru/user
""" """
user = await e2e_client.user.get_info() user = await e2e_client.client.user.get_info()
assert user is not None assert user is not None
# API возвращает dict с данными пользователя # API возвращает dict с данными пользователя
assert isinstance(user, dict) assert isinstance(user, dict)
@ -88,19 +86,19 @@ async def test_get_reference_data(e2e_client):
- POST https://api.kwork.ru/getBadgesInfo - POST https://api.kwork.ru/getBadgesInfo
""" """
# Города (может вернуть пустой список) # Города (может вернуть пустой список)
cities = await e2e_client.reference.get_cities() cities = await e2e_client.client.reference.get_cities()
assert isinstance(cities, list) assert isinstance(cities, list)
# Страны (может вернуть пустой список) # Страны (может вернуть пустой список)
countries = await e2e_client.reference.get_countries() countries = await e2e_client.client.reference.get_countries()
assert isinstance(countries, list) assert isinstance(countries, list)
# Фичи # Фичи
features = await e2e_client.reference.get_features() features = await e2e_client.client.reference.get_features()
assert isinstance(features, list) assert isinstance(features, list)
# Бейджи # Бейджи
badges = await e2e_client.reference.get_badges_info() badges = await e2e_client.client.reference.get_badges_info()
assert isinstance(badges, list) assert isinstance(badges, list)
@ -110,7 +108,7 @@ async def test_get_notifications(e2e_client):
HAR: POST https://api.kwork.ru/notifications HAR: POST https://api.kwork.ru/notifications
""" """
notifications = await e2e_client.notifications.get_list() notifications = await e2e_client.client.notifications.get_list()
assert notifications is not None assert notifications is not None
# Уведомления могут быть пустыми # Уведомления могут быть пустыми
assert hasattr(notifications, 'notifications') assert hasattr(notifications, 'notifications')
@ -125,9 +123,9 @@ async def test_get_user_orders(e2e_client):
- POST https://api.kwork.ru/workerOrders - POST https://api.kwork.ru/workerOrders
""" """
# Заказы как заказчик # Заказы как заказчик
payer_orders = await e2e_client.projects.get_payer_orders() payer_orders = await e2e_client.client.projects.get_payer_orders()
assert isinstance(payer_orders, list) assert isinstance(payer_orders, list)
# Заказы как исполнитель # Заказы как исполнитель
worker_orders = await e2e_client.projects.get_worker_orders() worker_orders = await e2e_client.client.projects.get_worker_orders()
assert isinstance(worker_orders, list) assert isinstance(worker_orders, list)