Мар 192016
 

BrowserMob Proxy + Selenium: автоматизация сбора данных о производительности

BrowserMob Proxy это бесплатная утилита, которая позволяет собирать данные о производительности веб-сайтов и браузеров. Обычно используется вместе с инструментальными средствами автоматизации, такими как Selenium или Watir. Proxy позволяет управлять поведением браузера, имитировать сетевой трафик и задержки, изменять запросы и ответы. К востребованной функциональности также можно отнести использование «черного» и «белого» списков, что позволяет, на, блокировать загрузку сторонних сайтов, не относящихся к тестированию Вашего веб-приложения, и тем самым повысить скорость тестов.
Также довольно часто 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 с драйверами и :

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();
    }
}

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)