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 locust
locustfile.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.py
http://localhost:8089
) и настройте количество пользователей и rate (запросов в секунду).Дополнительные соображения:
top
, htop
, vmstat
, iostat
(Linux) или мониторинг ресурсов Windows, могут быть полезны. Также полезны специализированные инструменты мониторинга, такие как Prometheus, Grafana, New Relic, Datadog.Выбор инструмента зависит от сложности требований, масштаба проекта и доступных ресурсов. Locust - хороший выбор для более сложных сценариев load testing с веб-интерфейсом. Pytest + Requests подходит для более простых тестов производительности или для интеграции с существующими тестовыми наборами pytest. Taurus упрощает использование нескольких инструментов и автоматизирует процесс тестирования. JMeter - мощный инструмент, но требует больше усилий для настройки и использования.