BrowserMob Proxy + Selenium: автоматизация сбора данных о производительности
BrowserMob Proxy это бесплатная утилита, которая позволяет собирать данные о производительности веб-сайтов и браузеров. Обычно используется вместе с инструментальными средствами автоматизации, такими как Selenium или Watir. Proxy позволяет управлять поведением браузера, имитировать сетевой трафик и задержки, изменять HTTP запросы и ответы. К востребованной функциональности также можно отнести использование «черного» и «белого» списков, что позволяет, например, блокировать загрузку сторонних сайтов, не относящихся к тестированию Вашего веб-приложения, и тем самым повысить скорость тестов.
Также довольно часто BrowserMob используется для автоматизации доступа к сайтам, требующим Basic авторизацию.
Управлять прокси-сервером можно напрямую через Java интерфейс или через REST API. В этой статье мы будем рассматривать только интересующий нас Java интерфейс. Для того, чтобы подключить BrowserMob в проект нужно скачать библиотеку и добавить ее в проект, либо добавить соответствующую зависимость в pom.xml, если вы используете Maven:
net.lightbody.bmp browsermob-proxy 2.0-beta-8 test
Если у Вас уже имеется подключенная в проект библиотека Selenium, то лучше исключить использование Selenium API, встроенного в BrowserMob. Но при этом учитывайте возможные несоответствия версий Selemium и BrowserMob:
net.lightbody.bmp browsermob-proxy 2.0-beta-8 test org.seleniumhq.selenium selenium-api
Java реализация BrowserMob представлена в виде набора классов, основной из которых net.lightbody.bmp.proxy.ProxyServer.
Пример запуска прокси-сервера с FirefoxDriver и сбора данных загрузки страницы:
import net.lightbody.bmp.core.har.Har; import net.lightbody.bmp.proxy.ProxyServer; import org.junit.Test; import org.openqa.selenium.Proxy; import org.openqa.selenium.WebDriver; import org.openqa.selenium.firefox.FirefoxDriver; import org.openqa.selenium.remote.CapabilityType; import org.openqa.selenium.remote.DesiredCapabilities; public class ProxyServerTest { @Test public void testMobProxyServer() throws Exception { // запуск прокси сервера ProxyServer server = new ProxyServer(4444); server.start(); // получение Selenium proxy Proxy proxy = server.seleniumProxy(); // конфигурация FirefoxDriver для использования прокси DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(CapabilityType.PROXY, proxy); WebDriver driver = new FirefoxDriver(capabilities); // создание HAR с меткой "yandex.ru" server.newHar("yandex.ru"); // открытие страницы driver.get("http://yandex.ru"); // получение данных HAR Har har = server.getHar(); // здесь будет обработка полученных данных driver.quit(); server.stop(); } }
Вывод в консоль свидетельствует об успешном запуске и остановке прокси-сервера на 4444 порту:
HttpSer~ - Version Jetty/5.1.x Contain~ - Started HttpContext[/,/] SocketL~ - Started SocketListener on 0.0.0.0:4444 Contain~ - Started net.lightbody.bmp.proxy.jetty.jetty.Server@133321d6 Threade~ - Stopping Acceptor ServerSocket[addr=0.0.0.0/0.0.0.0,port=0,localport=4444] SocketL~ - Stopped SocketListener on 0.0.0.0:4444 Contain~ - Stopped HttpContext[/,/] Contain~ - Stopped net.lightbody.bmp.proxy.jetty.jetty.Server@133321d6
HAR
BrowserMob Proxy предоставляет полученную им информацию в HAR (HTTP Archive) формате. Этот формат используется инструментами мониторинга HTTP для выгрузки собранных данных. Фактически HAR формат представляет из себя JSON структуру данных в кодировке UTF-8, которую можно просматривать и анализировать использую различные HAR визуализаторы.
После того как в тесте мы получили данные HAR их можно сохранить физически в виде файла:
// получение данных HAR Har har = server.getHar(); // обработка полученных данных try { File file = new File("results\\Test.har"); if (!file.exists()) { file.createNewFile(); } FileOutputStream fos = new FileOutputStream(file); try { har.writeTo(fos); } finally { fos.close(); } } catch (IOException e) { // обработка ошибки e.printStackTrace(); } finally { driver.quit(); server.stop(); }
Обновив проект Вы увидите сохраненный файл Test.har в папке results (папка была предварительно создана перед запуском).
Полученный HAR файл содержит JSON данные, которые можно использовать как текстовую информацию, либо просмотреть в удобном представлении, используя один из существующих онлайн инструментов, например, HTTP Archive Viewer 2.0.15:
Получить интересующую Вас информацию и поместить ее в собственный отчет можно и без сохранения HAR файла. Java класс net.lightbody.bmp.core.har.HarLog предоставляет набор методов для выборочного получения нужной информации:
Har har = server.getHar(); // получить информацию о браузере System.out.println(har.getLog().getBrowser().getName()); System.out.println(har.getLog().getBrowser().getVersion()); // список всех обработанных запросов for (HarEntry entry : har.getLog().getEntries()) { System.out.println(entry.getRequest().getUrl()); // время ожидания ответа от сервера в миллисекундах System.out.println(entry.getTimings().getWait()); // время чтения ответа от сервера в миллисекундах System.out.println(entry.getTimings().getReceive()); }
Помимо сбора информации net.lightbody.bmp.proxy.ProxyServer позволяет манипулировать запросами и полученными ответами с помощью добавления интерсепторов запросов и ответов соответственно:
public void addRequestInterceptor(RequestInterceptor interceptor)
public void addResponseInterceptor(ResponseInterceptor interceptor)
Пример интеграции BrowserMob с драйверами ChromeDriver и InternetExplorerDriver:
public class ProxyServerTest { private static ProxyServer server; private static Proxy proxy; @BeforeClass public static void setUpProxy() throws Exception { server = new ProxyServer(4444); server.start(); proxy = server.seleniumProxy(); } @Before public void createNewHar() { server.newHar("yandex.ru"); } /** * ChromeDriver */ @Test public void testChromeDriver() throws Exception { ChromeOptions option = new ChromeOptions(); option.addArguments("--proxy-server=localhost:" + server.getPort()); WebDriver driver = new ChromeDriver(option); driver.get("http://yandex.ru"); driver.quit(); } /** * InternetExplorerDriver */ @Test public void testIEDriver() throws Exception { DesiredCapabilities capabilities = DesiredCapabilities.internetExplorer(); capabilities.setCapability(CapabilityType.PROXY, proxy); capabilities.setCapability("ie.setProxyByServer", true); WebDriver driver = new InternetExplorerDriver(capabilities); driver.get("http://yandex.ru"); driver.quit(); } @After public void saveHAR() throws Exception { Har har = server.getHar(); File file = new File("results\\" + har.getLog().getBrowser().getName() + ".har"); if (!file.exists()) { file.createNewFile(); } FileOutputStream fos = new FileOutputStream(file); try { har.writeTo(fos); } finally { fos.close(); } } @AfterClass public static void stopProxyServer() throws Exception { server.stop(); } }