Нагрузочное тестирование для начинающих: JMeter и Gatling — что выбрать и как начать

Нагрузочное тестирование для начинающих: JMeter и Gatling — что выбрать и как начать

«Сайт упал в Чёрную пятницу». «API не выдержал наплыва пользователей после рекламы». «Приложение тормозит, когда больше 100 человек онлайн». Знакомые истории? Нагрузочное тестирование — это способ узнать о таких проблемах до того, как о них узнают ваши пользователи. По данным исследований, компании вроде Etsy, использующие автоматизированное нагрузочное тестирование в CI/CD, ловят до 90% проблем производительности до продакшена. Apache JMeter и Gatling — два самых популярных инструмента для нагрузочного тестирования. В этой статье разберёмся, что это такое, какие типы тестов бывают, как настроить первый тест в каждом из инструментов, и — главное — какой выбрать именно вам.

1. Что такое нагрузочное тестирование

Определение

Нагрузочное тестирование (Load Testing) — это тип тестирования производительности, который проверяет, как система ведёт себя под ожидаемой нагрузкой. Цель — убедиться, что приложение справляется с запланированным количеством пользователей, сохраняя приемлемое время отклика и стабильность.

Зачем нужно

ЦельЧто даёт

Найти bottlenecks

Определить, где система «захлёбывается» под нагрузкой

Capacity planning

Понять, сколько пользователей может выдержать инфраструктура

Валидация SLA

Проверить, что система соответствует требованиям по времени отклика

Предотвращение инцидентов

Найти проблемы до того, как они ударят по пользователям

Оптимизация

Данные для настройки серверов, БД, кэширования

Нагрузочное тестирование vs Performance Testing

Performance Testing — общий термин, включающий разные типы тестов производительности. Load Testing — один из них.

Performance Testing включает:

• Load Testing — тестирование под ожидаемой нагрузкой
• Stress Testing — тестирование за пределами нормальной нагрузки
• Spike Testing — тестирование резких скачков
• Soak/Endurance Testing — длительное тестирование
• Scalability Testing — тестирование масштабируемости
• Breakpoint Testing — поиск точки отказа


2. Типы нагрузочных тестов

Load Testing

Классическое нагрузочное тестирование: проверка системы под ожидаемым количеством пользователей. Цель — убедиться, что приложение работает корректно при нормальной нагрузке.

ПараметрОписание

Нагрузка

Ожидаемое количество пользователей (например, 1000 concurrent users)

Длительность

Обычно 15-60 минут

Что измеряем

Response time, throughput, error rate

Когда применять

Перед релизом, после крупных изменений

Stress Testing

Стресс-тестирование выходит за пределы нормальной нагрузки, чтобы найти точку отказа и понять, как система ведёт себя на пределе возможностей.

Цитата: «Стресс-тестирование — популярный тип нагрузочного тестирования, который оценивает, как система работает при нагрузке выше обычной. Системы могут получать повышенную нагрузку: дедлайны, зарплаты, час пик, конец недели и многие другие ситуации.»

Что выявляет: проблемы синхронизации, утечки памяти, race conditions.

Spike Testing

Spike-тестирование проверяет, как система справляется с внезапным резким ростом нагрузки — например, когда реклама на ТВ приводит миллионы пользователей одновременно.

СценарийПример
Продажа билетовКонцерт Taylor Swift — миллионы в очереди одновременно
Запуск продуктаPlayStation 5 — очередь на предзаказ
Реклама на ТВSuper Bowl — сайт рекламодателя
Сезонные распродажиBlack Friday, 11.11
ДедлайныПоследний день подачи налоговой декларации

Цель: проверить эластичность системы — может ли она масштабироваться вверх при пике и вернуться к норме после.

Soak/Endurance Testing

Длительное тестирование под стабильной нагрузкой (часы или дни). Цель — найти проблемы, которые проявляются со временем: утечки памяти, деградация производительности, накопление ошибок.

Breakpoint/Capacity Testing

Поиск точки отказа: постепенное увеличение нагрузки до момента, когда система перестаёт справляться. Помогает понять реальную capacity системы.

Breakpoint Test:

Начать с 100 пользователей → Добавлять по 100 каждые 5 минут → Мониторить response time и error rate → Зафиксировать точку, где response time резко растёт или errors > 1%


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

Response Time (Время отклика)

Время, которое сервер тратит на обработку запроса и отправку ответа. Основная метрика пользовательского опыта.

МетрикаОписаниеИспользование

Avg Response Time

Среднее время откликаОбщая картина, но скрывает outliers

Min / Max

Минимальное / максимальное времяГраницы, но max может быть аномалией

Median (P50)

50% запросов быстрее этого значенияТипичный опыт пользователя

P90 / P95 / P99

ПерцентилиОпыт «худших» пользователей

Почему перцентили важнее среднего

Факт: «Один запрос с временем отклика 20 секунд может исказить среднее время всего приложения, даже если 7 из 8 запросов обрабатываются за 107 мс.»

Средние значения скрывают проблемы. Перцентили показывают реальную картину:

ПерцентильЧто показываетКогда использовать

P50 (Median)

Типичный опытБазовая метрика

P90

10% пользователей ждут дольшеХороший индикатор UX

P95

5% пользователей ждут дольше🟢 Рекомендуется для SLO

P99

1% пользователей ждут дольше🟢 Критичные системы (финансы, медицина)

Совет: Не определяйте SLA через средние значения. Используйте формулировку: «Сервис должен отвечать менее чем за 1 секунду для 99% запросов».

Throughput (Пропускная способность)

Количество запросов, обработанных в единицу времени. Измеряется в requests/second (RPS) или transactions/second (TPS).

ThroughputИнтерпретация
СтабильныйСистема справляется с нагрузкой
Падает при росте usersBottleneck, система насыщена
Растёт линейно с usersСистема масштабируется хорошо

Error Rate (Процент ошибок)

Доля запросов, завершившихся с ошибкой (HTTP 4xx, 5xx, timeouts).

Error RateОценка
< 0.1%🟢 Отлично
0.1% - 1%🟡 Приемлемо
> 1%🔴 Требует внимания
> 5%🔴 Критично

Другие важные метрики

  • Concurrent Users: Количество одновременных пользователей

  • CPU/Memory Usage: Утилизация ресурсов сервера

  • Network I/O: Использование сети

  • Database Connections: Пул соединений с БД

  • Queue Length: Длина очередей (если есть)


4. JMeter vs Gatling: сравнение

Общее сравнение

КритерийApache JMeterGatling

Год создания

19982012

Язык

JavaScala (Kotlin/Java также)

Подход

GUI + XMLCode-first (DSL)

Архитектура

Thread-based (1 thread = 1 user)Async, event-driven (Akka)

Потребление ресурсов

ВысокоеНизкое

Кривая обучения

Низкая (GUI)Средняя (нужен код)

Протоколы

HTTP, FTP, JDBC, LDAP, JMS, SOAP и др.HTTP, WebSocket, JMS, MQTT

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

Через плагиныНативная (Maven/Gradle)

Отчёты

Базовые + плагиныКрасивые HTML из коробки

Лицензия

Apache 2.0 (бесплатно)Apache 2.0 (бесплатно)

Архитектурные различия

JMeter (Thread-based):
• 1 виртуальный пользователь = 1 поток
• Больше пользователей = больше памяти и CPU
• При 1000+ пользователей требуется distributed testing

Gatling (Async/Event-driven):
• Использует Akka actors и Netty
• Один процесс может симулировать тысячи пользователей
• Меньше потребление ресурсов при большой нагрузке

Когда выбрать JMeter

  • ✅ Команда без опыта программирования

  • ✅ Нужен GUI для визуального создания тестов

  • ✅ Тестирование не только HTTP (JDBC, FTP, LDAP, JMS)

  • ✅ Богатая экосистема плагинов

  • ✅ Небольшие и средние нагрузки (до 1000 users на машину)

  • ✅ Нужна запись сценариев через прокси

Когда выбрать Gatling

  • ✅ Команда разработчиков (code-first подход)

  • ✅ Высокие нагрузки (тысячи concurrent users)

  • ✅ CI/CD пайплайны (тесты как код, версионирование)

  • ✅ Тестирование API и микросервисов

  • ✅ Важна эффективность ресурсов

  • ✅ Нужны красивые отчёты из коробки

Вердикт: «Оба инструмента поддерживают большинство требований, так что это скорее вопрос личных предпочтений и опыта команды.»


5. Apache JMeter: быстрый старт

Установка

  1. Требования: Java 8 или выше

  2. Скачать: jmeter.apache.org

  3. Распаковать архив

  4. Запустить: bin/jmeter.sh (Linux/Mac) или bin/jmeter.bat (Windows)

Структура Test Plan

ЭлементНазначение

Test Plan

Корневой элемент, контейнер для всего теста

Thread Group

Группа виртуальных пользователей

Sampler

Запрос к серверу (HTTP Request, JDBC Request и т.д.)

Config Element

Настройки (HTTP Defaults, Cookie Manager)

Assertion

Проверка ответа (Response Assertion, Duration Assertion)

Listener

Сбор и отображение результатов

Timer

Задержки между запросами (think time)

Создание первого теста

Шаг 1: Создать Thread Group

Thread Group определяет количество пользователей и режим нагрузки.

ПКМ на Test Plan → Add → Threads (Users) → Thread Group

ПараметрОписаниеПример

Number of Threads

Количество виртуальных пользователей100

Ramp-Up Period

Время для запуска всех пользователей60 сек

Loop Count

Сколько раз каждый пользователь выполнит сценарий10 или Infinite

Шаг 2: Добавить HTTP Request Defaults (опционально)

Общие настройки для всех HTTP запросов в группе.

ПКМ на Thread Group → Add → Config Element → HTTP Request Defaults

  • Server Name or IP: example.com

  • Port: 443

  • Protocol: https

Совет: Используйте HTTP Request Defaults, чтобы менять сервер в одном месте (например, для переключения между staging и production).

Шаг 3: Добавить HTTP Request Sampler

ПКМ на Thread Group → Add → Sampler → HTTP Request

Name: Home Page
Method: GET
Path: /

Шаг 4: Добавить Cookie Manager

Для веб-тестирования обязательно — иначе JMeter будет игнорировать cookies.

ПКМ на Thread Group → Add → Config Element → HTTP Cookie Manager

Шаг 5: Добавить Listener

ПКМ на Thread Group → Add → Listener → View Results Tree

Также полезны:

  • Summary Report: Агрегированная статистика

  • Aggregate Report: Детальная статистика с перцентилями

  • Graph Results: Визуализация

Шаг 6: Запустить тест

Run → Start или зелёная кнопка ▶️

⚠️ Важно: Для реальных нагрузочных тестов используйте CLI-режим, не GUI!

jmeter -n -t test.jmx -l results.jtl -e -o report/

GUI потребляет много ресурсов и искажает результаты.

Пример структуры теста

Test Plan
├── Thread Group (100 users, 60s ramp-up)
│   ├── HTTP Request Defaults (example.com)
│   ├── HTTP Cookie Manager
│   ├── HTTP Request: Home Page (GET /)
│   ├── HTTP Request: Login (POST /api/login)
│   ├── HTTP Request: Dashboard (GET /dashboard)
│   ├── Response Assertion (check status 200)
│   ├── Duration Assertion (< 2000ms)
│   └── Constant Timer (1000ms think time)
├── View Results Tree
└── Summary Report

6. JMeter: Assertions

Response Assertion

Проверяет содержимое ответа сервера. Самый часто используемый тип assertion.

ПолеВарианты

Field to Test

Text Response, Response Code, Response Headers, Document

Pattern Matching

Contains, Matches, Equals, Substring, Not

Пример: проверить, что ответ содержит «Welcome»

Field to Test: Text Response
Pattern Matching Rules: Contains
Patterns to Test: Welcome

Duration Assertion

Проверяет, что время ответа не превышает заданное значение. Идеально для валидации SLA.

Duration in milliseconds: 2000

Если запрос занимает больше 2 секунд — помечается как failed.

Факт: Duration Assertion практически не влияет на производительность теста, так как JMeter уже измеряет response time — assertion просто сравнивает с заданным значением.

JSON Assertion

Для API-тестирования: проверка значений в JSON-ответе.

Assert JSON Path exists: $.data.user.id
Expected Value: 12345

7. Gatling: быстрый старт

Установка

  1. Требования: Java 8+ или Java 11+

  2. Скачать: gatling.io

  3. Распаковать архив

  4. Или: Создать Maven/Gradle проект с Gatling plugin

Структура проекта

gatling-project/
├── src/
│   └── test/
│       ├── scala/
│       │   └── simulations/
│       │       └── MyFirstSimulation.scala
│       └── resources/
│           └── data/
│               └── users.csv
├── pom.xml (или build.gradle)
└── gatling.conf

Первый тест на Scala

package simulations

import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class MyFirstSimulation extends Simulation {

  // HTTP Configuration
  val httpProtocol = http
    .baseUrl("https://example.com")
    .acceptHeader("application/json")
    .userAgentHeader("Gatling")

  // Scenario
  val scn = scenario("Basic Load Test")
    .exec(
      http("Home Page")
        .get("/")
        .check(status.is(200))
    )
    .pause(1) // Think time: 1 second
    .exec(
      http("API Request")
        .get("/api/data")
        .check(status.is(200))
        .check(jsonPath("$.status").is("ok"))
    )

  // Load Profile
  setUp(
    scn.inject(
      rampUsers(100).during(60.seconds) // 100 users over 60 seconds
    )
  ).protocols(httpProtocol)
}

Ключевые концепции Gatling

КонцепцияОписание

Simulation

Класс теста, наследует Simulation

Scenario

Сценарий поведения пользователя

HTTP Protocol

Настройки HTTP (base URL, headers)

Injection Profile

Как пользователи появляются (ramp, constant, etc.)

Checks

Проверки ответа (аналог assertions)

Feeders

Источники тестовых данных (CSV, JSON)

Injection Profiles

// Постепенный рост
rampUsers(100).during(60.seconds)

// Константная нагрузка
constantUsersPerSec(10).during(5.minutes)

// Пиковая нагрузка (spike)
atOnceUsers(1000)

// Комбинация
setUp(
  scn.inject(
    nothingFor(5.seconds),
    atOnceUsers(10),
    rampUsers(100).during(60.seconds),
    constantUsersPerSec(20).during(10.minutes)
  )
)

Запуск теста

Через shell script:

bin/gatling.sh

Через Maven:

mvn clean gatling:test

Через Gradle:

gradle gatlingRun

Отчёты Gatling

Gatling генерирует красивые HTML-отчёты автоматически:

  • Global statistics (min/max/mean/percentiles)

  • Response time distribution

  • Active users over time

  • Requests per second

  • Response time percentiles over time


8. Gatling: продвинутые возможности

Feeders (Тестовые данные)

// CSV Feeder
val csvFeeder = csv("users.csv").circular

val scn = scenario("Login Test")
  .feed(csvFeeder)
  .exec(
    http("Login")
      .post("/api/login")
      .formParam("username", "${username}")
      .formParam("password", "${password}")
  )

Файл users.csv:

username,password
user1,pass1
user2,pass2
user3,pass3

Корреляция (извлечение данных)

val scn = scenario("Extract Token")
  .exec(
    http("Login")
      .post("/api/login")
      .body(StringBody("""{"user":"test","pass":"test"}"""))
      .check(jsonPath("$.token").saveAs("authToken"))
  )
  .exec(
    http("Protected Resource")
      .get("/api/data")
      .header("Authorization", "Bearer ${authToken}")
  )

Assertions на уровне simulation

setUp(
  scn.inject(rampUsers(100).during(60.seconds))
).protocols(httpProtocol)
  .assertions(
    global.responseTime.max.lt(5000),    // Max < 5s
    global.responseTime.percentile3.lt(2000), // P95 < 2s
    global.successfulRequests.percent.gt(99)  // Success > 99%
  )

Если assertion не проходит — тест считается failed (полезно для CI/CD).


9. Другие инструменты: k6 и Locust

k6 (Grafana k6)

Современный инструмент от Grafana Labs. Тесты пишутся на JavaScript.

ПлюсыМинусы
JavaScript — знакомый языкНет GUI
Отличная CI/CD интеграцияМеньше протоколов, чем JMeter
Низкое потребление ресурсовОблачная версия платная
Встроенные метрики и визуализация 
// k6 пример
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 100,
  duration: '60s',
};

export default function () {
  const res = http.get('https://example.com/');
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
  sleep(1);
}

Locust

Python-based инструмент с веб-интерфейсом для мониторинга.

ПлюсыМинусы
Python — простой для освоенияТолько HTTP (в основном)
Веб-интерфейс для мониторингаМенее производительный, чем Gatling/k6
Distributed testing из коробки 
Бесплатный и open source 
# Locust пример
from locust import HttpUser, task, between

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

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

    @task(3)  # Weight: выполняется в 3 раза чаще
    def api_call(self):
        self.client.get("/api/data")

Сравнение современных инструментов

ИнструментЯзык тестовGUIПроизводительностьCI/CD

JMeter

GUI/XMLСредняяЧерез плагины

Gatling

Scala/Java/KotlinВысокаяНативная

k6

JavaScriptВысокаяНативная

Locust

PythonWeb UIСредняяХорошая

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

Зачем интегрировать в пайплайн

  • Автоматическое обнаружение регрессий производительности

  • Performance gates: блокировка релиза при деградации

  • Исторические данные для трендов

  • Shift-left: раннее обнаружение проблем

Факт: «Etsy использует Jenkins для автоматического запуска тестов и ловит 90% проблем производительности до продакшена.»

JMeter в Jenkins

pipeline {
    agent any

    stages {
        stage('Performance Test') {
            steps {
                sh '''
                    jmeter -n -t tests/load-test.jmx \
                           -l results/results.jtl \
                           -e -o results/report/
                '''
            }
        }

        stage('Publish Results') {
            steps {
                perfReport sourceDataFiles: 'results/results.jtl'
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: 'results/**'
        }
    }
}

Gatling в Jenkins

pipeline {
    agent any

    stages {
        stage('Performance Test') {
            steps {
                sh 'mvn clean gatling:test'
            }
        }
    }

    post {
        always {
            gatlingArchive()
        }
    }
}

Performance Gates

Автоматическая проверка SLA и блокировка релиза при нарушении:

// Gatling assertions для CI/CD
setUp(scn.inject(...))
  .assertions(
    global.responseTime.percentile3.lt(2000), // P95 < 2s
    global.failedRequests.percent.lt(1)       // Errors < 1%
  )

Если assertions не проходят — Gatling возвращает non-zero exit code, и пайплайн падает.


11. Типичные ошибки начинающих

1. Отсутствие Think Time

❌ Ошибка: Запросы без пауз между ними

Реальные пользователи не кликают мгновенно. Без think time вы создаёте нереалистичную нагрузку и перегружаете систему больше, чем она будет нагружена в реальности.

Решение: Добавляйте паузы (1-5 секунд) между запросами:

// JMeter: Constant Timer = 2000ms

// Gatling:
.pause(2)  // 2 секунды
.pause(1, 3)  // случайно от 1 до 3 секунд

2. Тестирование слишком поздно

❌ Ошибка: Нагрузочное тестирование только перед релизом

Найденные проблемы сложно и дорого исправлять.

Решение: Начинайте с базовых тестов на ранних этапах. Интегрируйте в CI/CD.

3. Нереалистичные сценарии

ОшибкаРешение
Все пользователи делают одно и то жеРазные сценарии с разным весом
Одни и те же тестовые данныеFeeders с реалистичными данными
Нет географического распределенияDistributed testing из разных регионов

4. Перегрузка Load Generator

⚠️ Проблема: Слишком много пользователей на одной машине → bottleneck на стороне генератора, не сервера.

Решение:

  • Мониторьте CPU/память машины с JMeter/Gatling

  • Используйте distributed testing

  • JMeter: ~300-500 threads на машину

  • Gatling: значительно больше благодаря async

5. Игнорирование ошибок в скриптах

Если скрипт возвращает ошибки — результаты теста невалидны. Всегда проверяйте:

  • Response codes (200 vs 500)

  • Response body содержит ожидаемые данные

  • Транзакции реально выполняются (проверьте в БД)

6. Тестирование на неполных данных

Факт: «Запрос, который выполняется меньше 1 секунды на БД 10 ГБ, может занимать более 10 секунд на БД 100 ГБ.»

Решение: База данных в тестовой среде должна быть близка к продакшену по объёму.

7. Мониторинг только Response Time

Response time важен, но недостаточен. Мониторьте также:

  • CPU и память серверов

  • Database connections и query time

  • Network I/O

  • Очереди и кэши


12. Best Practices

Планирование теста

  1. Определите цели: Какую нагрузку должна выдержать система?

  2. Соберите требования: SLA, ожидаемое количество пользователей, критичные сценарии

  3. Проанализируйте продакшен: Реальные паттерны использования, пиковые часы

  4. Создайте реалистичные сценарии: Не один запрос, а user journey

Выполнение теста

  • ✅ Используйте CLI-режим для реальных тестов (не GUI)

  • ✅ Изолируйте тестовую среду от продакшена

  • ✅ Начинайте с малой нагрузки, постепенно увеличивайте

  • ✅ Записывайте baseline перед изменениями

  • ✅ Повторяйте тесты для статистической значимости

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

  • ✅ Смотрите на перцентили, не только средние

  • ✅ Корреляция с серверными метриками

  • ✅ Сравнение с baseline и предыдущими тестами

  • ✅ Документируйте результаты и условия теста

Чек-лист перед тестом

  • ☐ Тестовая среда изолирована и стабильна

  • ☐ База данных наполнена реалистичными данными

  • ☐ Сценарии соответствуют реальному использованию

  • ☐ Think time добавлен

  • ☐ Assertions настроены

  • ☐ Мониторинг серверов включён

  • ☐ Baseline зафиксирован

  • ☐ Команда уведомлена о проведении теста


13. Матрица выбора инструмента

Вопросы для выбора

ВопросJMeterGatlingk6Locust
Команда умеет программировать?Не обязательноДа (Scala)Да (JS)Да (Python)
Нужен GUI?✅ Есть❌ Нет❌ НетWeb UI
Тестирование не-HTTP?✅ Много протоколовОграниченноОграниченно❌ В основном HTTP
Высокие нагрузки (10k+ users)?Distributed✅ Эффективен✅ ЭффективенDistributed
CI/CD важен?Плагины✅ Нативно✅ Нативно✅ Хорошо
Нужны красивые отчёты?Плагины✅ Из коробкиCLI + GrafanaБазовые

Рекомендации по ситуациям

СитуацияРекомендация
QA без опыта программирования🟢 JMeter
Команда разработчиков🟢 Gatling или k6
Python-команда🟢 Locust
JavaScript-команда🟢 k6
Enterprise с разными протоколами🟢 JMeter
Микросервисы и API🟢 Gatling или k6
CI/CD-first подход🟢 Gatling или k6
Ограниченные ресурсы машин🟢 Gatling (async)

14. Пример сквозного теста

Сценарий: E-commerce checkout

Типичный сценарий для интернет-магазина:

  1. Открыть главную страницу

  2. Поиск товара

  3. Просмотр товара

  4. Добавление в корзину

  5. Переход в корзину

  6. Оформление заказа

JMeter Test Plan (структура)

Test Plan: E-commerce Load Test
├── Thread Group (200 users, 120s ramp-up, 10 min duration)
│   ├── HTTP Request Defaults
│   │   └── Server: shop.example.com
│   ├── HTTP Cookie Manager
│   ├── CSV Data Set Config (products.csv)
│   │
│   ├── Transaction Controller: Browse
│   │   ├── HTTP Request: Home Page (GET /)
│   │   ├── Gaussian Random Timer (1000-3000ms)
│   │   ├── HTTP Request: Search (GET /search?q=${product})
│   │   └── Gaussian Random Timer (2000-4000ms)
│   │
│   ├── Transaction Controller: View Product
│   │   ├── HTTP Request: Product Page (GET /product/${productId})
│   │   └── Gaussian Random Timer (3000-5000ms)
│   │
│   ├── Transaction Controller: Add to Cart
│   │   ├── HTTP Request: Add to Cart (POST /cart/add)
│   │   └── Gaussian Random Timer (1000-2000ms)
│   │
│   ├── Transaction Controller: Checkout
│   │   ├── HTTP Request: View Cart (GET /cart)
│   │   ├── HTTP Request: Checkout (POST /checkout)
│   │   └── Response Assertion: Order Confirmed
│   │
│   ├── Duration Assertion: All requests < 3000ms
│   │
├── Aggregate Report
└── HTML Report (Dashboard)

Gatling Simulation

class EcommerceSimulation extends Simulation {

  val httpProtocol = http
    .baseUrl("https://shop.example.com")
    .acceptHeader("text/html,application/json")

  val productFeeder = csv("products.csv").random

  val browse = exec(
    http("Home Page").get("/").check(status.is(200))
  ).pause(1, 3)
  .feed(productFeeder)
  .exec(
    http("Search").get("/search?q=${product}").check(status.is(200))
  ).pause(2, 4)

  val viewProduct = exec(
    http("Product Page")
      .get("/product/${productId}")
      .check(status.is(200))
      .check(css("button.add-to-cart").exists)
  ).pause(3, 5)

  val addToCart = exec(
    http("Add to Cart")
      .post("/cart/add")
      .formParam("productId", "${productId}")
      .check(status.is(200))
  ).pause(1, 2)

  val checkout = exec(
    http("View Cart").get("/cart").check(status.is(200))
  ).pause(2)
  .exec(
    http("Checkout")
      .post("/checkout")
      .check(status.is(200))
      .check(substring("Order Confirmed"))
  )

  val scn = scenario("E-commerce Flow")
    .exec(browse, viewProduct, addToCart, checkout)

  setUp(
    scn.inject(
      rampUsers(200).during(120.seconds),
      constantUsersPerSec(2).during(10.minutes)
    )
  ).protocols(httpProtocol)
   .assertions(
     global.responseTime.percentile3.lt(3000),
     global.successfulRequests.percent.gt(99)
   )
}

Итоги

Нагрузочное тестирование — не роскошь, а необходимость. Узнать о проблемах производительности до пользователей — в разы дешевле и проще, чем разбираться с инцидентами на продакшене.

Ключевые выводы:

  • JMeter — для команд без опыта программирования, широкого спектра протоколов, богатой экосистемы плагинов

  • Gatling — для разработчиков, высоких нагрузок, CI/CD интеграции, красивых отчётов

  • k6 — для JavaScript-команд, DevOps-культуры, современных API

  • Locust — для Python-команд, простых сценариев

Важные принципы:

  • Смотрите на перцентили (P95, P99), не средние

  • Добавляйте think time между запросами

  • Используйте реалистичные сценарии и данные

  • Интегрируйте в CI/CD с performance gates

  • Тестируйте рано и часто, не только перед релизом

  • Мониторьте не только response time, но и серверные метрики

Формула успешного нагрузочного тестирования:

Реалистичные сценарии + Правильные метрики + Регулярность + CI/CD интеграция = Уверенность в производительности

Начните с простого: установите JMeter или Gatling, создайте тест на один endpoint, запустите с 10 пользователями. Затем усложняйте: добавляйте сценарии, увеличивайте нагрузку, интегрируйте в пайплайн. Главное — начать.

А лучшие вакансии для QA (тестировщиков) ищите на hirehi.ru