test: simplify E2E tests - login per test (pytest-asyncio compatibility)

This commit is contained in:
root 2026-03-29 23:51:55 +00:00
parent 204f9f26de
commit adcb22dc75
2 changed files with 128 additions and 107 deletions

View File

@ -4,21 +4,15 @@ E2E тесты для Kwork API.
Требуют реальных credentials и запускаются только локально. Требуют реальных credentials и запускаются только локально.
""" """
import asyncio
import os import os
from pathlib import Path from pathlib import Path
import pytest import pytest
from dotenv import load_dotenv from dotenv import load_dotenv
from kwork_api import KworkClient
# Загружаем .env # Загружаем .env
load_dotenv(Path(__file__).parent / ".env") load_dotenv(Path(__file__).parent / ".env")
# Отключаем auto mode для pytest-asyncio чтобы использовать один event loop
pytest_plugins = ('pytest_asyncio',)
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def kwork_credentials(): def kwork_credentials():
@ -40,40 +34,6 @@ def require_credentials(kwork_credentials):
return 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") @pytest.fixture(scope="function")
def slowmo(request): def slowmo(request):
"""Задержка между тестами для rate limiting.""" """Задержка между тестами для rate limiting."""

View File

@ -11,11 +11,17 @@ from kwork_api import KworkClient
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_catalog_list(client): async def test_get_catalog_list(require_credentials):
"""E2E: Получить список кворков из каталога. """E2E: Получить список кворков из каталога.
HAR: POST https://api.kwork.ru/catalogMainv2 HAR: POST https://api.kwork.ru/catalogMainv2
""" """
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
try:
# Первая страница каталога # Первая страница каталога
catalog = await client.catalog.get_list(page=1) catalog = await client.catalog.get_list(page=1)
@ -27,33 +33,54 @@ async def test_get_catalog_list(client):
assert first_kwork.id is not None assert first_kwork.id is not None
assert first_kwork.title is not None assert first_kwork.title is not None
assert first_kwork.price is not None assert first_kwork.price is not None
finally:
await client.close()
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_kwork_details(client, catalog_kwork_id): async def test_get_kwork_details(require_credentials):
"""E2E: Получить детали кворка. """E2E: Получить детали кворка.
HAR: POST https://api.kwork.ru/getKworkDetails HAR: POST https://api.kwork.ru/getKworkDetails
""" """
# Пропускаем если каталог пустой client = await KworkClient.login(
if catalog_kwork_id is None: 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") pytest.skip("Catalog is empty")
kwork_id = catalog.kworks[0].id
# Получаем детали # Получаем детали
details = await client.catalog.get_details(catalog_kwork_id) details = await client.catalog.get_details(kwork_id)
assert details is not None assert details is not None
assert details.id == catalog_kwork_id assert details.id == kwork_id
assert details.title is not None assert details.title is not None
assert details.price is not None assert details.price is not None
finally:
await client.close()
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_projects_list(client): async def test_get_projects_list(require_credentials):
"""E2E: Получить список проектов с биржи. """E2E: Получить список проектов с биржи.
HAR: POST https://api.kwork.ru/projects HAR: POST https://api.kwork.ru/projects
""" """
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
try:
projects = await client.projects.get_list(page=1) projects = await client.projects.get_list(page=1)
assert projects is not None assert projects is not None
@ -62,22 +89,32 @@ async def test_get_projects_list(client):
first_project = projects.projects[0] first_project = projects.projects[0]
assert first_project.id is not None assert first_project.id is not None
assert first_project.title is not None assert first_project.title is not None
finally:
await client.close()
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_user_info(client): async def test_get_user_info(require_credentials):
"""E2E: Получить информацию о текущем пользователе. """E2E: Получить информацию о текущем пользователе.
HAR: POST https://api.kwork.ru/user HAR: POST https://api.kwork.ru/user
""" """
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
try:
user = await client.user.get_info() user = await 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)
finally:
await client.close()
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_reference_data(client): async def test_get_reference_data(require_credentials):
"""E2E: Получить справочные данные (города, страны, фичи). """E2E: Получить справочные данные (города, страны, фичи).
HAR endpoints: HAR endpoints:
@ -86,6 +123,12 @@ async def test_get_reference_data(client):
- POST https://api.kwork.ru/getAvailableFeatures - POST https://api.kwork.ru/getAvailableFeatures
- POST https://api.kwork.ru/getBadgesInfo - POST https://api.kwork.ru/getBadgesInfo
""" """
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
try:
# Города (может вернуть пустой список) # Города (может вернуть пустой список)
cities = await client.reference.get_cities() cities = await client.reference.get_cities()
assert isinstance(cities, list) assert isinstance(cities, list)
@ -101,28 +144,44 @@ async def test_get_reference_data(client):
# Бейджи # Бейджи
badges = await client.reference.get_badges_info() badges = await client.reference.get_badges_info()
assert isinstance(badges, list) assert isinstance(badges, list)
finally:
await client.close()
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_notifications(client): async def test_get_notifications(require_credentials):
"""E2E: Получить уведомления. """E2E: Получить уведомления.
HAR: POST https://api.kwork.ru/notifications HAR: POST https://api.kwork.ru/notifications
""" """
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
try:
notifications = await client.notifications.get_list() notifications = await client.notifications.get_list()
assert notifications is not None assert notifications is not None
# Уведомления могут быть пустыми # Уведомления могут быть пустыми
assert hasattr(notifications, 'notifications') assert hasattr(notifications, 'notifications')
finally:
await client.close()
@pytest.mark.e2e @pytest.mark.e2e
async def test_get_user_orders(client): async def test_get_user_orders(require_credentials):
"""E2E: Получить заказы пользователя. """E2E: Получить заказы пользователя.
HAR endpoints: HAR endpoints:
- POST https://api.kwork.ru/payerOrders - POST https://api.kwork.ru/payerOrders
- POST https://api.kwork.ru/workerOrders - POST https://api.kwork.ru/workerOrders
""" """
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
try:
# Заказы как заказчик # Заказы как заказчик
payer_orders = await client.projects.get_payer_orders() payer_orders = await client.projects.get_payer_orders()
assert isinstance(payer_orders, list) assert isinstance(payer_orders, list)
@ -130,3 +189,5 @@ async def test_get_user_orders(client):
# Заказы как исполнитель # Заказы как исполнитель
worker_orders = await client.projects.get_worker_orders() worker_orders = await client.projects.get_worker_orders()
assert isinstance(worker_orders, list) assert isinstance(worker_orders, list)
finally:
await client.close()