Блог a1qa

О тестировании и качестве ПО

Поведенческий метод в тестировании производительности

Сегодня мы сравним два метода тестирования производительности ПО и рассмотрим по шагам, как проводится наиболее эффективный из них.

Тестирование производительности охватывает широкий спектр целей и способов их достижения. Чаще всего необходимо проверить, какую нагрузку может выдержать система в определенных условиях. Для этого используют один из двух методов:

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

Метод с использованием онлайн-сервисов более простой в реализации, но имеет ряд недостатков. Запросы, создаваемые онлайн-сервисами для тестирования производительности, часто непредсказуемы по своей интенсивности.

Онлайн-сервисы не учитывают некоторые особенности поведения реальных пользователей, например, корректность передачи динамических параметров, эмуляцию кэширования данных браузером и правильные временные задержки между действиями виртуальных пользователей.

Нагрузка, генерируемая подобными сервисами, больше напоминает DDoS-атаку, чем эффективный нагрузочный тест. Быстрое и нереалистичное тестирование зачастую оказывается бесполезным и даже контрпродуктивным, поскольку результаты производительности системы, полученные в таких условиях, могут быть ненадежны и ошибочны. А это влечет за собой риск потери репутации и финансовые расходы.

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

Однако для того чтобы получить эффект, соответствующий фактической производительности системы, необходимо очень точно воспроизвести работу пользователей. Но как достичь максимальной реалистичности нагрузки? С помощью виртуальных пользователей.

Виртуальный пользователь — скрипт, который выполняет запросы к приложению, эмулируя работу реального пользователя.

Высокая степень реалистичности достигается за счет того, что генерируемый поток запросов по своим характеристикам приближен к запросам, наблюдаемым в условиях эксплуатации приложения, а виртуальные пользователи взаимодействуют с системой в поведенческой манере.

6 правил подачи нагрузки на систему поведенческим методом:

  1. создаем сценарии поведения пользователей;
  2. определяем профиль нагрузки;
  3. разрабатываем и настраиваем нагрузочные скрипты;
  4. генерируем набор реалистичных тестовых данных;
  5. выбираем, как подавать нагрузку;
  6. организовываем распределенное тестирование.

Рассмотрим их подробнее.

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

Перед тем как приступить к разработке нагрузочных скриптов инженер по тестированию производительности составляет максимально объективные шаблоны поведения виртуальных пользователей. Для этого ему необходимо узнать:

  • общее количество пользователей, взаимодействующих с приложением (среднее количество в час, сутки, месяц);
  • какая часть пользователей использует приложение во время наибольшей его загруженности;
  • что конкретно делают эти пользователи на сайте и как часто;
  • каким образом между пользователями распределяются существующие в системе роли.

Ответы на эти вопросы для вышедшего на рынок приложения дает статистика из инструментов веб-аналитики, таких как Google Analytics, Яндекс.Метрика, Adobe Analytics и так далее. Инженер анализирует частоту выполнения операций и создаваемую нагрузку на сайт, выделяет ключевые бизнес-операции и составляет сценарии поведения пользователей, в соответствии с которыми далее он разрабатывает нагрузочные скрипты.

Скриншот из Google Analytics - статистика поведения пользователей на сайте

Источник изображения: marketingplatform.google.com

В случае если приложение находится в предрелизной стадии, тестовые сценарии составляются таким образом, чтобы охватить важнейшие бизнес-процессы и основные функциональные модули системы. В таком случае нужную информацию инженер получает у бизнес-аналитика проекта или напрямую у заказчика. Кроме того, в сценарии могут быть включены редкие, но тяжелые с точки зрения работы системы запросы, на которые может указать команда разработки. Например, запросы, обрабатывающие информацию из большого количества таблиц базы данных и тем самым загружающие систему.

Помимо определения последовательности действий реальных пользователей, инженер по тестированию производительности изучает статистическое распределение временных задержек между действиями или время ожидания (Think Time).

Think Time — промежуток, когда пользователь не совершает действий, а находится в процессе их выполнения или раздумывает над следующим шагом: вводит пароль, выбирает товары, читает текст, пишет комментарий и т. д. К примеру, временная задержка при операции авторизации может составить 10 секунд, а при навигации по меню веб-сайта или использовании поиска – 5 секунд. Подобные задержки обязательно должны учитываться при разработке скриптов.

Ниже приведен пример тестового сценария, составленного для интернет-магазина. В скобках указано время ожидания.

Сценарий «Зарегистрированный пользователь: оплата заказа»

  1. Пользователь открывает домашнюю страницу (5-10 сек.)
  2. Пользователь нажимает «Вход для зарегистрированных пользователей» (5-10 сек.)
  3. Заполняет форму входа, нажимает «Войти» (10-60 сек.)
  4. Выбирает произвольный товар и нажимает «Добавить в заказ» (30-60 сек.)
  5. Нажимает «Продолжить оформление заказа» (10-20 сек.)
  6. Шаги 4-5 повторяет случайное количество раз (от 1 до 5)
  7. Нажимает «Утвердить заказ» (10-20 сек.)
  8. Нажимает «Перейти к оплате» (10-20 сек.)
  9. Заполняет форму оплаты и нажимает «Оплатить» (10-20 сек.)
  10. Нажимает «Подтвердить оплату» (10-20 сек.)

Обычно для ПО среднего объема разрабатывается от 3 до 10 сценариев, каждый из которых содержит до 10 шагов-действий пользователей, в зависимости от размеров тестируемого приложения.

Многофункциональные приложения со сложной логикой требуют большего количества сценариев. Например, для тестирования портала по обслуживанию производственных сооружений, включающего в себя назначение ремонтных работ, создание сертификатов, нарядов допусков и многое другое, инженерами a1qa было подготовлено более 20 тестовых сценариев, а количество шагов варьировалось от 15 до 20.

Заказать бесплатную консультацию специалиста по тестированию производительности.

2. Определение профиля нагрузки

По мере подготовки тестовых сценариев разрабатывается профиль нагрузки (Load Profile), отражающий процентное распределение совершаемых в системе операций между пользователями разных ролей.

Процентное распределение совершаемых в системе операций между пользователями разных ролей

При составлении профиля нагрузки учитывается статистика посещения целевых страниц приложения реальными пользователями. Не каждый пользователь, который добавляет товар в корзину, совершает покупку, часть пользователей закрывает приложение так и не оформив заказ. Получается, что каждое действие имеет предварительно заданную вероятность и выполняется только некоторым количеством пользователей. Например, во время тестирования интернет-магазина между сценариями соблюдалось следующее соотношение:

Таблица - соотношение количества виртуальных пользователей по различным сценариям поведения на сайте.

Таким образом, при подаче нагрузки в 1 000 виртуальных пользователей, 700 из них будут выполнять Сценарий 1, 200 – Сценарий 2 и 100 – Сценарий 3.

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

3. Разработка и отладка нагрузочных скриптов

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

Как правило, разработка начинается с записи процесса обмена данными между сервером и браузером пользователя на уровне различных протоколов передачи данных. Инструменты тестирования позволяют впоследствии воспроизвести этот процесс в несколько потоков, чтобы сгенерировать необходимый уровень нагрузки на систему.

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

Инструменты нагрузочного тестирования позволяют добиться уникальности и параметризировать данные в самом запросе: его заголовке, файлах cookie, параметрах в теле запроса.  Параметризация производится с помощью набора встроенных функций нагрузочных инструментов, однако в особо сложных случаях может возникнуть необходимость прибегнуть к написанию кода. Исключительность действий виртуальных пользователей также достигается использованием функций, выполняющих циклы, разветвления и рандомизацию значений.

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

Структура и размер запросов/ответов от сервера должны быть строго идентичны. Также ключевые ответы сервера часто необходимо проверять на корректность выполнения, поскольку современные системы при возникновении ошибки могут ответить пользователю не кодом состояния HTTP-запроса, а особым сообщением об ошибке. В таком случае при помощи инструмента нагрузочного тестирования можно задавать критерии для проверки ответов сервера.

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

Нагрузочное тестирование - работа реального и виртуального пользователей неразличима

На финальном этапе отладки скриптов проводится серия предварительных тестов с небольшим уровнем нагрузки, чтобы убедиться в корректности отработки скриптов для нескольких учетных записей пользователей: проверяется передача динамических параметров и коды ошибок HTTP, сверяется структура запросов и ответов.

Предварительные тесты также позволяют выбрать оптимальную схему подачи нагрузки (Load Pattern), например, +1 виртуальный пользователь каждые 3 секунды.

Перечисленные шаги часто упускаются из виду, что приводит к возникновению ошибок в работе нагрузочных скриптов на этапе запуска финальных тестов и потере времени на поиск и устранение их дефектов.

Получите бесплатную консультацию специалиста по тестированию производительности a1qa.

4. Генерация реалистичного набора тестовых данных

Перед запуском финальных нагрузочных тестов важно заранее сгенерировать необходимые тестовые данные в количестве, необходимом для корректной отработки скриптов, ведь при эмуляции тысячи виртуальных пользователей, использующих одну и ту же учетную запись, запросы будут кэшироваться на стороне сервера.

Также возможны проблемы, связанные с конфликтом виртуальных пользователей, выполняющих одинаковые действия.

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

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

В общем виде тестовые данные можно разделить на три типа:

  • Учетные записи пользователей разных ролей

Особое внимание здесь уделяется уникальности имен виртуальных пользователей и их паролям, отвечающим установленным критериям надежности. Для удобства и легкой идентификации в базе данных системы имена пользователей создаются по определенным шаблонам.

Иногда стоит задача генерации пользователей различных размеров: «легких» и «тяжелых». «Тяжелый» пользователь обладает большим количеством записей в базе данных системы и взаимосвязей между ними. Для «легкого» пользователя характерно ограниченное количество записей. Например, в ходе тестирования производительности биллинговой системы результаты производительности на «тяжелых» пользователях с большим количеством абонентов оказались в десятки раз хуже результатов, полученных в тех же условиях, но для «легких» пользователей.

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

  • Файлы для импорта различного размера и типа

Помимо учетных записей пользователей, необходимо добавить и данные, с которыми они работают. В некоторых случаях нужно не просто измерить количество времени, за которое сервер обработает запросы веб-страниц, а оценить скорость загрузки файлов – этот показатель может иметь важнейшее значение, например, для корпоративных систем.

Тестовые данные приводятся к формату, соответствующему конкретному документу для загрузки, и могут иметь такие характеристики, как тип (MS Word, Excel, PDF, jpeg), размер и содержание. Генерация файлов может осуществляться в командной строке с помощью команды Fsutil либо с использованием набора PowerShell-команд.

  • Валидные данные для заполнения форм

Часто веб-страницы содержат формы для заполнения, имеющие произвольное количество полей, в которые пользователи вводят персональные данные. Сервер обрабатывает полученную информацию и сохраняет её в базу данных системы. Для того чтобы отправленные данные были успешно обработаны приложением, необходимо соблюсти условия их валидности, например, проверить соответствие вводимых номеров телефонов или банковских карт установленному формату. В противном случае можно получить сообщение об ошибке.

Для генерации валидных тестовых данных можно прибегнуть к написанию кода, циклически генерирующего значения в необходимом формате. Также можно использовать встроенные функции нагрузочных инструментов для рандомизации значений по определенному алгоритму.

После определения типов тестовых данных и способов их генерации инженер по тестированию производительности определяет количество данных, необходимых для успешного выполнения запланированных тестов, а также выбирает наиболее эффективный способ очистки базы данных системы.

5. Выбор схемы подачи нагрузки

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

Основные схемы подачи нагрузки во время тестов представлены ниже.

Схема №1 — линейное увеличение количества виртуальных пользователей без значительных интервалов.

График линейного увеличения количества виртуальных пользователей без значительных интервалов.

Схема №2 — ступенчатое увеличение количества виртуальных пользователей с интервалами, на которых отсутствует прирост пользователей.

График ступенчатого увеличения количества виртуальных пользователей с интервалами

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

График линейного увеличения количества виртуальных пользователей до определенного уровня, в дальнейшем постоянного.

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

График скачкообразного увеличения нагрузки.

Схема №5 — кастомное изменение количества виртуальных пользователей, возможна комбинация схем №1-4.

График кастомного изменения количества виртуальных пользователей.

В качестве must-have-тестов мы рекомендуем проведение стресс-теста (Stress Test) и нагрузочного теста (Load Test).

Stress-тест позволяет определить максимальный уровень производительности системы (схема нагрузки №1/2); Load-тест – убедиться в том, что производительность системы не снижается с течением времени под нагрузкой среднего уровня (схема №3).

Выбор схемы подачи нагрузки может быть обусловлен особенностями системы и требованиями к ее производительности. Например, запуск системы раздачи ограниченного количества бонусов на крупном игровом портале запланирован на определенную дату. Владельцы портала ожидают резкий наплыв пользователей и хотят удостовериться в том, что система справится с экстремальной нагрузкой. В таком случае может использоваться схема №1 с приростом 3 000 виртуальных пользователей за 10 секунд. Напротив, корпоративные системы обычно используются средним количеством пользователей, но во время всего рабочего дня. Тогда оптимальной схемой подачи нагрузки будет схема №3 в течение 8-10 часов.

В качестве еще одного примера можно привести интернет-магазины, для которых характерно резкое увеличение количества пользователей во время сезонных распродаж. На основе статистики посещения интернет-магазина в обычный период и в период высоких нагрузок можно спрогнозировать ожидаемый уровень количества пользователей в течение следующей распродажи. Требованием к производительности такой системы может быть высокая устойчивость к пиковой нагрузке, а в качестве дополнительной схемы нагрузки мы рекомендуем использовать схему №4.

Заказать консультацию специалиста.

6. Проведение распределенного тестирования из разных геолокаций

Мы рекомендуем располагать генераторы нагрузки как можно ближе к тестовому окружению. Это необходимо, для того чтобы избежать непредвиденных проблем во время запуска тестов, вызванных пропускной способностью сети, ведь величина ее задержек может варьироваться от нескольких миллисекунд до нескольких десятков секунд. Обеспечение наибольшей скорости обмена данными между клиентом и сервером, например, путем размещения генератора нагрузки в одной локальной сети с тестовым окружением, позволяет протестировать производительность приложения в условиях, приближенных к идеальным.

Однако иногда стоит обратная задача: измерить ключевые характеристики производительности приложения, эмулируя работу пользователей из отдаленных регионов. Например, протестировать крупный новостной портал игровой вселенной, который посещают пользователи со всего мира. В таком случае для того чтобы создать реалистичную нагрузку, необходимо учесть географию пользователей, информацию о которой можно получить с помощью веб-аналитических инструментов.

Для выполнения этой задачи настраивается распределенный нагрузочный тест, при котором виртуальные пользователи распределяются между несколькими генераторами нагрузки, расположенными в разных географических регионах. В качестве генераторов нагрузки при таком виде тестирования используются виртуальные машины, арендуемые на платформах облачных сервисов (Amazon WS, Microsoft Azure, Google Cloud и другие).

В ходе настройки теста создаются клиент (или Master, Test Controller) и серверы (или Slaves, Test Agents), например, в США, Европе, Бразилии и Австралии. Клиент – машина которая собирает и отображает результаты; серверы – машины, используемые в качестве обычных генераторов нагрузки. В ходе функционирования системы нагрузка подается со всех серверов одновременно.

Карта серверов Microsoft Azure и amazon web services

Результаты такого тестирования позволяют сделать выводы о производительности системы для конечных пользователей и о необходимости размещения дополнительных серверов в регионах с наихудшими показателями производительности.

Таким образом, мы рассмотрели основные правила подачи нагрузки на систему. Результаты, полученные поведенческим методом, максимально приближены к фактическому уровню производительности системы.

Бонусом такого метода тестирования является возможность обнаружения функциональных дефектов, проявляющихся только под нагрузкой. Разработка скриптов в соответствии с действиями реальных пользователей позволяет локализовать подобные дефекты.

Закажите бесплатную консультацию с экспертами a1qa и узнайте, как мы можем помочь улучшить ваш продукт.

Поделиться статьей: