Введение в JMeter

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

    Введение


    Как-то я начал осваивать новый инструмент — JМeter — и не смог найти какого-то полноценного руководства как руководства к действию. Постепенно, разобравшись по некоторым довольно полезным статьям и блогам, пользовательской документации, я начал что-то понимать. И решил, что, возможно, я не один ищу то, с чего можно начать работать. Освоить некоторые принципы построения и логику самого инструмента. Так что вот — статья о том, как начать.
    Так что в этой статье мы рассмотрим пример создания скрипта для 3 пользователей, которые хотят:
    1. залогиниться;
    2. добавить в какой-нибудь альбом новую фотографию;
    3. поменять аватарку.
    Как таковой — это обычный бизнес процесс для какой-нибудь социальной сети.

    И для этих целей будут использованы такие встроенные компоненты:
    • HTTP Proxy Server
    • Recording Controller x3
    • User Define Variables
    • CSV Data Set Config x3
    • Constant Timer
    • Uniform Random Timer
    • HTTP Autorization Manager
    • HTTP Request x6
    • Debug Sampler х3
    • HTTP Cookie Manager
    • Once Only Controller
    • Возможно, некоторые другие.

    Статья большая, потому что подробная. В итоге должно получиться что-то вроде такого:
    c017f1f09f290a0fa142b4cb9edbc8b5.png

    Автоматическая запись скрипта


    Суть в том, что когда мы создаем скрипт для сайта, который мы тестируем методом черного ящика, мы не знаем всех тонкостей и особенностей его работы. Так, например, тот сайт, на базе которого в итоге получится мой скрипт, написан при помощи некоторого пакета Symphony2. Из-за неё отправка данных логин-пароль идет не прямо с формы на странице /login, а с некоторой несуществующей страницы /login_check. И ко всему этому отправляется еще одно пустое поле, которое для пользователя скрыто.
    Обнаружить подобные подводные камни поможет HTTP Proxy Server (это, как и всё прочие, встроенный элемент). Эмулируя работу прокси сервера, он будет записывать все полученные\отправляемые запросы.

    Подготовительные действия


    Мы пока не будем добавлять HTTP Proxy Server в дерево теста. Обсудим, куда мы будем записывать полученные «шаги». Позже, когда мы добавим элемент в дерево, мы увидим, что есть несколько возможностей, куда именно записывать результаты. Их можно записать прямо в «катушку» (Thread), на «верстак» (Workbanch), либо в элемент «Recording Controller». Я советую воспользоваться последним способом. Во-первых, это позволит при необходимости отключить (ctrl+t) весь лог разом; во-вторых, так лучше отслеживается и формируется структура теста.
    Все действия по добавлению и редактировнию происходят по нажатию правой кнопки мыши в контекстном меню. Созданные элементы можно просто перетаскивать (drag and drop).
    Итак: Test Plan -> Add -> Threads ->Thread Group; Thread Group -> Add -> Logic Controller -> Recording Controller.
    Настоятельно рекомендую дать сразу всем элементам понятные имена. В моём случае это будут «Картинки» и «Залогинимся», соответственно.
    15bb271fb1ef8d13b8c0d94ba3319ef7.png

    Записываем скрипт при помощи HTTP Proxy Server


    Когда подготовительные действия завершены, добавим на «верстак» необходимый элемент: WorkBench -> Add -> Non-Test Elements -> HTTP Proxy Server.
    В нем много настроек, но нас интересует пока только порт. Если порт 8080 занят, можно выставить, например, 8089. Я на своей машине использую именно этот (8089). Так же мы видим, что по умолчанию в поле Target Controller стоит «use recording controller». Т.е. записываться лог будет именно туда.
    Остальные поля трогать не будем, но некоторые из них нам понадобятся, когда мы получим чуть больше информации о нашем сайте.
    df806a35fb74dc3aac7b46f4dfb7421e.png
    После того, как выставили порт, идем в настройки браузера. Я банально использую IE. Сервис — Свойства обозревателя — Подключения — кнопка Настройка сети. Ставим галки «Использовать прокси-сервер …», вторую галку снимаем. Рекомендую заглянуть в «Дополнительно» и посмотреть, что написано в «Исключения». В моей практике в процессе тестирования сайт перенесли на новый домен, который оказался в исключениях. Ушло около получаса, чтобы разобраться, почему действия моего виртуального пользователя на тестируемом сайте не записываются, а всякие ссылки на яндекс, твиттер и фэйсбук прекрасно логируются. В общем, если там неожиданно оказался домен вашего сайта, сотрите.
    В поле Адрес пишем «Localhost», а порт указываем как из JMetеr'а: «8089». Без кавычек всё, разумеется.
    795fceb9b55e67df06cbb39b501e9d61.png
    Теперь все готово для записи. Возвращаемся в JMeter на прокси и внизу можем нажать кнопку Start. После нажатия все действия пользователя в браузере начнут записываться в созданный нами Recording Controller «Залогинимся». Записывать действия будем в несколько шагов, т.к. скрипт может оказаться чрезмерно большим и его будет сложно редактировать. Так что первое, что мы сделаем, а после отладим, это авторизация пользователя на сайте.
    Итак, нажимаем Start и проходим процедуру авторизации на сервере (у вас может её не быть, а у меня есть) и процедуру авторизации на сайте. Возвращаемся в JMeter и жмем Stop. Смотрим на Recording Controller: у него куча дочерних элементов. Это то, что мы послали на сервер, а сервер ответил. Изучаем и чистим.
    fc624c70b137e9f18e1c1106790f1ceb.png

    Отладка скрипта


    Отладка скрипта представляет собой удаление различных .jpg, .png и ссылок на сторонние ресурсы. У меня в скрипте больше половины таких сторонних ресурсов — это связи с различными социалками и яндекс картой. Всё это можно вычищать (клавишей delete). В целом, также можно вычистить .js. Главное найти запрос, который передает в своем теле учетные данные вашего пользователя. Ну и для красоты найти запрос, который ведет вас на страницу, на которой пользователь логинится. Таким образом, вместе они моделируют связку в действиях пользователя «зашел на страницу — залогинился».
    Предположим, что нам повезло вычленить необходимые запросы. Ну, или нам кажется, что мы их вычленили. Дадим им читаемые имена! Чтобы проверить то ли мы вычленили, скрипт надо запустить. В моем случае, если запустить скрипт, то он выполнится с ошибками. Дело в том, что мне для тестирования нужно авторизоваться на сервере. Для этого добавим в верхушку дерева HTTP Autorization Manager (Thread Group – Add – Config Elements – HTTP Autorization Manager). Он интуитивно понятен. Записываем туда адрес нашего ресурса обязательно с http://, имя пользователя и пароль.
    5327c7af9f700f2bcfdcff6f0e4cc4a1.png
    Если Менеджер Авторизации нужен для авторизации на сервере, то абсолютно точно при авторизации на сайте используются куки. Добавляем Cookie Manager после Менеджера Авторизации (TestPlan – Add – Config Elements — HTTP Cookie Manager). Этот элемент необходимо добавлять, пожалуй, всегда, если речь идет о том, что пользователю нужно залогиниться.
    Прежде чем запустить и проверить скрипт добавим элемент View Results Tree (Катушка – Add – Listener – View Results Tree), в котором можно будет наблюдать выполнение. Этот элемент удобно располагать всегда внизу. Ах да, еще нужно в настройках браузера убрать галку «использовать прокси» — он пока нам не понадобится.
    09d903bd3717d97ac545623830610536.png
    Итак, можно запустить. Запускаем (ctrl + r)!
    В View Results Tree видим следующее:
    023f9367cb24ffed7e5cca45b7f82831.png
    Кажется, нам повезло. И даже если мы не залогинились, то, по крайней мере, запросы дошли до сервера. Чтобы убедиться, что пользователь был успешно залогинен, посмотрим в дереве на ответ. Нажимаем на Response Data. В ответе сервера ищем информацию, которая свидетельствует об успешной авторизации пользователя. В моем случае это будут имя пользователя, т.к. после авторизации оно высвечивается на странице.
    a7915066621c3127e152cdd72739ea2d.png
    Скрипт по-прежнему может нуждаться в чистке. Я, например, удалил из него HTTP Header Manager'ы. И без них всё работает отлично. Чтобы убедиться в нужности каждого элемента, его не обязательно сразу удалять, достаточно этот элемент отключить (ctrl + t).
    Далее мы хотим привлечь к этому делу 3 пользователей. Для этого прежде выполним небольшой учебный пример по параметризации запросов. Параметризируем одного конкретного пользователя.

    Параметризация


    Для параметризации запросов добавим в самый верх User Define Variables. Thread -> Config Controllers -> User Define Variables. Внизу есть кнопка Add. Нажимаем ее, вбиваем две переменные, т.к. меняться у нас будут только два параметра: логин и пароль. Дадим им хорошие имена: userName и password. А в качестве значений впишем пока конкретные значения текущего пользователя.
    64f29cba08c40a5eb434cd5592d333c0.png
    Чтобы их использовать переходим в запрос Логин, и вместо конкретных значений пишем имена переменных в формате ${имя переменной}. В нашем случае записываем в поля Value для логина — ${userName}, для пароля — ${password}.
    3ce15268749a60ff2bf390df1e63e2ac.jpg
    Для отладки передачи параметров добавим еще один элемент – Debug Sampler. Thread –> Add -> Samplers –> Debug Sampler. Его поставим после запроса Логин. В настройках элемента оставим только JMeter variables, остальные поставим в false. Это делам для того, чтобы отловить только наши переменные. Да и всё равно других нет.
    060ae24c1bb7116dd9584958c9a51b9a.png
    Запускаем и смотрим в View Results Tree результаты. Должны видеть, что в качестве переменных передались именно наши значения, и запросы в целом вернули то, что нужно (см. выше).
    ab2dea0a6bf3bf094fda5db1c90dec99.png
    Теперь можно передать данные 3 пользователей. Для этого воспользуемся CSV Data Set Config.

    CSV Data Set Config


    Я предлагаю создавать .csv файл в блокноте. Для пользователей файл должен представлять собой набор из 3х строчек вида «UserName;Password». Мой файл представлен на скрине ниже:
    494aec49fe34799d4b84496c9e3a86d7.png
    Далее добавим в дерево элемент CSV Data Set Config (Add – Config Elements – CSV Data Set Config). Добавим его не в катушку, а в тест-план, ниже пользовательских переменных. В качестве filename для файла нужно указать полностью путь к файлу и его имя. Ниже указать кодировку (на ваш выбор). Если все данные на английском, то поле можно оставить пустым. Ниже написать переменные, которые считаются из файла. Для нас это будут UserName и Password. В качестве разделителя нужно указать точку с запятой, так как в файле используется она. Ниже, для того, кто хоть немного владеет английским, не сложно перевести имена логических переменных. Нужно поставить в false повтор файла по достижении конца, а также остановку катушки.
    0e6afc60ec56cda8c1b2ec293e1dbf38.png
    Далее удалим подобные переменные из User Define Variables. То, что он останется пустым, это не страшно. После этого в самой катушке количество потоков (Number of Threrads) установим на 3.
    Теперь можно запустить скрипт и наблюдать в Debug Sampler и View Results Tree результаты. Не забудьте проверить, те ли данные вернул сервер, есть ли в них имена ваших пользователей.
    c48389e089136baa81c6e0b43bc9d969.jpg

    Добавляем фотографию в альбом


    Теперь, когда наши пользователи научились логиниться, приступим к следующей части нашего скрипта. Научим их заливать в какой-нибудь определенный альбом нашего сайта фотографии. Для этого опять добавим в катушку Recording Controller, назвав его «Фотографии».
    Чтобы сократить полученный скрипт, заранее авторизуемся пользователем на сайте и перейдем на страницу, на которой начнется непосредственно загрузка фотографии. После этого снова включим в настройках браузера прокси и воспользуемся элементом Proxy Server на верстаке (указав другой Recording Controller). Так же в URL Patterns to Exclude укажем расширения, которые нам не нужны в формате «*.\.ххх».
    d7bc20766cd922782bef276dc4c859da.png
    Start, заливаем в альбом фотографии, End. Приступаем к чистке скрипта. Точно также можно для красоты оставить лишь те запросы, которые образуют связку «зашел в альбом — добавил фотографию». У меня получилось так:
    872415c5eb1f61833944faad3ab94d18.png
    На самом деле, запрос «зашел в альбом» записан был вручную. Он не представляет собой ничего сложного: это GET запрос с указанием адреса страницы.
    Обратим внимание на тело запроса, который отправляет на сервер файл. Единственное, что в нем представляет для нас ценность, — это путь и имя файла. Вот их мы и параметризируем, чтобы каждый пользователь заливал какую-то свою фотографию. Начнем с пути к файлу. Как таковой для тестирования он не представляет интереса. Вполне вероятно, что все фотографии будут у вас лежать в одной папке. Но в тесте он может встречаться много раз. Так что по правилам хорошего тона запишем его в переменную. Возвратимся к User Define Variables и добавим туда переменную filePath со значением пути до папки, в которой лежат фотографии, например, "** D:\jakarta-jmeter-2.5.1\images\**". Именно со слэшем в конце, позже ясно будет для чего.
    Как всегда, протестируем сначала скрипт на одном файле. Поэтому создадим еще одну переменную fileName, в качестве значения которой будет конкретное имя файла, например, "img.jpg".
    23b590db04c057d0d48817886a1107a4.png
    Возвратимся в тело запроса. В разделе Send Files With the Request пишем путь уже таким образом: ${filePath}${fileName}. Если подставить в переменные указанные значения (value из user define variables), легко убедиться, что получается корректный путь. Посмотрим на параметры, которые передает запрос. Там тоже есть имя файла. Впишем вместо него ${fileName}.
    31d4483e50685da1fa518f82c134d51e.png
    Теперь, когда имитация пользователя в этой части закончена, добавим новый Debug Sampler. Подумаем на шаг вперед: если мы заставим катушку крутиться forever (пока не ставить!), то каждый пользователь будет логиниться по много-много раз, верно? Чтобы этого избежать, добавим в катушку логический элемент Only Once (Thread -> Add -> Logic Controllers -> Only Once Controller). Поместите его в соответствующее место над Recording Controller'ом, отвечающий за авторизацию пользователя на сайте, а сам контроллер перетащите в него как дочерний.
    c762b94cfdb723ff46aa620a622cc7cd.png
    Отключите в браузере прокси. Запустите срипт. Если всё сделано правильно, то в выбранный альбом добавится новая фотография. Если что-то не так, посмотрите Debug Sampler в View Results Tree.

    Параметризируем


    Теперь можно сделать так, чтобы пользователи добавляли разные фотографии. Для этого создадим csv файл, в кототором будут содержаться только имена фотографий:
    Img.jpg
    Img1.jpg
    Img2.jpg

    Создадим CSV Data Set Config, перетащив его под другой CSV Data Set Config, укажем путь к этому файлу. В качестве переменной (variable Names) укажем fileName, а из пользовательских переменных (User Defined Variables) её удалим. Поле для разделителя оставим пустым. В этот раз повторять файл при достижении конца (Recycle on EOF) оставим на True, а останавливать катушку при достижении конца (Stop thread on EOF) — на False. Для красивой логики нашего теста перенесем фотографии в отдельную папку: " D:\jakarta-jmeter-2.5.1\images\Photo\ " и соответствующим образом изменим значение переменной filePath на filePath_Photo. Сделаем это и в тех местах, где переменная используется.
    Запускаем тест! После чего смотрим, добавилось ли в альбом 3 фотографии (да, все пользователи должны иметь достаточно прав, на добавление фотографий в альбом). Если всё ОК, продолжаем дальше. Если нет — читаем Debug Sampler и ответы сервера.
    813d89e44911fc7e1ac02f404e708d01.png

    Изменяем аватарку


    На деле это ничем не отличается от предыдущего параграфа. Точно также нужно залить на сервер фотографию. Поэтому делаем все также:
    1. создаем очередной recording controller
    2. настраиваем прокси
    3. делаем действия на сайте (записываем скрипт)
    4. чистим скрипт
    5. параметризуем для одной аватарки
    6. отлаживаем
    7. параметризуем для множества аватарок

    В качестве имен аватарок я использовал тот же csv файл, но залил картинки в другую папку и создал новую переменную для нее: filePath_Avatars.
    Если всё работает, то это хорошо. Если нет, смотрим в Debug Sampler.
    Чтобы скрипт был больше похож на живого человека, нужно добавить задержки. Например, после загрузки фото на сервер, можно поставить Constant Timer на 3 секунды (3000ms), будто пользователь ждет, пока картинка загрузится на сервер. А для смены аватарки Gaussian Random Timer от 2 до 6 секунд, будко пользователь ищет и выбирает аватарку. Так же для большего правдоподобия в каждом HTTP Request можно поставить галку Retrieve All Embedded Resourced From HTML Files, означающую что со страницы будет загружаться всё возможное, как в обычном браузере.
    Итак, предположим, что всё работает и всё отлично. Всё. Задача полностью выполнена. Теперь осталось нагрузить наш сайт на всю ночь. Вернемся в Thread и установим галку forever. Это значит, что скрипт будет выполняться, пока не случится событие «stop thread». В CSV Data Set Config'ах мы выставили возможность такого события в False. Значит, тест будет выполняться, пока его не остановит тестировщик руками (меню Run -> Stop). Итоговый скрин выложен в начале статьи.
    Тест моделирует банальный бизнес-процесс для какой-нибудь социалки: пользователь зашел в сеть, залил в альбом фотографию, которая ему ну уж очень понравилась, со вчерашней вечерины и поменял свою аватарку на это (либо другое) фото. Поставив такой процесс на forever, мы получили 3 пользователей, которые заливают фотки и меняют на них аватарки. Процесс можно изменить, добавляя различные другие элементы. Например, заливать фотографии можно только одну, поставив Only Once, а вот менять аватарки бесконечно. Если пополнить базу до 1000 пользователей, запустить скрипт непосредственно с сервера, а также с локальных машин в офисе — это будет достаточно серьезная нагрузка на сервер приложения.
    Возможно, следующая статья будет посвящена тестированию поиска и регулярным выражениям, либо оценке и интерпретации собранных данных.
    Будем рады любому обмену опыта.
    Share post

    Comments 10

      +5
      Вы хотя бы написали сначала, что это вообще за инструмент, раз уж статья для начинающих. Я могу конечно загуглить, но не все же такие. =)
        –1
        Если кто-то не может загуглить, то можно смело мимо проходить.
          +1
          Вы не правы. Я вот статью тупо пропустил через свой информационный фильтр и она его не прошла. Если бы была вводная — я бы почитал и понял о чем речь, что за оно и стоит ли в это углубляться. Прочитать один абзац не трудно.
          Читать для этого всю статью, тем более не маленькую — неа. А значит в топку.
          Гуглить, пускай это и один запрос и один клик — неа. Потому что лениво, потому что куча других дел, потому что начав гуглить увлекусь еще другими темами и пошло поехало. Поэтому в топку.
            –3
            Если бы это была первая статья про жмитер — то да, согласен. А так это уже «стопятьсотая».
              0
              «Статья подготовлена сотрудниками отдела тестирования в компании, где я работаю.
              На хабре уже не первый раз пишут про JMeter, но статьи имеют довольно узкую направленность, либо сложны для понимания. Поэтому, эта статья будет интересная именно начинающим.»
                –2
                Именно поэтому вводную часть можно пропустить.
                В общем здесь явно что-то не сходится =)))
        0
        Неплохо бы использовать вместо «катушки» адекватный перевод, а не то что нарисовано на картинке — дабы не терять смысл термина =]

        И думаю стоит на всякий случай упомянуть, что зачастую при проблемах авторизации помогает установка у HTTP Cookie Manager параметра Cookie Policy в значение netscape.
          +2
          Больше всего в статьях о jmeter мне хочется видеть описание не того как сделать и запустить тест а описание анализа итоговых результатов, графиков.
            0
            С одной стороны, поддерживаю комментарий, а с другой… По-моему, в зависимости от принятых в компании норм, могут потребоваться очень разные метрики, поэтому надо быть готовым парсить логи или писать свой листенер, чтобы получить то, что нужно именно тебе. Такие обсуждения скорее в профильных коммьюнити надо искать, Хабр тестирование не очень-то жалует.
            Например, мне совершенно не понятно, почему довольно распространённой метрикой является 90% Line. Для меня от информации, что на 90% запросов сервер отвечал за 80 мс, совершенно ничего не проясняется :)

            И да, на офсайте пишут про версию 2.6 с обновлённым интерфейсом и огромным количеством багфиксов :)
              0
              графики JMeter анализировать вообще довольно сложно. Только так — посмотреть, «как оно идёт».
              Гораздо удобнее — таблицами, или на худой конец импортировать результаты.

            Only users with full accounts can post comments. Log in, please.