From 8cb0a590639fdd687128f4b6421c2f5c7f2e8948 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 29 Mar 2026 01:35:57 +0000 Subject: [PATCH] test: add E2E testing framework - Add E2E test structure (tests/e2e/) - Add conftest.py with fixtures and credentials loading - Add test_auth.py with authentication tests - Add .env.example template - Add README.md with usage instructions - Mark tests with @pytest.mark.e2e - Add --slowmo option for rate limiting --- tests/e2e/.env.example | 5 ++ tests/e2e/README.md | 136 +++++++++++++++++++++++++++++++++++++++++ tests/e2e/conftest.py | 59 ++++++++++++++++++ tests/e2e/test_auth.py | 52 ++++++++++++++++ 4 files changed, 252 insertions(+) create mode 100644 tests/e2e/.env.example create mode 100644 tests/e2e/README.md create mode 100644 tests/e2e/conftest.py create mode 100644 tests/e2e/test_auth.py diff --git a/tests/e2e/.env.example b/tests/e2e/.env.example new file mode 100644 index 0000000..106cb3c --- /dev/null +++ b/tests/e2e/.env.example @@ -0,0 +1,5 @@ +# Kwork.ru credentials for E2E testing +# Copy this file to .env and fill in your test credentials + +KWORK_USERNAME=your_test_username +KWORK_PASSWORD=your_test_password diff --git a/tests/e2e/README.md b/tests/e2e/README.md new file mode 100644 index 0000000..d757cf9 --- /dev/null +++ b/tests/e2e/README.md @@ -0,0 +1,136 @@ +# End-to-End (E2E) Testing + +E2E тесты требуют реальных credentials Kwork.ru и запускаются **только локально** (не в CI). + +## ⚠️ Предупреждение + +- **Не запускай в CI** — требуются реальные credentials +- **Используй тестовый аккаунт** — не основной аккаунт Kwork +- **Rate limiting** — добавляй задержки между запросами + +--- + +## 🔧 Настройка + +### 1. Создай файл окружения + +```bash +cd /root/kwork-api +cp tests/e2e/.env.example tests/e2e/.env +``` + +### 2. Заполни credentials + +```bash +# tests/e2e/.env +KWORK_USERNAME=your_test_username +KWORK_PASSWORD=your_test_password +``` + +### 3. Установи зависимости + +```bash +uv sync --group dev +``` + +--- + +## 🚀 Запуск тестов + +### Все E2E тесты + +```bash +uv run pytest tests/e2e/ -v +``` + +### Конкретный тест + +```bash +uv run pytest tests/e2e/test_auth.py -v +uv run pytest tests/e2e/test_catalog.py::test_get_catalog_list -v +``` + +### С задержками (rate limiting) + +```bash +uv run pytest tests/e2e/ -v --slowmo=1 +``` + +--- + +## 📁 Структура тестов + +``` +tests/e2e/ +├── README.md # Этот файл +├── .env.example # Шаблон для credentials +├── conftest.py # Фикстуры и setup +├── test_auth.py # Аутентификация +├── test_catalog.py # Каталог кворков +├── test_projects.py # Биржа проектов +└── test_user.py # Пользовательские данные +``` + +--- + +## 🧪 Пример теста + +```python +import pytest +from kwork_api import KworkClient + +@pytest.mark.e2e +async def test_get_user_info(): + """E2E тест: получение информации о пользователе.""" + async with await KworkClient.login( + username="test_user", + password="test_pass" + ) as client: + user = await client.user.get_info() + assert user.username == "test_user" + assert user.balance >= 0 +``` + +--- + +## 🏷️ Маркировка тестов + +E2E тесты маркируются `@pytest.mark.e2e` для изоляции: + +```bash +# Запустить только unit тесты (исключить e2e) +uv run pytest tests/ -v -m "not e2e" + +# Запустить только e2e тесты +uv run pytest tests/ -v -m e2e +``` + +--- + +## 🔒 Безопасность + +1. **Никогда не коммить `.env`** — добавлен в `.gitignore` +2. **Используй тестовый аккаунт** — не основной +3. **Не сохраняй токены в коде** — только через env vars + +--- + +## 🐛 Troubleshooting + +### Ошибка аутентификации +``` +KworkAuthError: Invalid credentials +``` +**Решение:** Проверь credentials в `.env` + +### Rate limit +``` +KworkApiError: Too many requests +``` +**Решение:** Запусти с задержкой: `pytest --slowmo=2` + +### Session expired +``` +KworkAuthError: Session expired +``` +**Решение:** Перезапусти тесты (session создаётся заново) diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py new file mode 100644 index 0000000..1057118 --- /dev/null +++ b/tests/e2e/conftest.py @@ -0,0 +1,59 @@ +""" +E2E тесты для Kwork API. + +Требуют реальных credentials и запускаются только локально. +""" + +import os +import pytest +from pathlib import Path +from dotenv import load_dotenv + +# Загружаем .env +load_dotenv(Path(__file__).parent / ".env") + + +@pytest.fixture(scope="session") +def kwork_credentials(): + """Credentials для тестового аккаунта.""" + return { + "username": os.getenv("KWORK_USERNAME"), + "password": os.getenv("KWORK_PASSWORD"), + } + + +@pytest.fixture(scope="session") +def require_credentials(kwork_credentials): + """Пропускает тест если нет credentials.""" + if not kwork_credentials["username"] or not kwork_credentials["password"]: + pytest.skip( + "E2E credentials not set. " + "Copy tests/e2e/.env.example to tests/e2e/.env and fill in credentials." + ) + return kwork_credentials + + +@pytest.fixture(scope="function") +def slowmo(request): + """Задержка между тестами для rate limiting.""" + slowmo = request.config.getoption("--slowmo", default=0) + if slowmo > 0: + import time + time.sleep(slowmo) + + +def pytest_configure(config): + """Регистрация маркера e2e.""" + config.addinivalue_line( + "markers", "e2e: mark test as end-to-end (requires credentials)" + ) + + +def pytest_addoption(parser): + """Добавляет опцию --slowmo.""" + parser.addoption( + "--slowmo", + type=float, + default=0, + help="Delay between tests in seconds (for rate limiting)" + ) diff --git a/tests/e2e/test_auth.py b/tests/e2e/test_auth.py new file mode 100644 index 0000000..db42b8b --- /dev/null +++ b/tests/e2e/test_auth.py @@ -0,0 +1,52 @@ +""" +E2E тесты аутентификации. +""" + +import pytest +from kwork_api import KworkClient +from kwork_api.errors import KworkAuthError + + +@pytest.mark.e2e +async def test_login_success(require_credentials): + """E2E: Успешная аутентификация.""" + client = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"] + ) + + try: + assert client.token is not None + assert len(client.token) > 0 + finally: + await client.aclose() + + +@pytest.mark.e2e +async def test_login_invalid_credentials(): + """E2E: Неверные credentials.""" + with pytest.raises(KworkAuthError): + await KworkClient.login( + username="invalid_user_12345", + password="invalid_pass_12345" + ) + + +@pytest.mark.e2e +async def test_restore_session(require_credentials): + """E2E: Восстановление сессии из токена.""" + # First login + client1 = await KworkClient.login( + username=require_credentials["username"], + password=require_credentials["password"] + ) + token = client1.token + await client1.aclose() + + # Restore from token + client2 = KworkClient(token=token) + try: + user = await client2.user.get_info() + assert user.username == require_credentials["username"] + finally: + await client2.aclose()