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
This commit is contained in:
parent
0841be5153
commit
8cb0a59063
5
tests/e2e/.env.example
Normal file
5
tests/e2e/.env.example
Normal file
@ -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
|
||||
136
tests/e2e/README.md
Normal file
136
tests/e2e/README.md
Normal file
@ -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 создаётся заново)
|
||||
59
tests/e2e/conftest.py
Normal file
59
tests/e2e/conftest.py
Normal file
@ -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)"
|
||||
)
|
||||
52
tests/e2e/test_auth.py
Normal file
52
tests/e2e/test_auth.py
Normal file
@ -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()
|
||||
Loading…
Reference in New Issue
Block a user