JMeter как инструмент для автоматизации функционального тестирования |
04.07.2023 14:05 |
Авторы: Алексей Чичук, Владислав Литвинов, Анастасия Стрижеченко Привет, мы Алексей Чичук, Анастасия Стрижеченко и Владислав Литвинов — тестировщики из банка Точка. И сегодня мы расскажем, как и почему мы используем JMeter для функционального тестирования. Предыстория Конечно же, в Точке огромное количество сервисов, каждый из которых совершенствуется и «обрастает» новыми фичами. Всё это невозможно протестировать руками, а обучать тестировщиков автоматизации на каком-либо языке программирования — долго, дорого, а местами и вовсе неэффективно. Поэтому мы начали искать инструмент автоматизации, который:
Мы начали экспериментировать с JMeter, и он себя хорошо показал: множество плагинов и огромное поле возможностей позволяли решать любые задачи автоматизации. Low-code-решение сделало вход намного легче и приятнее, чем изучать языки программирования с нуля, поднимать окружение и инфраструктуру для тестов. Время шло, мы становились опытнее, и этот инструмент плавно перешёл для нас из категории «удобный» в «незаменимый». Что сейчасВ Точке нет строгих правил по выбору инструментов для тестирования, поэтому каждая команда может сама решать, какой использовать в работе. Сейчас 15% всех тестировщиков Точки пишут автотесты на Jmeter, хотя на старте им пользовалась только одна команда. На данный момент с его помощью написано более 6 тыс. автотестов. Также мы разработали внутренний курс по обучению автоматизации на Jmeter. Так тестировщик сможет быстро освоить этот инструмент и сократить ручное тестирование в своей команде. Почему не другие инструменты?Изначально у нас были определённые требования к инструменту, от которых мы и отталкивались. Если сравнить, что умеет каждый из них, то увидим следующую картину: В Точке используется единая TMS, которая принимает отчёты в формате Allure. Из таблицы видно, что ни один из рассмотренных low-code инструментов не имеет необходимого нам формата отчёта (причём у каждого инструмента вообще своя реализация). Полагаем, что здесь знатоки Postman и Newman нам возразят, отметив, что такая связка умеет работать с Allure. Это, конечно, так, но реализация «один запрос — один тест в отчёте» — это совсем не то, что применимо в реальной практике тестирования. Помимо проблем с отчётами, у того же Postman имеются проблемы с походом в базы данных. Конечно, есть сервисы по типу PostgREST и ему подобные, которые предоставляют интерфейс общения с базой по REST, но нам такое не нравится: плодить ради такого действия дополнительные сервисы — перебор. К тому же, это дополнительная точка отказа, которую иметь не хочется. Закрыв глаза на проблемы с отчётностью, которые есть у всех рассматриваемых инструментов, мы выявили для себя лидера — это JMeter. Самый большой плюс этого инструмента для нас кроется в пункте «Возможность подпилить напильником», поскольку именно благодаря этому в пункте «Нормальный отчёт по прогону» можно сменить красный кружок на зелёный. Что мы, собственно, и сделали. По итогу с выбором JMeter мы ни капли не ошиблись. JMeter умеет многое. С его помощью вы сможете:
Как написать тест на JMeterHTTP Request, headers, assertionsДля общего понимания, немного пройдёмся по двум определениям:
Перейдём к практической части и напишем простой тест. В качестве тестируемого сервиса возьмём форк известного приложения на Spring Boot — Spring Petclinic. Его особенность в том, что это серверная версия приложения и предоставляет только REST API. К тому же имеется база данных, а пользовательского интерфейса нет. Это нам подходит, так как в Точке много бэкенд-микросервисов, не имеющих UI. Фундаментальным элементом для тестирования API является HTTP Request. Он позволяет отправлять HTTP-запросы к вашему API-серверу и получать ответы в формате JSON или XML. Создадим запрос на получение списка всех хозяев домашних животных. Выглядит достаточно просто, собственно, как и в любых других приложениях, позволяющих отправлять HTTP-запросы. Вам необходимо знать базовый URL, порт и путь. Заголовок Content-Type: application/json можем прописать, добавив элемент HTTP Header Manager. Важная особенность — от того, где расположен этот элемент, зависит область действия. Если находится в корне Thread Group, то применятся ко всем HTTP Request. Если внутри конкретного HTTP Request — действует только для него. Из коробки JMeter отображает JSON в одну строку — это неудобно. Поэтому подключаем плагин jp@gc — JSON Format Post Processor. Предварительно добавив элемент View Results Tree в наш Test Plan и выполнив HTTP-запрос, мы увидим результат. Какой же тест без проверки? Например, мы хотим проверить, что в полученном списке у хозяина по имени Peter есть змея по кличке George. Так как в ответ нам приходит JSON, то логично для проверки использовать JSON Assertion. Этот элемент использует JSON Path. С его помощью мы можем делать совершенно любые проверки в JSON. Получилось вот такое jsonpath-выражение: JSONPath — это язык запросов для JSON, который позволяет обращаться к любому из элементов JSON. Хороший навык для написания тестов, позволяющий указывать пути до элементов для явных проверок. Специально сделаем опечатку в ожидаемом значении, чтобы убедиться в правильности проверки. Результат запуска покажет несоответствие ожидаемого и фактического результата. Отлично! Первый тест готов. Далее мы сделаем так, чтобы тест был атомарным и мог быть зелёным сколько угодно раз, вне зависимости от данных. Базы данных, переменныеМожет произойти такое, что Peter с его питомцем больше нет в нашей базе данных. Логично, что наш тест сразу начнёт падать. Чтобы сделать тест независимым от данных, нужно добавлять данные перед тестом и очищать их после теста. Таким образом, тест всегда будет проходить вне зависимости от изменений в базе данных. Здесь есть два пути:
Рассмотрим оба случая. В первом варианте с использованием API: добавляем HTTP Request с добавлением хозяина перед нашей основной проверкой. Также добавим проверки: код ответа 201, firstName в ответе совпадает с тем, что мы указали в запросе. Добавим Response Assertion, чтобы проверить код ответа. И уже известный нам JSON Assertion для проверки значения в возвращаемом JSON. В ответ запрос возвращает Значение Аналогичным образом добавляем питомца к тестовому хозяину. Исправляем нашу проверку на наличие добавленного хозяина в списке и проверяем, что появился тестовый хозяин, у которого змею зовут George. После этой проверки добавляем два шага по удалению данных: удаляем питомца и самого хозяина. У нас получился атомарный тест, который не зависит от наличия данных в базе или от другого теста, и может запускаться сколько угодно раз:
Теперь рассмотрим второй вариант с использованием базы данных. Подключиться к базе данных из JMeter можно через элемент JDBC Connection Configuration. Настроим подключение для нашей базы — используем postgresql. Необходимо задать нужные значения для подключения. Из особенностей только то, что необходимо придумать название для создаваемого пула соединений — например, PETCLINIC. Выполнить запрос в базу данных позволяет элемент JDBC Request. Добавим его и напишем insert на добавление хозяина и его питомца. Указываем наш пул соединений — PETCLINIC. Запрос в базу данных получился такой:
Обратите внимание, что при добавлении записи в базу, мы сразу же возвращаем значения Важно отметить: так как мы возвращаем значение Точно таким же образом делаем добавление питомца, а после самой проверки — удаление этих же данных из базы по имеющихся у нас Довольно простыми действиями мы смогли написать полноценный тест, к тому же используя разные подходы. Познали мощь переменных для цепочек запросов и научились ходить в базу данных из Jmeter. ПроцессорыПеред использованием ранее полученных данных иногда их нужно обработать. Процессор выполняет какое-то действие около семплера. В Jmeter есть два типа процессоров: Pre-processor — выполняет действие до работы семплера; Post-processor — после. Процессоров достаточно много, все они разные и используются в функциональном тестировании не всегда. Про часть из них уже было написано выше — JSON Extractor после запроса может сохранить переменную по jsonpath, Format Post Processor форматирует Response JSON в читаемый вид после выполнения семплера. Взглянем какие ещё процессоры можно использовать. Regular Expression Extractor — используется для извлечения части переменной для дальнейшего использования. Например, мы получили в ответе ссылку в формате Если вы не смогли что-то сделать стандартными инструментами Jmeter, то на помощь придёт JSR223 Post-processor. В данном процессоре можно выполнять код на разных языках (java/groovy/javascript и т.д.). Кажется чем-то сложным, но всегда есть возможность загуглить и взять ту или иную реализацию. КонтроллерыКонтроллеры применяются для того, чтобы делать ветвления и циклы. Расскажем про контроллеры, которые мы используем в своей работе чаще всего. Simple Controller — контроллер, который ничего не делает, кроме хранения данных. Мы его используем как папку для удобства хранения тестов, чтобы в них была красивая понятная структура. Также для структурирования тестов можно использовать Transaction Controller, в этом случае при запуске семплеры будут складываться в отдельное дерево в View Results Tree. If Controller используется, если нужно добавить условие для выполнения шага. Не стоит увлекаться с данным контроллером и использовать его для реализации бизнес-логики в тестах, лучше делать явные отдельные тесты на разные условия. Например, при написании теста «Стоимость подписки в зависимости от тарифа» не стоит проверять If-ом тариф на X/Y. Тест должен выглядеть как:
А не:
А теперь к более приближённым примерам: если первый запрос не вернул ошибку, то нужно отправить второй. Для этого в первый запрос добавляем JSON Extractor с дефолтным значением, например — NOT_FOUND. Если мы не получим ошибку на первый запрос, то переменная error_code будет равна NOT_FOUND. После первого запроса вставляем If Controller c выключенным флагом Interpret Condition as Variable Expression ? и добавляем условие:
В If Controller вкладываем второй запрос, который будет отправлен после выполнения условия. While Controller применяется для многократного повторения запроса, пока не выполнится определённое условие (вернётся нужный ответ). Например, если нужно отправлять запрос, пока не вернётся значение success_status равное true: Также While Controller можно использовать, если нужно перебрать список значений и для каждого выполнить одинаковый запрос. Реализация цикла while в языках программирования выглядит примерно так:
Получается, данный цикл будет выводить 0, затем 1, а затем 2. В мире Jmeter с While Controller такой цикл будет выглядеть следующим образом:
2. Добавляем While Controller с условием counter < 3 (будет работать пока переменная меньше 3).
ForEach Controller нужен для обработки всех элементов массива или коллекции. На вход принимаются переменные, которые выглядят как Пример: Запрос возвращает массив со списком ссылок. Мы хотим проверить отдачу картинок по каждой ссылке.
Важно иметь в виду, что данный контроллер принимает на вход префикс одной переменной. Две и более переменных на вход он не принимает. Иногда есть необходимость в данном контроллере пробегать по нескольким переменным, для этого мы используем счётчики и конструкцию обращения к переменным внутри переменных. Если переменная состоит их двух частей, например
Пример: Имеем на входе 2 массива переменных: имя хозяина и кличка животного, которые сохранили через JDBC Request в виде:
Настраиваем его и даем ему имя.
Loop Controller применяется, если нужно отправить запрос определённое кол-во раз. Покажем, как его применять:
Как запускать тесты через терминал, менять окружение и запускать тесты в CIЗапускать тесты в GUI режиме просто — нажать кнопку Start. Но иногда есть необходимость запустить тесты через командную строку (в NON GUI режиме). Чаще всего это применяется при запуске тестов в CI. Обратимся к официальному мануалу и посмотрим, как запустить тесты через командную строку. В общем виде команда запуска выглядит так:
Тестовых слоёв может быть несколько и на всех надо прогонять тесты. Управлять окружением можно несколькими способами:
Поговорим подробнее про последний вариант. Вы называете переменные
А сам слой определяете с помощью Jmeter property
Таким образом:
Всё, что описано выше, пригодится при запуске тестов в CI. Ведь тесты не должны ходить только локально, особенно, если у вас большая команда. Выбрав любой из множества инструментов CI, и найдя к нему интеграцию Allure (например, Jenkins), можно создать билд, который будет запускать ваши тесты. Для этого всё готово — есть МногопоточностьВ какой-то момент тестов стало так много, что их прохождение начало занимать очень много времени и тогда встал вопрос о параллельном запуске тестов. JMeter, как нагрузочный инструмент, постоянно работает с потоками, для этого настраивается Numbers of threads в тред группе, но для функционального тестирования эта настройка не подойдёт. Решением для ускорения прогона тестов стало использование нескольких Thread Group. Далее расскажем принцип использования нескольких тредов. Изначально имеем такую структуру тестов:
Один тред групп и несколько тестовых фрагментов. Если на выполнение каждого тестового фрагмента уходит по 2 минуты, то прогон всего треда занимает 6 минут. Теперь разобьём тесты по отдельным тредам:
В результате наши 6 минут превратились в 2, ну не круто ли? Теперь потоки будут работать параллельно. Так как они не знают друг о друге ничего, могут мешать друг другу при прогоне тестов. В целом лучше стараться создавать тестовые фрагменты изолированными друг от друга. Если не удаётся этого добиться, то можно пожертвовать параллельностью и указать в настройках «конфликтной» Thread Group задержку запуска. Иногда можно обойтись без задержек — сдвинуть конфликтный тестовый фрагмент по порядку в пределах его Thread Group так, чтобы к моменту его запуска он ни с кем не конфликтовал. Если использовать allure-reporter, то данную «конкуренцию» тредов можно увидеть в Allure 2.0. Зайдя во вкладку timeline, можно увидеть каждый тред по отдельности, что за чем шло и т. д. При конкуренции тредов будут видны красные тесты примерно в одно и то же время. Создавать тред-группы можно до бесконечности, всё ограничивается производительностью вашей локальной машинки (у jmeter, с его возможностями в нагрузочном тестировании, проблем с ресурсностью не будет). С добавлением большого количества тредов скрипт начинает много весить и при открытии файла требуется больше ресурсов, но это того стоит. Для примера, 550 тестов в 17 потоков проходят в среднем за 7 минут. Хотя могли бы проходить 1,5 часа, если бы запускались в одном потоке. JMeter Allure ReporterНаписать хорошие тесты — это ещё половина дела. Вторая половина дела — сделать полезные и понятные отчёты. Давайте представим: мы создали запросы, написали пару тестов, запустили локально в GUI и видим: Вроде всё понятно, что и где упало, знаем куда смотреть. А теперь давайте представим, что автотесты будут ходить не в GUI, а прямо из терминала. Чтобы получить стандартный отчёт от JMeter не в GUI режиме, нужно запускать его с определёнными параметрами:
Запустим и посмотрим, что имеем в стандартном отчёте: Видим какие-то ошибки, на каких-то запросах. А понять какая была цепочка запросов, в которой встретилась та или иная ошибка, какие запросы/ответы — уже нереально. Ни понять, ни отловить, ни логов найти по идентификаторам — больно! Поэтому мы начинали задумываться о нормальных, человекочитаемых, привычных для глаз отчётах. Женим JMeter с AllureМы сразу же наметили путь в сторону формата Allure, на это есть пара причин:
Захотели — cделали! Имея открытое API JMeter и возможность запускать код внутри наших запросов через процессоры, мы написали «репортер», который создаёт нужные данные в формате Allure. И как говорится — машем волшебной палочкой и получаем следующее: Теперь можем наблюдать результаты в знакомом всем формате Allure. Вся цепочка перед глазами, все ошибки, все запросы/ответы. Можем разделять проверки на Epic/Feature/Story, добавлять ссылки, комментарии, теги и кастомные лейблы. Если коротко, то абсолютно всё, что умеет кушать Allure, можно добавить. Как пример, с добавлением задачи + описания + тега + овнера. К слову, аттачменты добавляются тут автоматически, кастомные лейблы прописываются в начале наших цепочек и ничего дополнительного настраивать тут не нужно. Кажется, тема написания всяческих «адаптеров» для Allure уже большинству известна. Описывать тут, как это работает — будет излишним, но, если желающие будут, мы подумаем и напишем :) В данном случае лишь сошлюсь на наш открытый репозиторий, где описано, как это работает и что нужно у себя сделать, чтобы всё заработало. Там и docker-compose и готовый образ, там и пример со всеми тестами, которые мы частенько используем https://github.com/nonealexq/jmeter-allure-reporting. Используйте у себя, ставьте звёздочки, следите за изменениями. С возникшими трудностями пишите issues. За репозиторием следим и постоянно обновляем. ИтогоЕдинственная проблема использования JMeter как инструмента для автоматизации функционального тестирования и НЕ локального прогона — отчёты. Они были скудными, не давали никакого понимания куда бежать и что смотреть. Но JMeter, опенсорс, и мы — сделали всё, чтобы эту проблему решить. Теперь всё красиво, всё понятно, и интегрировано с TMS, что даёт нам ещё и статистику и историчность всего происходящего. В статье мы постарались описать необходимый минимум для вкатывания в написание тестов на JMeter. Если вы давно откладывали автоматизацию тестирования, потому что не было времени учить языки программирования, то теперь у вас есть инструмент, с которым вы можете написать свой первый автотест уже сегодня. |