Тестирование программного обеспечения
Нагрузочное тестирование и стресс-тестирование: Различия, метрики и примеры k6
Один из них доказывает, что ваша система обрабатывает ожидаемый трафик. Другой узнает, где оно ломается и как восстанавливается. Узнайте, когда запускать каждый из них, каким цифрам доверять и как спланировать тест, который даст реальные ответы.
- Нагрузочное тестирование проверяет, соответствует ли система своим целям при ожидаемом трафике.
- Стресс-тестирование расширяет возможности найти переломный момент и изучить восстановление.
- Инструменты обычно одни и те же. Отличие заключается в цели и структуре трафика.
- Оценивайте результаты с помощью процентилей, таких как p95 и p99, поскольку средние значения могут скрывать серьезные проблемы.
Ваше приложение прекрасно работает с десятью пользователями. Что произойдет в день распродажи с десятью тысячами? Нагрузочное тестирование и стресс-тестирование описывают два разных способа ответа на этот вопрос, и их смешение приводит к тестам, которые не доказывают то, что, по вашему мнению, они делают.
В этом руководстве объясняется, что показывает каждый из них, связанные типы тестов и как читать результаты. Ниже мы выполнили небольшой расчет процентиля на Python 3.13 с смоделированными числами. Скрипты k6 — это наглядные примеры, которые мы не выполняли, а количество пользователей и цели придуманы, поэтому замените их своими. Запускайте эти тесты только на тех системах, которыми вы владеете или имеете разрешение на тестирование, поскольку большой трафик может выглядеть как атака и вызывать реальные сбои.
Короткий ответ
Нагрузочный тест спрашивает: можем ли мы справиться с ожидаемым трафиком и достичь при этом наших целей? Стресс-тест спрашивает: сколько мы можем выдержать, прежде чем потерпим неудачу, как мы потерпим неудачу и как быстро мы восстановимся?
Подумайте о мосте. Нагрузочный тест проезжает ожидаемое количество грузовиков и подтверждает, что все в порядке. Стресс-тест продолжает прибавлять вес, чтобы узнать его предел и определить, выдает ли он предупреждение в первую очередь. К счастью, сломать программное обеспечение дешевле, чем мост.
Нагрузочное тестирование и стресс-тестирование бок о бок
| Аспект | Нагрузочное тестирование | Стресс-тестирование |
|---|---|---|
| Главный вопрос | Достигаем ли мы целевых показателей при ожидаемой нагрузке? | Где и как мы ломаемся? |
| Уровень трафика | От нормального до ожидаемого пика | За пределами ожидаемого пика |
| Узор | Набирайте темп, держитесь устойчиво | Продолжайте увеличивать до отказа |
| Неудача | Неудачный тест | Ожидаемый результат |
| Ключевые показатели | Время отклика, пропускная способность, ошибки | Точка разрушения, режим отказа, время восстановления |
| Типичное время | Перед каждым крупным релизом или событием | После того, как система стабилизируется под нагрузкой |
| Результат | Пройти или провалиться против целей | Ограничение мощности и список слабых мест |
Что такое нагрузочное тестирование?
Нагрузочное тестирование имитирует ожидаемый реалистичный трафик и измеряет поведение системы. Ему нужна цель для тестирования, например: «при 500 одновременных пользователях 95% запросов на оформление завершаются в течение 800 мс, с ошибками менее 1%.»
Вот как это может выглядеть в виде сценария k6. Тесты k6 написаны на JavaScript и thresholds превращают ваши цели в результат «пройден» или «не пройден»:
import http from "k6/http";
import { sleep } from "k6";
export const options = {
stages: [
{ duration: "5m", target: 500 }, // ramp up
{ duration: "20m", target: 500 }, // hold at expected peak
{ duration: "2m", target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ["p(95)<800"],
http_req_failed: ["rate<0.01"],
},
};
export default function () {
http.get("https://staging.example.com/products");
sleep(1); // think time, as real users pause
}
sleep имеет значение. Не тратя времени на раздумья, каждый виртуальный пользователь постоянно загружает сервер, производя гораздо больше трафика, чем такое же количество реальных людей.
Что такое стресс-тестирование?
Стресс-тестирование намеренно выходит за рамки ожидаемых уровней. Вы не пытаетесь пройти. Вам нужны ответы на такие вопросы, как:
- На каком уровне производительность начинает падать?
- Какой компонент выходит из строя первым: база данных, серверы приложений или сторонний вызов?
- Происходит ли он корректно с явными ошибками или происходит сбой и потеря данных?
- Восстанавливается ли он сам при падении трафика?
export const options = {
stages: [
{ duration: "5m", target: 500 }, // expected peak
{ duration: "5m", target: 1000 }, // beyond it
{ duration: "5m", target: 2000 }, // further
{ duration: "5m", target: 4000 }, // likely to break
{ duration: "10m", target: 0 }, // recovery: does it come back?
],
};
Об этом заключительном этапе восстановления часто забывают, и он может быть самым ценным. Система, которая хорошо справляется со сбоями, но никогда не восстанавливается без ручного перезапуска, по-прежнему означает сбой, который кто-то должен устранить посреди ночи. В идеале при экстремальной нагрузке система должна прекращать работу контролируемым образом, возвращая четкие 503 ответа вместо тайм-аута.
Шип, замачивание и другие типы
Нагрузочные и стресс-тесты относятся к более широкому семейству тестов производительности:
| Тип | Узор | Что он находит |
|---|---|---|
| Дым (спектакль) | Несколько пользователей, кратко | Работают ли вообще скрипт и система |
| Загрузить | Ожидаемый пик, удержан | Достигнуты ли цели |
| Стресс | Рост прошлых мощностей | Пределы и режимы отказа |
| Спайк | Внезапный прыжок, затем падение | Автомасштабирование и поведение очереди |
| Замачивание (выносливость) | Нормальная нагрузка в течение нескольких часов | Утечки памяти, кончающиеся соединения |
| Емкость | Постепенное увеличение | Максимальная нагрузка в пределах ваших целей |
Тесты на выдержку выявляют проблемы, которые никогда не обнаруживаются короткими тестами. Небольшая утечка памяти может выглядеть безобидной в течение двадцати минут и привести к отключению службы только через два дня. Пиковые тесты подходят для таких мероприятий, как флэш-продажи, где трафик не увеличивается постепенно.
Метрики, которые имеют значение
| Метрика | Значение | Следите за |
|---|---|---|
| Время ответа (процентили) | Сколько времени занимают запросы | p95 и p99 повышаются |
| Пропускная способность | Запросов, обрабатываемых в секунду | Сглаживание по мере увеличения числа пользователей |
| Частота ошибок | Процент неудачных запросов | Любой внезапный подъем |
| Процессор и память | Использование ресурсов сервера | Насыщение, или устойчивый рост |
| База данных | Медленные запросы, использование пула соединений | Бассейн исчерпан, замок ждет |
| Глубина очереди | Работа ожидает обработки | Рост, который никогда не истощается |
Почему средние значения вводят в заблуждение
Средние значения скрывают медленные запросы, на которые жалуются реальные люди. Чтобы продемонстрировать это, мы сгенерировали 100 смоделированных времен отклика, из которых 95 были быстрыми (от 80 до 200 мс), а 5 — очень медленными (от 2,5 до 4 секунд), а затем рассчитали общую статистику:
import math, random, statistics
random.seed(3)
times = [random.randint(80, 200) for _ in range(95)] \
+ [random.randint(2500, 4000) for _ in range(5)]
def pct(values, p):
values = sorted(values)
return values[math.ceil(p / 100 * len(values)) - 1]
print("avg", round(statistics.mean(times)), "p50", pct(times, 50),
"p95", pct(times, 95), "p99", pct(times, 99), "max", max(times))
# avg 302 p50 150 p95 199 p99 3740 max 3896
Посмотрите внимательно на эти цифры. Среднее значение 302 мс никого не характеризует. Типичные запросы занимали около 150 мс, а медленные — более 3 секунд. Даже p95 выглядит здоровым на 199 мс, и только p99 выявляет проблему. Такая цифра, как p95, означает, что 95% запросов были такими же быстрыми или быстрее.
И один процент запросов – явление не редкое. Если страница отправляет 50 запросов, медленный p99 влияет на большую долю просмотров страниц. Установите цели для важных для вас процентилей и рассмотрите несколько из них вместе.
Совет. Ищите «колено» на своих графиках. По мере увеличения нагрузки время отклика какое-то время остается неизменным, а затем внезапно увеличивается, а пропускная способность перестает расти. Эта точка и есть ваши практические возможности, и она часто наступает задолго до того, как что-то действительно потерпит крах.
Инструменты
| Инструмент | Сценарии | Известный |
|---|---|---|
| к6 | JavaScript | Удобен для разработчиков, пороговые значения подходят для CI |
| JMeter | Графический интерфейс и XML | Зрелый, поддерживает множество протоколов |
| Гатлинг | Scala, Java, Kotlin и другие. | На основе кода, эффективный |
| Саранча | Питон | Простое поведение пользователя на основе Python |
Любой из них может запускать как нагрузочные, так и стресс-тесты. Выберите тот, который соответствует навыкам вашей команды, а не гонитесь за списком функций. Чтобы использовать его в своем конвейере, см. что такое CI/CD.
Как спланировать тест
- Установите цели. Используйте реальную аналитику, чтобы определить пиковый трафик и определить цели.
- Выбирайте путешествия. Моделируйте реалистичное поведение пользователей, например просмотр, поиск и оформление заказа, в реалистичных пропорциях. Посещение только домашней страницы мало что доказывает.
- Используйте реалистичную среду. Крошечный промежуточный сервер не может предсказать производительность. Обратите внимание на любые различия.
- Подготовьте данные. Используйте реалистичные объемы, поскольку запрос, который быстро обрабатывает 100 строк, может просканировать 10 миллионов.
- Предупредите людей. Сообщите об этом своей операционной команде и третьим лицам и не запускайте случайное нагрузочное тестирование платежной системы. Имитируйте внешние сервисы, где это возможно.
- Начните с малого. Сначала проведите небольшой дым-тест, чтобы убедиться, что ваш скрипт работает.
- Мониторьте все. Без показателей сервера вы увидите, что он замедлился, но не почему.
- Повторите. Запускайте его снова после каждого исправления и сохраняйте базовый уровень для сравнения.
Чтение результатов
| Симптом | Возможная причина |
|---|---|
| Медленные ответы, но низкий процессор | Ожидание базы данных, блокировки или внешней службы |
| Процессор базы данных высок | Отсутствующие индексы или неэффективные запросы |
| Внезапные ошибки подключения | Достигнут лимит пула подключений или файлов |
| Память постоянно растет | Утечка, или неограниченный кэш |
| Нагрузка на процессор генератора высокая | Инструмент тестирования — это узкое место, а не ваша система |
Базы данных являются распространенным узким местом, поэтому, если проблема связана с запросами, прочитайте наше руководство по оптимизации SQL-запросов. Эта последняя строка таблицы является важной ловушкой: всегда проверяйте также исправность машины, генерирующей нагрузку.
Распространенные ошибки
- Запутывает пользователей запросами. Уточните, означает ли цель количество одновременных пользователей или количество запросов в секунду.
- Не хватает времени на размышления. Это увеличивает трафик и приводит к вводящим в заблуждение результатам.
- Тестирование слишком позднее. Неделя до запуска не оставляет времени на исправление проблем с архитектурой.
- Использование одной конечной точки. Реальный трафик смешивает операции чтения, записи и поиска.
- Кэширование скрывает всё. Идентичные повторяющиеся запросы могут только проверить ваш кеш, поэтому меняйте данные.
- Тестирование один раз. Производительность меняется с каждым выпуском, поэтому запускайте тесты регулярно.
Итоги
Запустите нагрузочные тесты, чтобы убедиться, что вы можете справиться с ожидаемым трафиком, и стресс-тесты, чтобы узнать, что происходит, когда вы не можете этого сделать. Начните с малого: выберите наиболее важный путь пользователя, установите одну четкую цель и проведите небольшой тест на промежуточную реализацию с включенным мониторингом. Этот первый запуск обычно чему-то вас учит, и вы можете дальше строить.
Часто задаваемые вопросы
В чем основная разница между нагрузочным и стресс-тестированием?
Нагрузочное тестирование проверяет поведение при ожидаемом трафике на соответствие установленным целям. Стресс-тестирование выходит за рамки возможности найти переломный момент и способ восстановления системы.
Должен ли я сначала запустить нагрузочное тестирование или стресс-тестирование?
Сначала нагрузочный тест. Как только система достигнет своих целей при ожидаемом трафике, запустите стресс-тесты, чтобы изучить ее пределы. Результаты стресса мало что значат для нестабильной системы.
В чем разница между стресс-тестом и спайк-тестом?
Стресс-тест обычно увеличивает нагрузку шаг за шагом, пока не произойдет сбой. Пиковый тест внезапно переходит на высокий уровень, чтобы увидеть, как система справляется с резкими изменениями.
Что такое время отклика p95?
Это означает, что 95% запросов выполняются в это время или раньше. Он описывает опыт большинства пользователей лучше, чем в среднем.
Могу ли я запускать нагрузочные тесты на производстве?
Можно, но осторожно, с разрешения, контроля и способа быстрой остановки. Большинство команд начинают с промежуточной среды, похожей на производственную, чтобы снизить риск для реальных пользователей.
Продолжайте учиться
Нужна помощь с тестированием, WordPress или SEO?
Мы помогаем командам выпускать лучшее программное обеспечение и развивать свои сайты. Расскажите нам, над чем вы работаете, и мы предложим четкий следующий шаг.
Больше руководств по тестирование, искусственный интеллект и современные разработки
Понравилась эта статья? Выберите тему и сразу приступайте к нашим новейшим руководствам.
Объяснение галлюцинаций искусственного интеллекта: почему языковые модели все выдумывают и как их уменьшить
Галлюцинации ИИ объяснили: что это такое, почему языковые модели их создают, распространенные типы, как уменьшить их с помощью заземления и подсказо…
Читать статью →DevOpsОбъяснение переменных среды: файлы .env, секреты и правильно выполненная конфигурация
Переменные среды объясняются на примерах Python, которые мы запускали: их чтение и установка, почему каждое значение является строкой, файлы .env, н…
Читать статью →Разработка ПООбъяснение ограничения скорости API: алгоритмы, заголовки и обработка ошибок 429
Ограничение скорости API объясняется с помощью проведенного нами моделирования: сегмент токенов, фиксированное окно, скользящее окно, 429 ответов, з…
Читать статью →Автоматизация тестированияИздевательство в Python: unittest.mock, патч и ошибки, из-за которых тесты лгут
Издевательство на Python с помощью unittest.mock, протестировано: Mock и return_value, Side_effect, исправление использования имени, спецификация и …
Читать статью →Тестирование ПООбъяснение покрытия кода: покрытие линий или ветвей и что на самом деле означает 100%
Покрытие кода объяснено с помощью реального запуска покрытия.py: покрытие строк, ветвей и условий, чтение отчета, почему 100%-ное покрытие все еще м…
Читать статью →Базы данных и SQLDELETE, TRUNCATE и DROP в SQL: различия, откат и когда использовать каждый из них
Объяснение DELETE, TRUNCATE и DROP на примере протестированного SQL: что каждый из них удаляет, откат, триггеры, сброс идентификаторов, скорость и ч…
Читать статью →Базы данных и SQLОбъяснение представлений SQL: создавайте, используйте и избегайте ловушек, с примерами
Представления SQL, объясненные с помощью запросов, которые мы выполняли: создание представления, результаты в реальном времени, скрытие столбцов, пр…
Читать статью →Разработка ПОИнтерфейс TypeScript и тип: реальные различия, протестированные с помощью компилятора
Интерфейс TypeScript против типа, проверенный реальным компилятором: что могут делать оба, что может делать только один, слияние объявлений, расшире…
Читать статью →Разработка ПООбъяснение Python *args и **kwargs: гибкие функции с понятными примерами
Python *args и **kwargs, объясненные с помощью кода, который мы запускали: упаковка и распаковка, порядок параметров, аргументы только по ключевым с…
Читать статью →Разработка ПОЛямбда-функции Python: синтаксис, реальное использование и когда их не следует использовать
Лямбда-функции Python, объясненные с помощью кода, который мы запускали: синтаксис, сортировка с помощью ключа, карты и фильтра, замыкания, ловушка …
Читать статью →Искусственный интеллектЧто такое ИИ-агенты? Как они работают: можно запустить простой цикл агента
Что такое агенты ИИ? Простое руководство по циклу агента, инструментам, памяти и ограничениям, с небольшим циклом Python, который мы запустили, реал…
Читать статью →DevOpsМониторинг и наблюдаемость: реальная разница с журналами, метриками и трассировками
Объяснение мониторинга и наблюдаемости: известные и неизвестные сбои, журналы, метрики и трассировки, пошаговое руководство по инцидентам при оформл…
Читать статью →DevOpsDocker Volumes против Bind Mounts: правильное сохранение данных контейнера
Объяснение томов Docker и монтирования привязки: почему исчезают данные контейнера, именованные тома, монтирование привязки, tmpfs, примеры создания…
Читать статью →Автоматизация тестированияTDD против BDD: ключевые различия, одна функция, созданная для обоих способов, и когда использовать каждый
TDD и BDD объясняются с помощью одной функции скидки, созданной в обоих направлениях: красно-зеленый рефакторинг с кодом, который мы запускали, сцен…
Читать статью →Тестирование ПОПользовательское приемочное тестирование (UAT): процесс, контрольный список и реальные примеры
Приемочное тестирование пользователей объяснило: кто его проводит, чем оно отличается от контроля качества, семиэтапный процесс, шаблон тестового сц…
Читать статью →Базы данных и SQLОбъяснение значений NULL в SQL: IS NULL, COALESCE, NULLIF и ловушки, которых следует избегать
Значения SQL NULL объяснены с помощью запросов, которые мы выполнили: трехзначная логика, IS NULL, COALESCE, NULLIF, как агрегаты, соединения и сорт…
Читать статью →Базы данных и SQLОператор SQL CASE WHEN: синтаксис, реальные примеры и распространенные ошибки
SQL CASE WHEN объяснен с помощью запросов, которые мы выполняли: простые формы и формы для поиска, порядок условий, повороты с помощью SUM, трюки CO…
Читать статью →Разработка ПОЧто такое JWT? Веб-токены JSON, объясненные на рабочем примере
Что такое JWT? Объяснение JSON Web Tokens: три части: токен, созданный и измененный в коде, который мы запускали, JWT и сеансы, хранилище, токены об…
Читать статью →Разработка ПООбъяснение цикла событий JavaScript: стек вызовов, микрозадачи и таймеры с примерами
Цикл событий JavaScript объясняется с помощью кода, который мы запускали: стек вызовов, очереди задач и микрозадач, почему setTimeout 0 не является …
Читать статью →Разработка ПОГенераторы Python и объяснение доходности: экономьте память с помощью реальных примеров
Генераторы Python и доходность, объясненные с помощью кода, который мы запускали: как они приостанавливаются и возобновляются, измеряют экономию пам…
Читать статью →Искусственный интеллектЧто такое вложения? Простое объяснение векторов и косинусного сходства
Что такое вложения? Простое руководство по векторам, косинусному подобию и семантическому поиску с небольшим примером, который мы использовали, общи…
Читать статью →DevOpsСине-зеленое и канареечное развертывание: различия, компромиссы и как выбрать
Объяснение сине-зеленого и канареечного развертывания: как каждый из них работает, стоимость, риски и откат, стабильное группирование пользователей,…
Читать статью →Автоматизация тестированияНенадежные тесты: что их вызывает и как их исправить навсегда
Ненадежные тесты объясняются на демонстрациях, которые мы запускали: основные причины, способы подтверждения и диагностики, правильные исправления в…
Читать статью →Тестирование ПОНагрузочное тестирование и стресс-тестирование: различия, метрики и примеры k6
Объяснение нагрузочного и стресс-тестирования: что доказывает каждое из них, тесты на всплески и выдержки, важные метрики, почему средние значения в…
Читать статью →Тестирование ПОТестовый пример и тестовый сценарий: ключевые различия, примеры и когда использовать каждый
Объяснение тестового случая и тестового сценария: четкие определения, параллельная таблица, одна функция сброса пароля, взятая из сценариев в случаи…
Читать статью →Базы данных и SQLОптимизация SQL-запросов: чтение планов выполнения и исправление медленных запросов с указанием времени
Оптимизация SQL-запросов проверена на миллионе строк: читайте планы выполнения, добавляйте правильные индексы, исправляйте неразмещаемые фильтры, ис…
Читать статью →Базы данных и SQLSQL UNION против UNION ALL: различия, примеры и проверка производительности
SQL UNION и UNION ALL объяснены с помощью запросов, которые мы выполнили: дубликаты, правила, которым следуют оба, реальная ошибка данных, измеренна…
Читать статью →Разработка ПОУчебное пособие по API JavaScript Fetch: GET, POST, обработка ошибок и тайм-ауты
Учебное пособие по API JavaScript Fetch, протестированное на локальном сервере: GET и POST, почему не выдается ошибка 404, многоразовый помощник, ст…
Читать статью →Разработка ПООбработка файлов Python: чтение, запись, CSV, JSON и pathlib с примерами
Обработка файлов Python объясняется с помощью кода, который мы запускали: открытые режимы, чтение больших файлов, CSV, JSON, pathlib, двоичные файлы…
Читать статью →Разработка ПОКлассы и объекты Python: учебник ООП с реальными примерами
Классы и объекты Python, объясненные с помощью кода, который мы запускали: __init__, методы, атрибуты класса и экземпляра, наследование, свойства, м…
Читать статью →Искусственный интеллектЧто такое большая языковая модель? Как работают LLM, объяснено без шумихи
Что такое большая языковая модель? LLM объясняется простым языком: токены, встраивания, внимание, обучение, температурные и контекстные окна, крошеч…
Читать статью →DevOpsКоманды Linux для начинающих: основное руководство по терминалу с примерами
Команды Linux для начинающих, сгруппированные по задачам: навигация, файлы, просмотр журналов, grep, каналы, разрешения, процессы и архивы, с практи…
Читать статью →Автоматизация тестированияSelenium vs Playwright: ключевые различия, сравнение кода и что выбрать
Сравнение Selenium и Playwright: архитектура, ожидание, поддержка браузера и языка, отладка, одинаковый тест в обоих инструментах, советы по миграци…
Читать статью →Тестирование ПОРазделение эквивалентности: метод проектирования тестов, объясненный на рабочих примерах
Объяснение эквивалентного разделения: как найти действительные и недействительные разделы, рабочие примеры для возрастов, паролей и купонов, проведе…
Читать статью →Тестирование ПОСерьезность и приоритет в тестировании программного обеспечения: различия, матрица и реальные примеры
Объяснение серьезности и приоритета при тестировании программного обеспечения: четкие определения, четырехсторонняя матрица с примерами, шкалы уровн…
Читать статью →Базы данных и SQLУчебное пособие по подзапросам SQL: типы, коррелирующие подзапросы и EXISTS с примерами
Руководство по подзапросам SQL с выполненными нами запросами: скалярные подзапросы, IN, FROM и SELECT, коррелированные подзапросы, EXISTS, ловушка N…
Читать статью →Базы данных и SQLОбъяснение транзакций SQL и ACID: COMMIT, ROLLBACK и уровни изоляции
Транзакции SQL и ACID, объясненные с помощью банковского перевода, который мы выполнили: COMMIT, ROLLBACK, точки сохранения, блокировки, уровни изол…
Читать статью →Разработка ПОGit merge vs rebase: отличия, примеры и когда что использовать
Git merge vs rebase с реальным выводом log, сравнительной таблицей, золотым правилом rebase и безопасным рабочим процессом для команды.
Читать статью →Разработка ПОГенераторы списков в Python: синтаксис, примеры и когда их избегать
Генераторы списков в Python: синтаксис, фильтры, if-else, вложенные циклы, измеренное время и случаи, когда обычный цикл for лучше.
Читать статью →Базы данных и SQLSQL JOIN: объяснение с примерами (Inner, Left, Right, Full)
Разберите SQL JOIN шаг за шагом на примерах таблиц и запросов: INNER, LEFT, RIGHT, FULL, CROSS и SELF, а также частые ошибки и советы по производите…
Читать статью →