From 6fc14db51e2f29f1a1d65bad7601dab353696897 Mon Sep 17 00:00:00 2001 From: 13orlov <13orlov@gmail.com> Date: Sat, 23 Aug 2025 22:36:23 +0100 Subject: [PATCH] refactor(tests): Simplify test setup and fix client fixture --- .drone.yml | 13 +++++++------ app/core/config.py | 11 +++-------- tests/conftest.py | 20 +++++--------------- tests/test_counters.py | 5 +++-- tests/test_main.py | 6 +++--- 5 files changed, 21 insertions(+), 34 deletions(-) diff --git a/.drone.yml b/.drone.yml index 413fc34..8e7d1c1 100644 --- a/.drone.yml +++ b/.drone.yml @@ -19,17 +19,18 @@ steps: commands: - echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin - # --- ИЗМЕНЕНИЕ ЗДЕСЬ --- - name: testing image: python:3.11-slim - # Передаем фейковые секреты напрямую в окружение этого шага - environment: - YANDEX_CLIENT_ID: "test_id_from_drone" - YANDEX_CLIENT_SECRET: "test_secret_from_drone" 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 - poetry install + + # 3. Запускаем тесты - poetry run pytest -v - name: deploy diff --git a/app/core/config.py b/app/core/config.py index 5bb779c..d46df3f 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -1,4 +1,4 @@ -import os +# app/core/config.py from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): @@ -7,12 +7,7 @@ class Settings(BaseSettings): YANDEX_METRIKA_API_URL: str = "https://api-metrika.yandex.net" 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() \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index b6c2349..96134df 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -2,20 +2,10 @@ import pytest from httpx import AsyncClient, ASGITransport from app.main import app -@pytest.fixture(scope="session") -def anyio_backend(): - """ - Это фикстура, необходимая для pytest-asyncio, чтобы он работал - с httpx в асинхронном режиме. Просто стандартный шаблон. - """ - return "asyncio" - +# Убираем async def и yield. Это будет обычная, синхронная фикстура, +# которая создает асинхронный клиент. @pytest.fixture -async def client() -> AsyncClient: - """ - Главная фикстура. Создает тестовый клиент, который мы будем - использовать во всех наших тестах. - """ +def client() -> AsyncClient: 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") \ No newline at end of file diff --git a/tests/test_counters.py b/tests/test_counters.py index c33969e..b23f41c 100644 --- a/tests/test_counters.py +++ b/tests/test_counters.py @@ -1,8 +1,9 @@ import pytest @pytest.mark.asyncio -async def test_get_counters_unauthorized(client): # <-- Получаем client как аргумент - response = await client.get("/api/v1/counters/") +async def test_get_counters_unauthorized(client): + async with client: + response = await client.get("/api/v1/counters/") assert response.status_code == 403 assert response.json() == {"detail": "Not authenticated"} \ No newline at end of file diff --git a/tests/test_main.py b/tests/test_main.py index 0ac47d1..b8953bc 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,9 +1,9 @@ import pytest -# Тесты теперь не знают про 'app', они знают только про 'client' @pytest.mark.asyncio -async def test_health_check(client): # <-- Получаем client как аргумент - response = await client.get("/") +async def test_health_check(client): # <-- client - это теперь сам AsyncClient + async with client: # <-- Используем async with для управления контекстом + response = await client.get("/") assert response.status_code == 200 assert response.json() == {