Три вопроса внутри тестирования производительности API
| Нагрузочная способность | Какой объём одновременного трафика выдерживает сервис, прежде чем задержки начнут расти. Нужен генератор нагрузки. Запускайте перед релизами и после изменений архитектуры. |
| Регрессия | Стал ли вызов медленнее после этого pull request. Нужны базовые значения и сравнение с ними, а не высокая конкурентность. |
| Корректность | Правильный ли ответ, в том числе на неудобные входные данные. Нужны проверки тела ответа. Самый дешёвый из трёх — и тот, который чаще всего пропускают. |
Почему автоматизировать стоит в первую очередь регрессию
Нагрузочное тестирование дорого запускать, и между релизами его результаты меняются редко. С регрессией производительности всё наоборот: она накапливается постепенно, по одному pull request за раз, и к моменту, когда её заметит нагрузочный тест, перед вами полгода накопленных изменений и никакого понимания, какое из них виновато.
Простое сравнение времени каждого вызова с базовым значением, запускаемое на каждое изменение, поймает запрос, ставший в десять раз медленнее, в тот же день, когда он попал в код. Это ценнее квартального отчёта о нагрузочной способности.
Нижняя планка: корректность
Ни одна цифра по времени ответа ничего не значит, если ответы неверны. Эндпоинт, возвращающий пустой массив, работает предельно быстро. Звучит очевидно — и ровно так сервис уезжает в прод со сломанным фильтром и отличными графиками задержек.
Поэтому порядок такой: сначала корректность, затем регрессия, затем нагрузочная способность. Большинство команд идут в обратном порядке, потому что именно нагрузочное тестирование выглядит как работа над производительностью.
Что даёт сгенерированное покрытие
Планы тестирования API включают граничные и стресс-подобные случаи, которые вскрывают комбинации входных данных, замедляющие эндпоинт по структурным причинам, а не из-за нагрузки. Запрос, который деградирует при большом размере страницы, всплывёт здесь задолго до того, как его найдёт нагрузочный тест.
Это не нагрузочное тестирование и не замена ему. Это дешёвый слой под ним.
Терминал
npm install -g @testsprite/testsprite-cli
testsprite setup
Если вы не хотите ничего устанавливать, то же самое можно сделать в дашборде. Всё остальное, что умеет командная строка, есть в репозитории CLI.
Сессии, состояние, порядок выполнения и очистка описаны в документации по тестированию API.
Где обычно прячется регрессия
Когда эндпоинт становится медленнее от релиза к релизу, причина почти всегда одна из трёх, и знание этого заметно сокращает поиск.
Запрос, потерявший индекс или получивший условие, которое индекс не покрывает. Это с большим отрывом самый частый случай, и изменение при этом незаметно в диффе, потому что SQL выглядит нормально.
Вызов, который раньше укладывался в одно обращение, а теперь делает несколько — обычно потому, что вспомогательный метод начал доставать связанные записи по одной внутри цикла. Код при этом читается лучше, чем раньше, — так он и проходит ревью.
Что-то выросло. Ответ содержит коллекцию, в которой раньше было пять элементов, а теперь пятьсот, потому что продукт взлетел. Ничего не сломалось — и эндпоинт теперь медленный для всех.
Периодичность
Два пути, и выбор на самом деле зависит от того, кто владеет пайплайном. Подключение GitHub App из дашборда вообще не требует изменений в вашем репозитории, потому что он реагирует на деплой, который ваша сборка и так публикует. Добавление шага GitHub Actions помещает проверку в репозиторий, где её ревьюят наравне с остальной сборкой.
Что из этих трёх покрывает TestSprite
Третий вопрос, корректность, и граничные случаи, вскрывающие структурные замедления. Запрос, который деградирует при большом размере страницы, проявится как упавший или медленный граничный тест задолго до того, как до него доберётся нагрузочный тест, и обойдётся это в разы дешевле.
Покрытие строится на API Discovery и вашей спецификации, а планы охватывают функциональные проверки, схему, авторизацию, обработку ошибок и граничные случаи. Auto-Authentication поддерживает сессии живыми на протяжении всего прогона, Dynamic Variables переносят значения между вызовами, Dependency Chains выводят порядок выполнения из того, что каждому тесту нужно и что он производит, а Auto-Cleanup удаляет ровно то, что создал прогон.
В итоге вы получаете слой, которого не хватает большинству программ по производительности: то, что запускается на каждый pull request и заметит эндпоинт, возвращающий пустой результат, — сбой, который график пропускной способности покажет как отличный результат.
Измеряет ли TestSprite задержки?
Он проверяет корректность, а не нагрузочную способность. Для замеров времени и пропускной способности при длительной конкурентной нагрузке нужен отдельный инструмент производительности.
Что считать разумным базовым значением?
Ваши собственные прошлые показатели в той же среде. Абсолютные целевые значения, заимствованные у других продуктов, говорят очень мало.
Должны ли тесты производительности блокировать мерж?
Большая регрессия на критическом пути — да. Небольшой разброс — нет, иначе вы будете тратить время на подгонку порогов вместо выпуска релизов.
Почему наши цифры так скачут?
Обычно дело в общей среде, холодном кэше или разном объёме данных. Возьмите это под контроль, прежде чем доверять любому сравнению.
Может ли один инструмент закрыть все три задачи?
Некоторые заявляют, что могут. На практике для вопроса о нагрузочной способности нужен генератор нагрузки, а для вопроса о корректности — проверки тела ответа, и хорошо совмещать это в одном прогоне удаётся реже, чем обещает маркетинг.
Сначала корректность, затем регрессия, затем нагрузочная способность.
Тестирование производительности API — это три вопроса с тремя ответами. Регрессию стоит автоматизировать на каждом изменении, корректность — фундамент под всем этим, а нагрузочная способность — самая дорогая часть, с которой большинство команд и начинает.