Как сделать общую авторизацию для всех тестов?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Стратегия реализации общей авторизации в автоматизированных тестах
Реализация общей авторизации — критически важный компонент тестовой инфраструктуры, позволяющий избежать дублирования кода, уменьшить время выполнения тестов и повысить их стабильность. Вот комплексный подход к решению этой задачи.
Архитектурные подходы
Использование хуков в Pytest — наиболее популярный и эффективный метод в Python-стеках:
import pytest
import requests
from typing import Dict, Any
@pytest.fixture(scope="session")
def auth_token() -> str:
"""Фикстура для получения токена авторизации на уровне сессии"""
credentials = {
"username": "test_user",
"password": "test_password"
}
response = requests.post(
"https://api.example.com/auth/login",
json=credentials
)
assert response.status_code == 200, "Авторизация не удалась"
token_data = response.json()
return token_data["access_token"]
@pytest.fixture(scope="function")
def authorized_client(auth_token: str) -> requests.Session:
"""Фикстура для создания авторизованной HTTP-сессии"""
session = requests.Session()
session.headers.update({
"Authorization": f"Bearer {auth_token}",
"Content-Type": "application/json"
})
# Добавляем автоматическую проверку срока действия токена
yield session
session.close()
Иерархия областей видимости фикстур позволяет оптимизировать процесс:
scope="session"— токен получается один раз за весь прогон тестовscope="module"— переиспользование в рамках модуляscope="class"— для тестовых классовscope="function"— для каждого теста отдельно (наименее эффективно)
Расширенная реализация с обработкой исключений
import pytest
import requests
from requests.exceptions import RequestException
from datetime import datetime, timedelta
class AuthManager:
"""Менеджер для управления авторизацией"""
def __init__(self):
self._token = None
self._token_expiry = None
self._base_url = "https://api.example.com"
def get_token(self, force_refresh: bool = False) -> str:
"""Получение токена с кэшированием и обновлением"""
if (force_refresh or
self._token is None or
self._token_expiry is None or
datetime.now() >= self._token_expiry):
self._refresh_token()
return self._token
def _refresh_token(self):
"""Обновление токена с обработкой ошибок"""
try:
response = requests.post(
f"{self._base_url}/auth/login",
json={
"username": self._get_credentials()["username"],
"password": self._get_credentials()["password"]
},
timeout=10
)
if response.status_code == 200:
token_data = response.json()
self._token = token_data["access_token"]
# Устанавливаем время истечения (минус 30 секунд буфер)
expires_in = token_data.get("expires_in", 3600)
self._token_expiry = datetime.now() + timedelta(seconds=expires_in - 30)
else:
raise AuthException(f"Ошибка авторизации: {response.status_code}")
except RequestException as e:
raise AuthException(f"Сетевая ошибка при авторизации: {str(e)}")
def _get_credentials(self) -> Dict[str, str]:
"""Безопасное получение учетных данных"""
# На практике используйте переменные окружения или секреты
return {
"username": "test_user",
"password": "test_password"
}
@pytest.fixture(scope="session")
def auth_manager():
"""Фикстура для менеджера авторизации"""
return AuthManager()
Интеграция с различными фреймворками
Для Selenium WebDriver (UI-тестирование):
from selenium import webdriver
from selenium.webdriver.common.by import By
@pytest.fixture
def authorized_driver(auth_token):
"""Фикстура для авторизованного браузера"""
driver = webdriver.Chrome()
# Устанавливаем токен в localStorage или cookies
driver.get("https://example.com")
# Внедряем токен через JavaScript
driver.execute_script(f"""
localStorage.setItem('auth_token', '{auth_token}');
window.location.reload();
""")
yield driver
driver.quit()
Для Playwright (современная альтернатива Selenium):
// Пример на JavaScript для Playwright
const { test, expect } = require('@playwright/test');
test.beforeAll(async ({ browser }) => {
// Получаем токен через API
const token = await getAuthToken();
// Создаем контекст с заранее установленными куками
const context = await browser.newContext({
storageState: {
cookies: [{
name: 'session_token',
value: token,
domain: 'example.com',
path: '/'
}]
}
});
global.authorizedPage = await context.newPage();
});
Ключевые практики и рекомендации
Безопасность и конфигурация:
- Никогда не храните учетные данные в коде — используйте переменные окружения или системы управления секретами
- Используйте различные наборы учетных данных для разных окружений (dev, staging, prod)
- Реализуйте механизм ротации токенов и автоматического обновления
Оптимизация производительности:
- Кэшируйте токены на уровне сессии для уменьшения количества запросов
- Используйте параллельный запуск тестов с общей авторизацией
- Реализуйте ленивую загрузку токенов (только при первом использовании)
Обработка ошибок и отказоустойчивость:
- Добавляйте повторные попытки при неудачной авторизации
- Реализуйте деградацию функциональности — возможность запуска тестов без авторизации (если допустимо)
- Ведите логирование всех операций авторизации для отладки
Интеграция с CI/CD:
- Настройте предварительную авторизацию на этапе подготовки тестового окружения
- Используйте Service Accounts вместо пользовательских учетных записей
- Реализуйте механизм очистки сессий после завершения тестов
Расширенные сценарии
Для микросервисных архитектур может потребоваться несколько уровней авторизации. В этом случае реализуйте фасад авторизации, который управляет множеством токенов:
class MultiServiceAuth:
"""Управление авторизацией для нескольких сервисов"""
def __init__(self):
self._tokens = {}
def get_service_token(self, service_name: str) -> str:
if service_name not in self._tokens:
self._tokens[service_name] = self._authenticate_to_service(service_name)
return self._tokens[service_name]
Мониторинг и аналитика
Инструментируйте процесс авторизации для сбора метрик:
- Время получения/обновления токенов
- Процент успешных авторизаций
- Частота использования различных учетных записей
Заключение
Правильная реализация общей авторизации требует баланса между производительностью, безопасностью и поддерживаемостью. Начните с простой фикстуры на уровне сессии, затем постепенно добавляйте обработку ошибок, кэширование и механизмы обновления токенов. Используйте абстракции и dependency injection для обеспечения гибкости и тестируемости решения. Регулярно пересматривайте и обновляйте механизм авторизации в соответствии с изменениями в тестируемой системе и появлением новых инструментов в экосистеме автоматизации.