Нагрузочное тестирование сайта
Задача:
Провести нагрузочное тестирование интернет-магазина с системой мультисайт.
Реализация:
Этапы нагрузочного тестирования
Первый этап. Первой мыслью проведения нагрузочного тестирования сайта было написание своих тестов. Предполагалось завести несколько подразделов мультисайта (по регионам), на каждом из которых будет N юзеров и M продавцов, продающих K товаров Далее через цепочку POST/GET запросов можно было бы имитировать основные проблемные действия юзеров (покупка, большие корзины, построение отчета, поиск по товарам) и все это замерить в отчет. Однако, в итоге приняли решение посмотреть в сторону аналогов. Оказалось они есть, и ими даже пользуются.
Второй этап. Посмотрев статьи, выбор пал на Selenium IDE + jMeter. В теории первый позволял эмулировать действия пользователя непосредственно из браузера, второй мог бы позволить запустить это в виде черного ящика во много потоков, тем самым создав нагрузку. На первый взгляд новичка в нагрузочном тетсировании у меня сразу всплыл в голове тот факт, что запуск такой системы насоздает мне миллион браузеров для каждого потока, съест оперативку и в итоге я не поулчу реальных значений тестов из-за лагов компьютера.
Выбираем онлайн сервис нагрузочного тестирования
Этап третий. Было решено еще поборозить интернет на предмет того, как это делают остальные. В наличии оказались online серверы нагрузочного тестирования. Первый сервер, который попался под руку: Load Impact (loadimpact.com), обладает невысокой функциональностью, позволяет нагрузить сайт 25 пользователями, которые изображают активность на сайте. Сайт с уверенностью прошел тест, поэтому понадобились более мощные инструменты нагрузки. Следующим подвернулся LoadStorm (loadstorm.com), более широкий в плане функциональности инструмент, с поддержкой верификации (чтобы проверить, что я не хакер создающий левую нагрузку), но уже платный. Дальнейшие просматриваемые online сервисы тоже свелись к тому, что нужно заплатить за создаваемую облаком нагрузку, а предоставляемые бесплатно 50-100 пользователей это мало.
Этап четвертый. Возвращение к jmeter. Почитав еще раз внимательно про эту систему я понял, что не так она и страшна. Первым делом её необходимо было поднять. Для этого на сайте jmeter.apache.org/download_jmeter.cgi был скачан дистрибутив, установлена Java SE, необходимая для его запуска и.... он не запустился. Информации по ошибкам в интернете код наплакал, поэтому методом проб и ошибок было выяснено, что дистрибутивы в разных архивах немного отличаются и тот который мне нужен был не в tgz архиве, а в zip. Хорошо. Берем на этот раз нужный дистрибутив, устанавливаем. Далее нам требуется плагин WebDriver для управления браузерами (в частности firefox). Заходим на сайт jmeter-plugins.org/downloads/all/ качаем плагин. Распаковываем его и ставj ,eим в паку lib. При этом смотрим, чтобы версии этих пакетов: httpclient, httpcore, httpmime в папке lib не двоились, если такое имеет место быть, то удаляем наиболее старые, в противном случае запуск теста обернется выбросом исключения (опять же метод проб и ошибок). Настало время собрать тест. Для этого в запущенном jmeter в раздел testplan добавляется thread group, в который добавляется HTTP Cokkie Manager, Firefox Driver Config, Web Driver Sampler и View Results Tree.
Получаем такую иерархию:
Далее необходимо написать управляющий сценарий, который будет обрабатывать jmeter и эмулировать действия юзера на сайте.
Примитивный вариант скрипта выглядит так:
var pkg = JavaImporter(org.openqa.selenium)
var support_ui = JavaImporter(org.openqa.selenium.support.ui.WebDriverWait)
var wait = new support_ui.WebDriverWait(WDS.browser, 5000)
WDS.sampleResult.sampleStart()
WDS.browser.get('http://192.168.0.92/jeikei/magazin/')
WDS.sampleResult.sampleEnd()
Вначале подключаются необходимые библиотеки, затем уже непосредственно через WDS передаются указания браузеру, что он должен сделать.
WDS.browser.get('http://192.168.0.9/jeikei/magazin/')
Здесь указывается сайт, который мы собственно собираемся мучать.
Пробуем запустить тест, если все в порядке, то мелькнет окно браузера, в котором быстро откроется тестируемый сайт, и оно закроется. В ноде View Results Tree можно будет увидеть сообщение о том, что тест пройдет (или не пройден, кому как повезет :)
Если браузер при запуске теста открылся, но сам сайт не открывается и процесс зависает, значит Вы такой же везунчик как и я. Поиск причин данной проблемы занял много времени, пока на одном захудалом форуме наконец не выяснилось, что моя версия firefox слишком новая, и вообще что jmeter лучше всего дружит с версией firefox 22. Принимаем как данное, идем ставить firefox 22, действительно после этого все работает.
На этом работа с jmeter приостанавливается, далее необходимо через selenium IDE сформировать набор управляющих команд, а затем перевести их в WebDriver формат, для запуска в jmeter.
Идем на сайт selenium ide и качаем пакет для установки в firefox. Перезапускаем браузер.
Включаем в расширениях браузера всю установленную радость и снова перезапускаем браузер.
После этого имеем в инструментах Selenium IDE.
Далее заходим на тестируемый сайт, и производим те действия, которые хотели бы эмулировать, Selenium IDE все это запишет. И переведет в управляющие команды.
Полученный набор команд, необходимо перевести в WebDriver format для нашего сэмплера в jmeter и тест можно будет запускать. Вариантов перевода в интернете найдено было немного. Основной - это генерация кода в JUnit через сам selenium IDE и последующей сборкой этого добра в Eclipse, однако это требовало бы в итоге отказаться от сэмплера и подключать JUnit Request в jmeter, и кто знает что бы за этим еще вылезло далее. Второй это документация по Web Driver Sampler, которая давала основные знания чтобы перевести код вручную (http://jmeter-plugins.org/wiki/WebDriverSampler/?utm_source=jmeter&utm_medium=helplink&utm_campaign=WebDriverSampler).
Я воспользовался вторым способом.
Скрипт для тестирования нагрузки
В конечном виде выходит примерно такой скрипт:
var pkg = JavaImporter(org.openqa.selenium)
var support_ui = JavaImporter(org.openqa.selenium.support.ui.WebDriverWait)
var wait = new support_ui.WebDriverWait(WDS.browser, 5000)
WDS.sampleResult.sampleStart()
WDS.browser.get('http://192.168.0.92/jeikei/magazin/')
var search_string = WDS.browser.findElement(pkg.By.name('search_string'))
search_string.sendKeys(['тестовый товар'])
var search = WDS.browser.findElement(pkg.By.name('search'))
search.click()
var bb1 = WDS.browser.findElement(pkg.By.cssSelector('#add2 > span'))
bb1.click()
var bb2 = WDS.browser.findElement(pkg.By.id('add4'))
bb2.click()
var bb3 = WDS.browser.findElement(pkg.By.cssSelector('#add8 > span'))
bb3.click()
var bb4 = WDS.browser.findElement(pkg.By.xpath('//div[@onclick="setQuantity(\'12\', \'up\')"]'))
bb4.click()
bb4.click()
bb4.click()
var bb5 = WDS.browser.findElement(pkg.By.id('add13'))
bb5.click()
var bb6 = WDS.browser.findElement(pkg.By.cssSelector('#add12 > span'))
bb6.click()
var bb7 = WDS.browser.findElement(pkg.By.linkText('Ваша корзина'))
bb7.click()
var fg89 = WDS.browser.findElement(pkg.By.cssSelector('#checkout > span'))
fg89.click()
var bb37 = WDS.browser.findElement(pkg.By.linkText('Заказ без регистрации'))
bb37.click()
var bb53 = WDS.browser.findElement(pkg.By.id('payment_id_94'))
bb53.click()
var fname = WDS.browser.findElement(pkg.By.name('first_name'))
fname.sendKeys(['test'])
var sname = WDS.browser.findElement(pkg.By.name('last_name'))
sname.sendKeys(['test'])
var email = WDS.browser.findElement(pkg.By.name('email'))
email.sendKeys(['Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.'])
var phone = WDS.browser.findElement(pkg.By.name('cell_phone'))
email.sendKeys(['1111111111111'])
var dstate = WDS.browser.findElement(pkg.By.id('delivery_state_id_71704'))
var cont = WDS.browser.findElement(pkg.By.id('continue'))
cont.click()
WDS.sampleResult.sampleEnd()
Этот скрипт запускается в Web Driver Sampler и устанавливается значение клиентов в Thread Groups. Запускать лучше в «тихом» режиме, чтобы не расходовать оперативку на запуски Firefox. Нагрузку можно запустить с нескольких компьютеров одновременно.
О результатах тестирования интернет-магазина мы расскажем в следующей статье.