pytest + плагины (например, для измерения времени выполнения): Можно использовать для базового тестирования производительности, но не для полноценного load testing.
locust -f locustfile.py
Тестирование производительности (load testing) в Python можно проводить с использованием различных инструментов и подходов, часто в сочетании с pytest для организации и запуска тестов.
Основные подходы и инструменты:
pytest сам по себе не является инструментом для load testing, но его можно использовать для организации тестов и запуска параллельных запросов. Библиотеки requests (синхронные запросы) или aiohttp (асинхронные запросы) позволяют отправлять HTTP-запросы к тестируемому API. Для создания нагрузки можно использовать `concurrent.futures` (ThreadPoolExecutor/ProcessPoolExecutor) или `asyncio.gather` для выполнения множества запросов одновременно. Этот подход проще Locust, но менее масштабируем и не предоставляет удобного веб-интерфейса.Пример с Pytest и Requests (базовый):
import pytest
import requests
import concurrent.futures
BASE_URL = "http://your-api-endpoint.com"
NUM_REQUESTS = 100
CONCURRENCY = 10
def make_request(url):
try:
response = requests.get(url)
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
return response.elapsed.total_seconds() # Return response time
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
return None
@pytest.fixture
def test_url():
return f"{BASE_URL}/some/endpoint"
def test_performance(test_url):
with concurrent.futures.ThreadPoolExecutor(max_workers=CONCURRENCY) as executor:
futures = [executor.submit(make_request, test_url) for _ in range(NUM_REQUESTS)]
response_times = [future.result() for future in concurrent.futures.as_completed(futures) if future.result() is not None]
assert len(response_times) > 0, "No successful requests were made."
average_response_time = sum(response_times) / len(response_times)
print(f"Average response time: {average_response_time:.4f} seconds")
# Add assertions based on performance requirements
assert average_response_time < 0.5, "Average response time exceeds threshold."
Пояснения к примеру:
BASE_URL: URL вашего API.NUM_REQUESTS: Общее количество запросов для отправки.CONCURRENCY: Количество параллельных потоков (или процессов) для отправки запросов.make_request отправляет GET-запрос и возвращает время ответа в секундах. Обрабатывает исключения, если запрос не удался.pytest.fixture определяет URL-адрес для тестирования.test_performance использует ThreadPoolExecutor для отправки запросов параллельно.assert) для проверки, что среднее время ответа находится в пределах допустимого порога.Пример с Locust (основные шаги):
pip install locustlocustfile.py:
from locust import HttpUser, task, between
class User(HttpUser):
wait_time = between(1, 2) # Wait between 1 and 2 seconds between tasks
host = "http://your-api-endpoint.com"
@task
def get_endpoint(self):
self.client.get("/some/endpoint")
locust -f locustfile.pyhttp://localhost:8089) и настройте количество пользователей и rate (запросов в секунду).Дополнительные соображения:
top, htop, vmstat, iostat (Linux) или мониторинг ресурсов Windows, могут быть полезны. Также полезны специализированные инструменты мониторинга, такие как Prometheus, Grafana, New Relic, Datadog.Выбор инструмента зависит от сложности требований, масштаба проекта и доступных ресурсов. Locust - хороший выбор для более сложных сценариев load testing с веб-интерфейсом. Pytest + Requests подходит для более простых тестов производительности или для интеграции с существующими тестовыми наборами pytest. Taurus упрощает использование нескольких инструментов и автоматизирует процесс тестирования. JMeter - мощный инструмент, но требует больше усилий для настройки и использования.