Привет, меня зовут Денис Свиридов, я занимаюсь автоматизацией тестирования в Hoff Tech. Мы активно разрабатываем микросервисы для сети мебельных гипермаркетов Hoff и естественным образом пришли к необходимости проведения нагрузочного тестирования по ним. В таком тестировании мы видим один из обязательных шагов для улучшения качества создаваемых IT-решений.
У нас сложилась следующая ситуация. С одной стороны, в компании много аналитиков и ручных тестировщиков, которым требуется проверять свои IT-решения на прочность. Они ищут ответы на вопросы: отказоустойчив ли наш сервис платежей, не просаживается ли веб-страница корзины товаров во время распродаж из-за сервиса скидок, каков предел масштабирования текущего сервиса уведомлений клиентов?
С другой стороны, в штате совсем немного тестировщиков-автоматизаторов, которые могут разрабатывать нагрузочные тесты.
И как выйти из ситуации: нагрузочных тестов надо проводить все больше и больше, а специализированных тестировщиков-автоматизаторов неизменное количество? Наша задумка была не нова: разработать Low-code решение, чтобы сотрудники без особых знаний программирования и без привлечения автоматизаторов могли проводить нагрузочное тестирование своих сервисов. В этой статье я расскажу о том, что у нас получилось с технической и организационной точек зрения.
Техническое описание решения
Схема решения
Для запуска тестов мы выбрали CI/CD-систему Jenkins: у нее удобный визуальный интерфейс, множество плагинов, и сотрудники могут работать с ней без каких-либо навыков программирования.
Инструментом нагрузочного тестирования сделали Yandex.Tank. Наши разработчики уже имели с ним дело, поэтому решили не множить видовое разнообразие сервисов.
Использование Low-code решения без программирования
Первый вариант использования прост – с помощью Excel и json. В Yandex.Tank при такой схеме используется генератор нагрузки (пушка) Phantom. Для запуска аналитик или тестировщик формирует:
конфигурационный yaml-файл;
Excel с данными;
шаблонный json-файл.
Так выглядит пример конфигурационного yaml-файла:
host: api.test.ru:443
endpoints:
- title: 1 json
endpoint: /v1/item/bonus
json_file: bonus1.json
- title: 2 json
endpoint: /v1/item/bonus
json_file: bonus2.json
method: POST
ssl: True
timeout: 1000
ammount_rps: $AMMOUNT_RPS|30
load_type: $LOAD_TYPE|rps
rps_type: $RPS_TYPE|const(1, 10s)
instances: $INSTANCES|5
Написанное на Python Low-code решение запускается как Jenkins-джоб. Он считывает параметры из конфигурационного yaml-файла, и на основании таблицы Excel по шаблону из параметра json_file формируется список json’ов для каждого эндпоинта из параметра endpoint. Список json’ов складывается в один текстовый файл (патрон).
В подготовленном Excel-файле для некоторых типов данных допускается указывать не фиксированные значения, а генерировать произвольные, используя специальные ключевые слова. Пример можно увидеть в на рисунке в строках 5–8.
После этого Jenkins-джоб конфигурирует Yandex.Tank, подкладывает ему сформированный файл-патрон и запускает нагрузочное тестирование. Результаты тестирования публикуются в сервисе Overload.yandex.net.
Использование Low-code решения с минимальными навыками программирования
Второй вариант использования немного сложнее – через написание сценариев на Python. В Yandex.Tank для этого используется другой генератор нагрузки (пушка) — BFG. Чтобы не-разработчику было проще написать такой скрипт, автотестеры могут подсказать примеры кода на Python, подходящие под задачу.
Пример конфигурационного yaml-файла для такого варианта:
engine: bfg
host: api.test.ru
instances: $INSTANCES|5
bfg_loop: $LOOP|10
class_name: LoadTestingScenario
module_name: scenarios_service
load_type: $LOAD_TYPE|rps
rps_type: $RPS_TYPE|const(10, 10s)
Jenkins-джоб через наше решение запускает Yandex.Tank, передавая Python-скрипт, указанный в параметре module_name с указанием класса class_name как точки запуска. Далее Yandex.Tank выполняет сценарий нагрузочного тестирования, прописанный в классе class_name. Результаты тестирования публикуются в сервисе Overload.yandex.net.
Настройка джоба Jenkins
Предварительно был подготовлен эталонный Jenkins-джоб. Любой, кто хочет создать свой нагрузочный тест, копирует эталонный джоб и заполняет пару полей.
При создании джоба необходимо заполнить поля SERVICE_FOLDER (сетевой путь до Python-скриптов или Excel-файлов) и SERVICE_NAME (здесь указывается конфигурационный yaml-файл со всей информацией для запуска нагрузочного теста).
Настройкой графика запуска и самим запуском джоба занимается другой человек — ответственный автоматизатор-тестировщик, а не автор теста. Я расскажу об этом позже. Это краткое техническое описание решения. Код Low-code решения можно найти в нашем GitHub.
Теперь про процесс со стороны организации взаимодействия людей.
Организация процесса нагрузочного тестирования
Просто создать техническое решение и пустить его в народ без правильной организации процесса вокруг него — значит гарантировать себе беспорядок. Беспорядок в Jenkins, дублирование работы по написанию нагрузочных тестов, слабое документирование и непрозрачность самого процесса нагрузочного тестирования.
Все это означает, что мы не добьемся желаемого постоянства по обеспечению качества IT-решений. А главное, можно подставить под удар рабочие и тестовые контуры IT-систем, которые падут под «пулями» нагрузочных тестов от новоиспеченных автоматизаторов. Поэтому мы регламентировали правила игры и требуем придерживаться их.
Описание задачи в Jira
Под каждый нагрузочный автотест создается новая задача в Jira, которая станет документацией по нему. В задаче автор описывает:
тест-кейс, на котором будет выполняться нагрузочное тестирование;
профиль нагрузки;
модель нагрузки.
Заполнить задачу надо определенным образом:
Поле | Правило |
Проект | Указывается Jira-проект, в рамках которого создается нагрузочный тест. Это же определяет, за чей счет выполняется разработка нагрузочного теста |
Тип задачи | Тест-кейс |
Тема | Название нагрузочного сценария |
Метки | "нагрузочное_тестирование" |
Компонент | Компонент проставляется обязательно, например, мы ставим AutoTest, LoadTest. Отбирая по компоненту, мы можем составить полный список всех задач на создание и доработку авто- и нагрузочных тестов |
Описание | Описывается подробно профиль нагрузочного тестирования сервиса |
Вложения | Шаблоны Json, Excel-файлы, Python-скрипты |
Шаги тест-кейса | В шагах тест-кейса прописываются проанализированные и сформированные модели нагрузочного тестирования. |
Профиль нагрузки – это определенный набор операций с заданными интенсивностями.
Определить профиль нагрузки значит выяснить и зафиксировать, как работают пользователи IT-решения. Если система только планируется к вводу в эксплуатацию, профиль нагрузки моделируется. Если система уже работает, то профиль формируется исходя из анализа текущих данных.
Модель нагрузки – модель, описывающая нагрузку, длительность и другие параметры, с которыми будет проводиться тестирование.
Например: количество пользователей и интенсивность запросов, варианты параллельной работы пользователей (последовательно, ступенчато группами, запуск всех сразу), длительность работы сценария.
Организация Jenkins-пространства
Под разные функциональные области и поддомены, покрываемые нагрузочным тестированием, мы создали отдельные папки в пространстве Jenkins. Это упорядочивает хранение нагрузочных тестов, которых с каждым месяцем становится всё больше.
Настройка Jenkins-джоба под нагрузочный тест
После описания тест-кейса в Jira автор, составивший нагрузочный тест, выбирает один из вариантов реализации на базе нашего Low-code решения: упрощенный без программирования или посложнее, с Python-скриптом.
Далее составляется Excel-файл либо Python-скрипт, а к ним — конфигурационный yaml-файл.
Jenkins-джоб создается путем клонирования из уже готового джоба с последующей донастройкой под конкретный нагрузочный тест-кейс. Папку, где надо разместить джоб, укажут автоматизаторы-тестировщики, которые администрируют Jenkins и следят за порядком в нем.
Наше Low-code решение снижает порог вхождения в мир тестирования, а значит автор, возможно, не сможет предсказать последствия тестирования для IT-инфраструктуры. Поэтому до запуска нагрузочного теста ответственный тестировщик-автоматизатор проводит ревью модели нагрузки, которую заказали. Это важный этап процесса, которым мы стараемся защитить тестируемые IT-системы от «аппетитов» автора нагрузочного теста.
Также мы разграничили права доступа на настройку запуска Jenkins-джобов. Пользователи в роли QA могут создать Jenkins-джоб, но не могут настроить расписание его выполнения. Право запуска отдается ролям admin и developer. Эти разграничения мы сделали через плагин Role-based Authorization Strategy.
Запуск нагрузочного теста
Перед запуском настроенного нагрузочного теста необходимо выполнить еще несколько условий:
первый запуск с новыми параметрами модели нагрузки должен проходить только на тестовом или предрелизном контуре, даже если согласовали провести нагрузочное тестирование на рабочем контуре. Это минимизирует потенциальный вред для рабочей ИТ-системы в случае возникновения ошибок или проблем;
перед запуском автор нагрузочного теста должен предупредить коллег отдела тестирования и DevOps-инженеров. Это позволит им подготовиться к возможным непредвиденным ситуациям и быстро отреагировать на них в случае необходимости.
Эти условия важны для обеспечения безопасности и качества процесса тестирования, а еще для минимизации возможных рисков.
В финале Jenkins-джоб выполняется, а данные с результатами сохраняются в Overload.yandex.net.
Анализ результатов нагрузочного тестирования
После тестирования проводится анализ результатов в сервисе Overload.yandex.net, а сотрудник заполняет карточку результатов по каждому эндпоинту сервиса. Результаты нагрузочного тестирования фиксируются в таблицы, из которых команда понимает, что заявленный уровень качества IT-решения с точки зрения производительности и устойчивости достигнут.
Результаты теста, подтверждающие достижение требуемых показателей:
План | Факт | ||
RPS, количество запросов в секунду | 100 | 100 | |
Длительность теста | - | 10 минут | |
Процент успешных ответов | - | 100% | |
Кол-во ответов с ошибкой | - | 0 | |
TTFB* | Среднее | 100мс | 100мс |
Минимальное | - | 86мс | |
Максимальное | - | 122мс |
* TTFB – time-to-first-byte — время между запросом к сервису и временем начала получения ответа от него
Результаты теста, иллюстрирующие предельно допустимую нагрузку:
Результаты теста стабильности:
Ревизия списка Jenkins-джобов
Jenkins-джобы, выполняющие нагрузочное тестирование, генерируют огромные массивы информации. Поэтому раз в квартал ответственный тестировщик-автоматизатор проводит ревизию созданных джобов, очистку логов их выполнения. Неиспользуемые джобы убираются из Jenkins, но информация о них остается в Jira, чтобы ее было просто найти и воссоздать нагрузочный тест при необходимости.
Такой организационный минимум был внедрен у нас, чтобы работа по нагрузочному тестированию была прозрачна и упорядочена.
Заключение
Теперь ручные тестировщики и аналитики с минимальными навыками программирования или вообще без них стали самостоятельно готовить нагрузочные тесты.
Это увеличило скорость работы, больше не выстраивается очередь задач для автоматизаторов тестирования, стало меньше узких мест в процессе поставки IT-решений и меньше конфликтов за ресурсы.
В итоге мы расширили рабочий инструментарий проектных команд, чтобы они выпускали устойчивые и надежные IT-системы без значительных затрат.