test: reuse authenticated client across E2E tests

- Add session-scoped 'client' fixture for authenticated client
- Add 'catalog_kwork_id' fixture for reusable kwork ID
- Update all catalog tests to use fixtures
- Reduces login calls from 10 to 1 per test session
This commit is contained in:
root 2026-03-29 23:39:05 +00:00
parent 201be98390
commit 034a2e4775
3 changed files with 99 additions and 133 deletions

View File

@ -10,6 +10,8 @@ from pathlib import Path
import pytest
from dotenv import load_dotenv
from kwork_api import KworkClient
# Загружаем .env
load_dotenv(Path(__file__).parent / ".env")
@ -34,6 +36,35 @@ def require_credentials(kwork_credentials):
return kwork_credentials
@pytest.fixture(scope="session")
async def client(require_credentials):
"""
E2E клиент для всех тестов.
Авторизуется один раз и переиспользуется во всех тестах сессии.
"""
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
yield client
await client.close()
@pytest.fixture(scope="session")
async def catalog_kwork_id(client):
"""
Получить ID первого кворка из каталога для тестов.
Переиспользуется во всех тестах сессии.
"""
catalog = await client.catalog.get_list(page=1)
if len(catalog.kworks) > 0:
return catalog.kworks[0].id
else:
return None
@pytest.fixture(scope="function")
def slowmo(request):
"""Задержка между тестами для rate limiting."""

View File

@ -11,114 +11,73 @@ from kwork_api import KworkClient
@pytest.mark.e2e
async def test_get_catalog_list(require_credentials):
async def test_get_catalog_list(client):
"""E2E: Получить список кворков из каталога.
HAR: POST https://api.kwork.ru/catalogMainv2
"""
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
# Первая страница каталога
catalog = await client.catalog.get_list(page=1)
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
# Пагинация
if catalog.pagination:
assert catalog.pagination.current_page >= 1
finally:
await client.close()
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
@pytest.mark.e2e
async def test_get_kwork_details(require_credentials):
async def test_get_kwork_details(client, catalog_kwork_id):
"""E2E: Получить детали кворка.
HAR: POST https://api.kwork.ru/getKworkDetails
"""
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
# Пропускаем если каталог пустой
if catalog_kwork_id is None:
pytest.skip("Catalog is empty")
try:
# Сначала получаем каталог чтобы найти реальный ID
catalog = await client.catalog.get_list(page=1)
# Получаем детали
details = await client.catalog.get_details(catalog_kwork_id)
# Если каталог пустой - пропускаем тест
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()
assert details is not None
assert details.id == catalog_kwork_id
assert details.title is not None
assert details.price is not None
@pytest.mark.e2e
async def test_get_projects_list(require_credentials):
async def test_get_projects_list(client):
"""E2E: Получить список проектов с биржи.
HAR: POST https://api.kwork.ru/projects
"""
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
projects = await client.projects.get_list(page=1)
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()
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
@pytest.mark.e2e
async def test_get_user_info(require_credentials):
async def test_get_user_info(client):
"""E2E: Получить информацию о текущем пользователе.
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()
assert user is not None
# API возвращает dict с данными пользователя
assert isinstance(user, dict)
finally:
await client.close()
user = await client.user.get_info()
assert user is not None
# API возвращает dict с данными пользователя
assert isinstance(user, dict)
@pytest.mark.e2e
async def test_get_reference_data(require_credentials):
async def test_get_reference_data(client):
"""E2E: Получить справочные данные (города, страны, фичи).
HAR endpoints:
@ -127,71 +86,47 @@ async def test_get_reference_data(require_credentials):
- POST https://api.kwork.ru/getAvailableFeatures
- POST https://api.kwork.ru/getBadgesInfo
"""
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
# Города (может вернуть пустой список)
cities = await client.reference.get_cities()
assert isinstance(cities, list)
try:
# Города
cities = await client.reference.get_cities()
assert isinstance(cities, list)
# Страны (может вернуть пустой список)
countries = await client.reference.get_countries()
assert isinstance(countries, list)
# Страны (может вернуть пустой список)
countries = await client.reference.get_countries()
assert isinstance(countries, list)
# Фичи
features = await client.reference.get_features()
assert isinstance(features, 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()
# Бейджи
badges = await client.reference.get_badges_info()
assert isinstance(badges, list)
@pytest.mark.e2e
async def test_get_notifications(require_credentials):
async def test_get_notifications(client):
"""E2E: Получить уведомления.
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()
assert notifications is not None
# Уведомления могут быть пустыми
assert hasattr(notifications, 'notifications')
finally:
await client.close()
notifications = await client.notifications.get_list()
assert notifications is not None
# Уведомления могут быть пустыми
assert hasattr(notifications, 'notifications')
@pytest.mark.e2e
async def test_get_user_orders(require_credentials):
async def test_get_user_orders(client):
"""E2E: Получить заказы пользователя.
HAR endpoints:
- POST https://api.kwork.ru/payerOrders
- POST https://api.kwork.ru/workerOrders
"""
client = await KworkClient.login(
username=require_credentials["username"],
password=require_credentials["password"],
)
# Заказы как заказчик
payer_orders = await client.projects.get_payer_orders()
assert isinstance(payer_orders, list)
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()
# Заказы как исполнитель
worker_orders = await client.projects.get_worker_orders()
assert isinstance(worker_orders, list)