С нуля до плагина JMeter: пишем свой продукт без опыта

8140efa090ea86d2802d857e15f63f2c.png

Всем привет.

Меня зовут Олег, я обеспечиваю качество в компании «Trucker Group» уже на протяжении двух лет. Для большинства выполняемых нами задач всегда хватало решений на рынке, но сегодня речь пойдёт о случае, который выходил за рамки привычного хода вещей и поделил мою работу на «до» и «после» — возникла потребность написать свой инструмент. И как это часто водится, всё началось внезапно и задолго до этого момента…

Но перед тем, как я начну повествование, стоит уточнить и взять в расчёт несколько деталей:

  1. На тот момент мой навык программирования был ограничен скромными познаниями в JS, умением писать регулярные выражения на Perl и основами использования JEXL3. Из всего этого в процессе мне немного пригодились регулярные выражения, но и без их знания мало что поменялось бы;

  2. Я не имел практически никакого представления о Java и ООП;

  3. Я владел JMeter на базовом уровне.

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

Введение

Уже в течение года в нашей компании активно используется JMeter как инструмент для написания backend-автотестов. Это по всем параметрам прекрасное решение:

  • Низкий порог входа;

  • Возможность писать и функциональные тесты, и нагрузку;

  • Модульность инструмента и открытый исходный код.

Параллельно с этим зарождалась потребность в смене системы управления тестами (TMS), а привлекал нас больше всего Allure. Здесь возник закономерный вопрос:, а как вообще выводить результаты тестовых прогонов из JMeter в интерфейс Allure? Мы изучали рынок, но информации не много, а универсального решения будто и вовсе нет. Самый интересный рабочий вариант из найденных нами предложила команда банка Точка.

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

Так из мухи получился слон и, вместо вопроса «Как вывести отчёт в формате Allure?», меня поглотила идея написать свой собственный плагин.

От идеи к требованиям

Любую идею нужно довести до ума и чётко определить, чего я хочу. Плагин — это здорово. Но каждый плагин для JMeter, добавляющий в него элементы теста, должен иметь тип (таймер, сэмплер, препроцессор и т.д.). На что же больше всего похожа штука, которая будет содержать в себе какое-то количество сэмплеров (шагов теста) и объединять их в один тест? Ну тут однозначно контроллер! Он как раз используется в этом инструменте для разграничения логических блоков — почему бы не считать тест-кейс отдельным блоком?

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

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

Помимо полей в интерфейсе вашему плагину могут потребоваться какие-то генерируемые только на бэке данные. В моём случае это было время в формате «timestamp» и случайные UUID. Во всех популярных языках программирования есть функции для их получения, потому что это общая информация, а не что-то специфическое. Если вы не уверены, что нужные вам значения легко можно получить, то сперва проверьте эту информацию любым достоверным способом. ChatGPT не всегда источник истины, но чаще всего на правильные вопросы получаются приближенные к правде ответы. Если всё ещё не уверены, заменяйте какими-то другими величинами.

Так сформировались предварительные продуктовые и проектные требования. Они ещё неоднократно менялись на следующих этапах, когда я сталкивался с теми или иными сложностями, но это нормально — вода камень точит.

Первые шаги: определяем стек и используемые инструменты

Вы видели, как выглядят плагины для JMeter? Это какие-то jar-файлы. Первый вопрос, которым я закономерно задался: «Что такое jar-файл и как его получить?». Так стало понятно, что мне для реализации своих планов потребуется не только среда разработки, вроде VSCode, но и компилятор, чтобы из файлов с расширением .java вытащить классы (.class) и создать из них jar-архив. Какую полезную информацию это даёт:

  • Исходные файлы, в которых написан плагин — это java-файлы. Следовательно, если я как человек без опыта хочу написать что-то, опираясь на уже существующие решения, то мне нужно искать исходники других плагинов в этом самом формате и качать их к себе в «базу знаний» (папку с материалами);

  • В исходниках для каждого элемента принято использовать как минимум 2 файла. Название второго заканчивается на GUI, что наводит на мысль, что в одном файле находится логика (условный backend), а во втором интерфейс (условный фронт);

  • Есть несколько популярных инструментов для компиляции кода на Java. По умолчанию для большинства пакетов этого языка идёт утилита javac. От компилятора будет зависеть способ сборки.

Мне повезло, что JMeter — это инструмент с открытым исходным кодом. У Apache на GitHub репозиторий, в котором лежат исходники продукта, то есть для всех базовых элементов теста. Я быстро отыскал его и жадно скачал себе всё до последнего файла. Всё в дом, пригодится или нет — потом разберёмся!

98bdaebb6b7b956a0d30e0ba1ffd0a70.jpg

К слову о компиляторе: попробуйте сразу Maven. Это связано с первой ощутимой пощёчиной, которую я отхватил из-за своей глупости и самоуверенности. Забегу на месяц вперёд: я пробовал по аналогии с уже имеющимися у меня исходниками других контроллеров писать какой-то код и компилировать его при помощи javac, а потом вставлял в папку с плагинами и запускал JMeter — ничего не работало, новый контроллер не появлялся. Так прошло несколько недель бессмысленных и беспощадных попыток, а потом меня неожиданно посетила мысль:, а что, если скачать все исходники какого-нибудь плагина и так же самостоятельно скомпилировать его с помощью javac? Каково же было моё удивление, когда не тронутый мною плагин, скомпилированный таким образом, не заработал.

Так javac, около 20 часов работы и мои нервные клетки отправились прямиком в помойку.

Я посмотрел на YouTube несколько обучающих видео о Maven, скачал его себе и провёл тот же эксперимент с чужим плагином — он тут же скомпилировался и без проблем отобразился в интерфейсе JMeter. Не повторяйте моих ошибок и заранее проверьте используемые вами инструменты на работоспособность.

Итого из постоянного инструментария мы будем использовать среду разработки (подойдёт упомянутый выше VSCode), сборщик проекта (Maven) и ChatGPT. Да-да, и его тоже, а как вы хотели? Когда нет опыта, нужно откуда-то брать информацию о языке программирования и его правилах. Я выбрал для этого путь наименьшего сопротивления.

ChatGPT или программирование для ленивых

Как порядочные пираты, мы уже «скоммуниздили» исходники всех нужных нам плагинов, но что вообще в них написано? Что за импорты? Какие ещё классы? На все эти базовые вопросы (и не только) ответит гуру всех простых вопросов — ChatGPT. Но помните, что здесь работает золотое правило: хотите получить правильный ответ — задайте правильный вопрос. Можно заставить бота объяснять код даже не построчно, а каждое новое слово отдельно, чтобы лучше понять его ценность. Для отдельных блоков кода, выделенных фигурными скобками, можно целиком узнать их назначение. Так впоследствии я выяснил, что они называются «методами» внутри класса, и их задача — выполнять определённые действия в момент вызова. Сам класс к тому же должен расширять родительский класс, который как правило общий для всех элементов из одной группы (у таймеров один, у сэмплеров другой и т.д.). В моём случае для всех контроллеров в JMeter родительским с точки зрения логики (backend) является класс «GenericController», а с точки зрения интерфейса — «AbstractControllerGui».

Посмотрев исходники других плагинов, я понял, что у них есть общие методы, которые они наследуют из родительского класса и при необходимости перезаписываются, если вносятся изменения. Для AbstractControllerGui оказалось несколько основных методов, которыми должен обладать мой класс, чтобы он отображался в интерфейсе. В GenericController за основные действия, выполняемые между обработкой сэмплеров, отвечает метод next (). Определив эти моменты, я стал писать свой первый код. Лучшее начало по моему опыту — это объявление всех полей на бэке и параллельное их указание в интерфейсном классе. Всю логику, которая будет вокруг этих полей, оставьте на потом — начинать нужно с малого.

Сразу ещё один совет, навеянный болезненным опытом. Выше я писал, что вместе с javac отправил в помойку около 20 часов работы. На том этапе вы могли возразить: «Компилятор ты поменял, но код же у тебя остался — значит не всё потеряно». Но не тут-то было. Разобравшись с Maven, я естественно сразу же попытался скомпилировать и свой плагин. Сборка прошла успешно, вот только в JMeter по-прежнему ничего не появилось. Тогда я начал с чистого листа. Оказалось, что в интерфейсном классе моего контроллера была пара строк, которые в коде выглядят хорошо (ещё и VSCode подсказывает, что они правильные), но по факту их использование что-то ломало и из-за них мой тестовый элемент не отображался в JMeter. Так и обесценились предыдущие наработки — я возомнил, что могу сразу всё написать, а потом просто скомпилировать и оно будет работать. Этот опыт научил меня делать компиляцию и проверять интерфейс JMeter после добавления каждых 3–4 строк кода (либо после добавления каждого нового метода или элемента интерфейса). Это позволяет быстро локализовать проблемный код, чтобы не выкидывать всё, не понимая, где и что не так. Знал бы я это раньше…

Для начала, к каждому объявленному полю (на всякий, объявление — это указание поля как свойства контроллера в строковом типе в самом верху класса) добавляется по 2 метода, которые ещё называют «геттер» и «сеттер». Они нужны, чтобы можно было получить значение свойства (get), и чтобы самостоятельно его указать (set). Их используют во всех плагинах, поэтому я решил сделать по примеру — убрать всегда успею.

3d7f084d39ccee5b83a378bc614a93dd.jpg

Каждое поле, которое я добавил как свойство в backend-классе, следовало добавить ещё и в интерфейсный класс, чтобы была чёткая связь между тем, что указывается в UI в полях контроллера, и тем, что в это время записывается для них в коде сценария (jmx-файле). Когда вы поймёте принцип и ваш тестовый элемент всё-таки появится в интерфейсе JMeter, обязательно попробуйте заполнить эти поля, сохранить изменения и открыть этот jmx-файл через любой редактор кода. Там вы должны увидеть, что значения, прописанные вами в интерфейсе, отображаются и в коде в соответствующих полях — значит начало положено и всё идёт хорошо.

Уже сейчас у вас собран тестовый элемент, в котором есть какие-то поля, которые заполняются, но только это ни на что не влияет. А почему? Потому что мы пока добавили только объявление полей и их отображение в UI, а самое «вкусное» — логику взаимодействия контроллера с этими полями во время теста — оставили на потом. И вот здесь настало время оправдать название этой главы, пришёл звёздный час ChatGPT. Геттеры и сеттеры писать не сложно, обычно это пара строк. А вот теперь собираются полноценные логические блоки, выполняющие действия в зависимости от условий. Мы с вами не программисты, но мы знаем, чего мы хотим. Самое время донести эту информацию боту. Пишем максимально подробный и чёткий запрос. Не бойтесь кидать ему полные тексты ошибок, которые вам подскажет VSCode, или даже целые куски кода. Например, мой типичный чат начинался так: «Я пишу класс на Java для JMeter, который расширяет класс GenericController. Как правильно написать метод или функцию, которая будет проверять значение из поля …, и если оно равно …, то будет происходить …». Да, бот тоже может ошибаться либо предлагать вам не самые оптимальные варианты, но по опыту — переспрашивайте, перефразировав вопрос, если вас сразу не поняли. Зачастую небольшие изменения (а иногда и повторный запрос один в один) выдают разные результаты. Искусственный интеллект не напишет всё за вас, но он может подсказывать сырые решения, и построчно объяснять их, чтобы после небольших доработок с вашей стороны они отвечали требованиям и делали именно то, что задумывалось.

И ещё один совет — сразу настройте логгер. Это такая утилита, которая позволит вам выводить в логи JMeter все нужные ошибки и другого рода сообщения. Я к этой мысли пришёл далеко не сразу и знатно намучился, выясняя, отрабатывает только что написанный мною метод или нет. А так вывел бы в логи сообщение об ошибке с любым текстом и сразу стало понятно, выполнился блок или нет. Будьте умнее меня и не тратьте время впустую.

Хорошей практикой также считается перепроверка кода. Разработчики постоянно так делают и оставляют друг другу свои комментарии и предложения по оптимизации. У нас такого «друга» нет, поэтому ревью будет проводить (барабанная дробь) ChatGPT. Когда вы закончите писать большой блок из нескольких связанных методов, скиньте их все в чат с ботом и попросите его провести ревью и оптимизировать. Если в том, что вы написали, есть что-то лишнее либо возможность эффективнее переиспользовать компоненты, в большинстве случаев искусственный интеллект поймёт это и перепишет код за вас. Но не спешите радостно удалять свой вариант и заменять рекомендованным. Убедитесь, что в случае чего сможете откатить, потому что такие изменения нуждаются в повторном кропотливом тестировании.

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

Эпилог

Рассказ подходит к логическому завершению. Это однозначно интересный опыт, который сопровождается обильным количеством преград на пути и прочих подводных камней. Универсального рецепта нет — есть лишь ваша потребность и ваше упорство. И когда этого упорства хватает, чтобы не бросать начатое после нескольких попыток, любое дело обречено на успех. Но независимо от результата вы получите навык создания на Java интерфейса и логических блоков на бэке, понимание, как они взаимодействуют между собой, и более осознанное и объективное видение процессов, которые и управляют вашим JMeter в ходе сценария.

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

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

0088712fa52ef380ffd2bdf956b5592c.jpg

© Habrahabr.ru