Lesson 13 of 26
Урок 13 — Load Testing
Название: Load Testing — проверяем систему под нагрузкой
Описание: Разбираем нагрузочное тестирование: что это, зачем нужно, как проводить, какие метрики собирать и какие инструменты использовать. Примеры с k6 и JMeter.
Почему это важно для QA: Сайт может отлично работать для одного пользователя и падать при 500. Нагрузочное тестирование — это страховка от позорных падений в момент рекламной кампании или пика продаж.
1. Что такое Load Testing
Load Testing (нагрузочное тестирование) — это тип нефункционального тестирования, при котором система проверяется под ожидаемой нагрузкой — тем количеством пользователей или запросов, которое реально ожидается в production.
Аналогия
Ты строишь мост и заявляешь, что он выдержит 10 тонн. Load Testing — это когда ты ставишь на мост ровно 10 тонн и смотришь: держит? Не гнётся? Не скрипит?
Если скрипит — нужна доработка. Если выдерживает спокойно — мост готов.
2. Цели Load Testing
- Убедиться, что система выдерживает ожидаемое количество пользователей
- Найти узкие места (bottlenecks) в производительности
- Определить максимальную пропускную способность системы
- Проверить время отклика под нагрузкой
- Убедиться, что система восстанавливается после пиковой нагрузки
3. Ключевые метрики
| Метрика | Что измеряет | Хороший показатель |
|---|---|---|
| Response Time | Время от запроса до ответа | < 200 мс (API), < 2 сек (страница) |
| Throughput | Кол-во запросов в секунду (RPS) | Зависит от требований |
| Error Rate | % ошибочных запросов | < 1% |
| Concurrent Users | Кол-во одновременных пользователей | Зависит от требований |
| CPU / Memory | Использование ресурсов сервера | CPU < 70%, Memory < 80% |
| P95 / P99 | 95-й и 99-й перцентиль времени отклика | P95 < 500 мс |
Что такое перцентили
P50 (медиана) = 150 мс: половина запросов быстрее 150 мс
P95 = 800 мс: 95% запросов быстрее 800 мс (только 5% медленнее)
P99 = 2000 мс: 99% запросов быстрее 2 сек (только 1% медленнее)
ВАЖНО: средний (average) показатель обманчив. Используй перцентили.
Пример: среднее 200 мс выглядит хорошо, но P99 может быть 5000 мс.4. Типы нагрузочного тестирования
| Тип | Описание | Нагрузка |
|---|---|---|
| Load Test | Проверка под ожидаемой нагрузкой | 100% от ожидаемой |
| Stress Test | Проверка за пределами ожидаемой | > 100% (до отказа) |
| Spike Test | Резкий скачок нагрузки | 0 → 500% мгновенно |
| Soak Test | Длительная нагрузка | 80% в течение 8–24 часов |
| Volume Test | Тестирование с большим объёмом данных | Миллионы записей в БД |
5. Профиль нагрузки (Load Profile)
Перед тестированием нужно определить профиль нагрузки:
Сценарий: Интернет-магазин перед распродажей
────────────────────────────────────────────
Ожидаемые пользователи: 5 000 одновременно
Пиковая нагрузка: 10 000 одновременно (во время акции)
Критические операции:
- Главная страница: 2000 просмотров/мин
- Поиск товаров: 1500 запросов/мин
- Страница товара: 3000 просмотров/мин
- Добавление в корзину: 500 операций/мин
- Оформление заказа: 200 операций/мин
Требования к отклику:
- Главная страница: < 1.5 сек
- API поиска: < 500 мс
- Оформление заказа: < 3 сек6. Пример Load Test с k6
k6 — современный инструмент для нагрузочного тестирования от Grafana Labs.
Установка
# Windows (через Chocolatey)
choco install k6
# macOS
brew install k6
# Docker
docker run grafana/k6 run - <script.jsБазовый скрипт нагрузочного теста
// load-test.js
import http from "k6/http";
import { sleep, check } from "k6";
import { Rate, Trend } from "k6/metrics";
const errorRate = new Rate("errors");
const searchDuration = new Trend("search_duration", true);
export const options = {
stages: [
{ duration: "2m", target: 100 }, // плавный старт: 0 → 100 пользователей
{ duration: "5m", target: 500 }, // нарастание до ожидаемой нагрузки
{ duration: "10m", target: 500 }, // удержание пика
{ duration: "3m", target: 0 }, // плавный спад
],
thresholds: {
http_req_duration: ["p(95)<500"], // 95% запросов быстрее 500 мс
errors: ["rate<0.01"], // ошибки < 1%
http_req_failed: ["rate<0.01"],
},
};
export default function () {
// Тест: поиск товаров
const searchStart = Date.now();
const searchResponse = http.get("https://shop.example.com/api/products?q=laptop");
const searchTime = Date.now() - searchStart;
searchDuration.add(searchTime);
errorRate.add(searchResponse.status !== 200);
check(searchResponse, {
"статус 200": (r) => r.status === 200,
"ответ содержит products": (r) => r.json("products") !== null,
"время отклика < 500мс": (r) => r.timings.duration < 500,
});
sleep(1); // пауза 1 секунда между итерациями
}
Запуск теста
k6 run load-test.js
# С выводом в HTML-отчёт
k6 run --out html=report.html load-test.js
# С выводом в Grafana
k6 run --out influxdb=http://localhost:8086/k6 load-test.jsПример вывода k6
/\ |‾‾| /‾‾/ /‾‾/
/\ / \ | |/ / / /
/ \/ \ | ( / ‾‾\
/ \ | |\ \ | (‾) |
/ __________ \ |__| \__\ \_____/ .io
execution: local
script: load-test.js
output: -
scenarios: (100.00%) 1 scenario, 500 max VUs, 20m30s max duration
running (20m00s), 0/500 VUs, 24500 complete and 0 interrupted iterations
default ✓ [======================================] 0/500 VUs 20m0s
✓ статус 200
✓ ответ содержит products
✗ время отклика < 500мс
↳ 91% — ✓ 22235 / ✗ 2265
checks.........................: 97.05% ✓ 71265 ✗ 2265
data_received..................: 1.2 GB 1.0 MB/s
http_req_duration..............: avg=312ms min=45ms med=218ms max=4.2s p(90)=680ms p(95)=920ms
http_req_failed................: 0.40% ✓ 98 ✗ 24402
FAILED! 1 thresholds breached.
✗ http_req_duration (p(95)<500)Из отчёта видно: P95 = 920 мс при требовании 500 мс. Система не выдерживает нагрузку по требованиям.
7. Инструменты Load Testing
| Инструмент | Язык | Особенности |
|---|---|---|
| k6 | JavaScript | Современный, скриптовый, CI-friendly |
| JMeter | GUI + XML | Классический, мощный, сложный |
| Gatling | Scala / Java | Код-first, хорошие отчёты |
| Locust | Python | Простой, Pythonic |
| Artillery | JavaScript | YAML-конфиги, облачный режим |
| wrk | CLI | Простые HTTP-бенчмарки |
8. Где искать узкие места
После нагрузочного теста нужно анализировать:
Сервер → CPU / Memory / Disk I/O
База данных → медленные запросы (slow queries log)
Сеть → пропускная способность
Код → N+1 запросы, отсутствие кеширования
Архитектура → отсутствие горизонтального масштабирования9. Частые ошибки
❌ Тестируют на production
→ Нагрузочный тест — только на Staging или выделенном окружении.
❌ Не используют реалистичный профиль нагрузки
→ 1000 запросов только к одной странице — не реалистично. Имитируй реальное поведение пользователей.
❌ Смотрят только на среднее время ответа
→ Используй P95, P99. Средний показатель скрывает проблемы.
❌ Не мониторят серверные ресурсы
→ Нагрузочный тест без мониторинга CPU/Memory бесполезен.
Итог
LOAD TESTING
├── Цель: убедиться, что система работает под ожидаемой нагрузкой
├── Метрики: Response Time, Throughput, Error Rate, P95, P99
├── Инструменты: k6, JMeter, Locust, Gatling
├── Профиль: нарастание → пик → удержание → спад
├── Не: не тестируй на production
└── После: анализируй bottlenecks и оптимизируй