refactor(tests): Simplify test setup and fix client fixture
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-08-23 22:36:23 +01:00
parent 1a2f9f9ff4
commit 6fc14db51e
5 changed files with 21 additions and 34 deletions

View File

@@ -19,17 +19,18 @@ steps:
commands: commands:
- echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin - echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
# --- ИЗМЕНЕНИЕ ЗДЕСЬ ---
- name: testing - name: testing
image: python:3.11-slim image: python:3.11-slim
# Передаем фейковые секреты напрямую в окружение этого шага
environment:
YANDEX_CLIENT_ID: "test_id_from_drone"
YANDEX_CLIENT_SECRET: "test_secret_from_drone"
commands: commands:
# Команды создания .env.test больше не нужны # 1. Создаем .env файл. pydantic-settings его найдет и использует.
- echo 'YANDEX_CLIENT_ID="test_id"' > .env
- echo 'YANDEX_CLIENT_SECRET="test_secret"' >> .env
# 2. Устанавливаем зависимости
- pip install poetry - pip install poetry
- poetry install - poetry install
# 3. Запускаем тесты
- poetry run pytest -v - poetry run pytest -v
- name: deploy - name: deploy

View File

@@ -1,4 +1,4 @@
import os # app/core/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings): class Settings(BaseSettings):
@@ -7,12 +7,7 @@ class Settings(BaseSettings):
YANDEX_METRIKA_API_URL: str = "https://api-metrika.yandex.net" YANDEX_METRIKA_API_URL: str = "https://api-metrika.yandex.net"
LOG_LEVEL: str = "INFO" LOG_LEVEL: str = "INFO"
# ИЗМЕНЕНИЕ ЗДЕСЬ: # Возвращаем простую и надежную конфигурацию
# Если запущена среда pytest, используем .env.test, иначе .env
if "PYTEST_CURRENT_TEST" in os.environ:
model_config = SettingsConfigDict(env_file=".env.test")
else:
model_config = SettingsConfigDict(env_file=".env") model_config = SettingsConfigDict(env_file=".env")
settings = Settings() settings = Settings()

View File

@@ -2,20 +2,10 @@ import pytest
from httpx import AsyncClient, ASGITransport from httpx import AsyncClient, ASGITransport
from app.main import app from app.main import app
@pytest.fixture(scope="session") # Убираем async def и yield. Это будет обычная, синхронная фикстура,
def anyio_backend(): # которая создает асинхронный клиент.
"""
Это фикстура, необходимая для pytest-asyncio, чтобы он работал
с httpx в асинхронном режиме. Просто стандартный шаблон.
"""
return "asyncio"
@pytest.fixture @pytest.fixture
async def client() -> AsyncClient: def client() -> AsyncClient:
"""
Главная фикстура. Создает тестовый клиент, который мы будем
использовать во всех наших тестах.
"""
transport = ASGITransport(app=app) transport = ASGITransport(app=app)
async with AsyncClient(transport=transport, base_url="http://test") as async_client: # Просто создаем и возвращаем клиент
yield async_client return AsyncClient(transport=transport, base_url="http://test")

View File

@@ -1,7 +1,8 @@
import pytest import pytest
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_get_counters_unauthorized(client): # <-- Получаем client как аргумент async def test_get_counters_unauthorized(client):
async with client:
response = await client.get("/api/v1/counters/") response = await client.get("/api/v1/counters/")
assert response.status_code == 403 assert response.status_code == 403

View File

@@ -1,8 +1,8 @@
import pytest import pytest
# Тесты теперь не знают про 'app', они знают только про 'client'
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_health_check(client): # <-- Получаем client как аргумент async def test_health_check(client): # <-- client - это теперь сам AsyncClient
async with client: # <-- Используем async with для управления контекстом
response = await client.get("/") response = await client.get("/")
assert response.status_code == 200 assert response.status_code == 200