TL;DR

  • Locust = нагрузочное тестирование на Python (тесты — это просто Python код)
  • Определяй поведение пользователей в locustfile.py с декораторами @task
  • Запуск с web UI (locust) или headless (locust --headless)
  • Распределённый режим: один master + N workers для масштаба
  • Метрики в реальном времени: RPS, время отклика, процент ошибок

Идеально для: Python-команд, нагрузочного тестирования API, разработчиков, предпочитающих код GUI Пропусти, если: Нужно GUI-построение тестов или широкая поддержка протоколов (используй JMeter) Время чтения: 12 минут

Твой API обрабатывает 100 запросов в секунду в продакшене. Приближается Чёрная пятница — выдержит ли он 10x? Лучше узнать заранее, чем от клиентов.

Locust позволяет писать нагрузочные тесты на Python. Никаких XML конфигов, сложных GUI. Просто Python код, симулирующий поведение пользователей.

Что такое Locust?

Locust — open-source фреймворк для нагрузочного тестирования на Python. Ты определяешь поведение пользователей как Python код, и Locust создаёт тысячи конкурентных пользователей для нагрузки на систему.

Почему Locust:

  • Python-native — тесты это обычный Python код
  • Масштабируемый — распределённый режим для миллионов пользователей
  • Real-time UI — веб-дашборд показывает метрики в реальном времени
  • Лёгкий — низкие ресурсы на пользователя
  • Гибкий — тестируй любую систему с Python библиотеками

Установка

pip install locust

Проверка установки:

locust --version

Твой первый нагрузочный тест

Базовый Locustfile

# locustfile.py
from locust import HttpUser, task, between

class WebsiteUser(HttpUser):
    wait_time = between(1, 3)  # Ожидание 1-3 секунды между задачами

    @task
    def homepage(self):
        self.client.get("/")

    @task(3)  # В 3 раза чаще чем homepage
    def api_endpoint(self):
        self.client.get("/api/products")

Запуск теста

# Запуск с web UI
locust -f locustfile.py --host=https://api.example.com

# Открой http://localhost:8089
# Укажи количество пользователей и spawn rate
# Нажми Start

Headless режим (CI/CD)

locust -f locustfile.py \
    --host=https://api.example.com \
    --users 100 \
    --spawn-rate 10 \
    --run-time 5m \
    --headless

Написание пользовательских сценариев

Множественные задачи

from locust import HttpUser, task, between

class ApiUser(HttpUser):
    wait_time = between(0.5, 2)

    @task(5)
    def list_products(self):
        self.client.get("/api/products")

    @task(2)
    def get_product(self):
        self.client.get("/api/products/1")

    @task(1)
    def create_order(self):
        self.client.post("/api/orders", json={
            "product_id": 1,
            "quantity": 2
        })

Setup и Teardown

from locust import HttpUser, task, between

class AuthenticatedUser(HttpUser):
    wait_time = between(1, 3)

    def on_start(self):
        # Выполняется один раз при старте пользователя
        response = self.client.post("/api/login", json={
            "username": "test",
            "password": "password"
        })
        self.token = response.json()["token"]

    def on_stop(self):
        # Выполняется один раз при остановке пользователя
        self.client.post("/api/logout")

    @task
    def protected_endpoint(self):
        self.client.get("/api/profile", headers={
            "Authorization": f"Bearer {self.token}"
        })

Последовательные задачи

from locust import HttpUser, task, between, SequentialTaskSet

class UserFlow(SequentialTaskSet):
    @task
    def browse(self):
        self.client.get("/products")

    @task
    def add_to_cart(self):
        self.client.post("/cart", json={"product_id": 1})

    @task
    def checkout(self):
        self.client.post("/checkout")

class EcommerceUser(HttpUser):
    tasks = [UserFlow]
    wait_time = between(1, 3)

Assertions и валидация

from locust import HttpUser, task

class ValidatingUser(HttpUser):
    @task
    def check_api(self):
        with self.client.get("/api/status", catch_response=True) as response:
            if response.status_code != 200:
                response.failure(f"Got {response.status_code}")
            elif response.elapsed.total_seconds() > 2:
                response.failure("Too slow!")
            elif "ok" not in response.text:
                response.failure("Missing 'ok' in response")
            else:
                response.success()

Распределённое тестирование

Master Node

locust -f locustfile.py --master --host=https://api.example.com

Worker Nodes

# На каждой worker машине
locust -f locustfile.py --worker --master-host=192.168.1.100

Docker Compose

# docker-compose.yml
version: '3'
services:
  master:
    image: locustio/locust
    ports:
      - "8089:8089"
    volumes:
      - ./:/mnt/locust
    command: -f /mnt/locust/locustfile.py --master -H https://api.example.com

  worker:
    image: locustio/locust
    volumes:
      - ./:/mnt/locust
    command: -f /mnt/locust/locustfile.py --worker --master-host master
    deploy:
      replicas: 4

Понимание результатов

Ключевые метрики

МетрикаЗначение
RPSЗапросов в секунду (throughput)
Median50-й перцентиль времени отклика
95%ile95% запросов быстрее этого значения
FailuresПроцент неуспешных запросов
UsersТекущее количество симулированных пользователей

Экспорт результатов

locust -f locustfile.py \
    --headless \
    --users 100 \
    --spawn-rate 10 \
    --run-time 5m \
    --csv=results \
    --html=report.html

CI/CD интеграция

GitHub Actions

# .github/workflows/load-test.yml
name: Load Tests

on:
  schedule:
    - cron: '0 2 * * *'  # Ежедневно в 2:00

jobs:
  load-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install Locust
        run: pip install locust

      - name: Run Load Test
        run: |
          locust -f locustfile.py \
            --host=${{ secrets.API_URL }} \
            --users 50 \
            --spawn-rate 5 \
            --run-time 2m \
            --headless \
            --csv=results

      - name: Upload Results
        uses: actions/upload-artifact@v4
        with:
          name: load-test-results
          path: results*.csv

Locust с помощью ИИ

ИИ инструменты могут помочь писать и оптимизировать Locust тесты.

Что ИИ делает хорошо:

  • Генерировать пользовательские сценарии из API спецификаций
  • Создавать вариации данных для реалистичной нагрузки
  • Предлагать пороговые значения производительности
  • Конвертировать JMeter тесты в Locust

Что требует людей:

  • Определение реалистичных паттернов поведения пользователей
  • Установка подходящих уровней нагрузки
  • Интерпретация результатов в бизнес-контексте
  • Отладка специфичных production проблем

FAQ

Что такое Locust?

Locust — open-source Python-фреймворк для нагрузочного тестирования. Ты пишешь поведение пользователей на Python с декораторами @task, и Locust создаёт конкурентных пользователей для генерации нагрузки. Предоставляет web UI для мониторинга в реальном времени и поддерживает распределённое тестирование для масштаба.

Locust vs JMeter — что лучше?

Locust использует Python код (лучше для разработчиков, которым нужен контроль версий и поддержка IDE). JMeter использует GUI (проще для не-разработчиков). Locust легче и проще масштабируется с распределённым режимом. JMeter имеет более широкую поддержку протоколов и больше плагинов. Выбирай Locust для Python команд, JMeter для команд, которым нужен GUI или специфические протоколы.

Может ли Locust тестировать WebSockets?

Да, через кастомные клиенты. Архитектура Locust поддерживает любой протокол — ты реализуешь логику подключения на Python. Сообщество предоставляет библиотеки для WebSockets, gRPC и других протоколов. Locust управляет симуляцией пользователей и метриками, пока ты контролируешь реализацию протокола.

Сколько пользователей может симулировать Locust?

Одна машина обычно обрабатывает 1000-10000 конкурентных пользователей в зависимости от сложности сценария и доступных ресурсов. Для больших тестов используй распределённый режим с одним master, координирующим несколько workers. Это масштабируется до миллионов пользователей на кластере.

Официальные ресурсы

Смотрите также