Перейти к содержимому
testingСредний15 минут

Performance testing с pytest-benchmark

Быстрый старт с pytest-benchmark: ставим рядом с функциональными тестами, заводим бюджет времени и сохраняем baseline в CI.

#pytest#performance#benchmark#testing

Performance testing с pytest-benchmark

Этот материал дополняет курс "Pytest: Борьба с flaky-тестами и race conditions", но не является его частью. Performance testing — отдельная дисциплина, которая требует своего подхода и инструментов.

Быстрый старт

Performance testing != Flaky testing. Это отдельная тема, но если вы хотите быстро прикрутить бенчмарки к вашему проекту:

pip install pytest-benchmark

Базовый пример

# tests/perf/test_serialization.py
import pytest
 
 
def test_order_serializer_speed(benchmark, sample_orders):
    """Тестируем скорость сериализации заказов"""
    result = benchmark(serialize_orders, sample_orders)
 
    # Можно установить бюджет времени
    assert benchmark.stats['mean'] < 0.05  # 50ms максимум

Запуск бенчмарков

# Запустить только бенчмарки
pytest tests/perf --benchmark-only
 
# С прогревом (warmup)
pytest tests/perf --benchmark-only --benchmark-warmup=on
 
# Сохранить baseline
pytest tests/perf --benchmark-only --benchmark-save=baseline
 
# Сравнить с baseline
pytest tests/perf --benchmark-only --benchmark-compare=baseline

Best practices

1. Отдельная директория для бенчмарков

tests/
  perf/              # Performance tests
    test_api.py
    test_db.py
  functional/        # Functional tests
    test_orders.py

2. Используйте маркеры

import pytest
 
@pytest.mark.perf
def test_database_query_speed(benchmark, db):
    benchmark(db.query, "SELECT * FROM orders")

Запуск:

pytest -m perf --benchmark-only

3. Фиксированное железо

Бенчмарки чувствительны к нагрузке:

  • Запускайте на выделенных CI-раннерах
  • Отключайте другие процессы
  • Используйте одну и ту же машину для сравнения

4. Установите бюджеты времени

def test_api_response_time(benchmark, client):
    response = benchmark(client.get, "/api/orders")
 
    # Жёсткие требования к производительности
    assert benchmark.stats['mean'] < 0.1  # 100ms среднее
    assert benchmark.stats['max'] < 0.5   # 500ms максимум

Интеграция в CI

# .gitlab-ci.yml
performance:
  stage: test
  tags:
    - performance # Выделенный раннер
  script:
    - pip install -e '.[test,perf]'
    - pytest tests/perf --benchmark-only --benchmark-save=ci-${CI_COMMIT_SHA}
    - pytest tests/perf --benchmark-compare=baseline --benchmark-compare-fail=mean:10%
  only:
    - master
    - merge_requests

Что НЕ надо делать

Не смешивайте бенчмарки с функциональными тестами

# Плохо: в одном тесте функциональность И производительность
def test_order_creation(db):
    start = time.time()
    order = create_order(db, {...})
    assert time.time() - start < 0.1  # ❌
    assert order.status == "pending"

Разделяйте тесты:

# Функциональный тест
def test_order_creation(db):
    order = create_order(db, {...})
    assert order.status == "pending"
 
# Performance тест
@pytest.mark.perf
def test_order_creation_speed(benchmark, db):
    benchmark(create_order, db, {...})

Продвинутые возможности

Параметризация бенчмарков

@pytest.mark.parametrize("size", [10, 100, 1000, 10000])
def test_serialization_scaling(benchmark, size):
    data = generate_orders(size)
    benchmark(serialize_orders, data)

Группировка результатов

@pytest.mark.benchmark(group="serialization")
def test_json_serialization(benchmark, orders):
    benchmark(json.dumps, orders)
 
@pytest.mark.benchmark(group="serialization")
def test_msgpack_serialization(benchmark, orders):
    benchmark(msgpack.packb, orders)

Когда использовать pytest-benchmark

Хорошо подходит для:

  • Unit-тесты критичных функций
  • Регрессионное тестирование производительности
  • Сравнение разных реализаций
  • CI/CD проверки

Не подходит для:

  • Load testing (используйте Locust, k6)
  • Stress testing
  • Распределённого тестирования
  • Production monitoring

Альтернативы

Для других задач performance testing используйте:

  • Load testing: Locust, k6, JMeter
  • Profiling: cProfile, py-spy, memory_profiler
  • APM: New Relic, DataDog, Sentry Performance

Связанные материалы