<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[QA Automation in Action]]></title><description><![CDATA[Useful Java-oriented articles for QAA engineers]]></description><link>https://sskorol.github.io</link><image><url>/images/back.jpg</url><title>QA Automation in Action</title><link>https://sskorol.github.io</link></image><generator>RSS for Node</generator><lastBuildDate>Wed, 01 Nov 2017 18:55:21 GMT</lastBuildDate><atom:link href="https://sskorol.github.io/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Tracking tests' network statistics with Docker]]></title><description><![CDATA[<div class="sect1">
<h2 id="_browsermob_proxy_docker_image">Browsermob Proxy Docker image</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To be able to use the following example, you&#8217;ll need to build <a href="https://github.com/sskorol/docker-browsermob-proxy" target="_blank">docker-browsermob-proxy</a> first. This base Docker image contains latest (2.1.1) <a href="https://github.com/lightbody/browsermob-proxy">Browsermob Proxy (BMP)</a> version.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_docker_configuration">Docker configuration</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Raising newly built image would be quite simple with a help of <code>docker-compose</code>. Here&#8217;s a sample BMP / Selenium Grid configuration, which will help you to link all containers together:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>seleniumhub:
 image: sskorol/hub:2.53.1
 ports:
 - "4444:4444"
firefoxnode:
 image: sskorol/node-firefox-debug:2.53.1
 volumes:
 - ~/Work:/e2e/uploads
 - ~/Work/tmp:/e2e/uploads/tmp
 ports:
 - "5900"
 expose:
 - "80"
 links:
 - seleniumhub:hub
chromenode:
 image: sskorol/node-chrome-debug:2.53.1
 volumes:
 - ~/Work:/e2e/uploads
 - ~/Work/tmp:/e2e/uploads/tmp
 ports:
 - "5900"
 expose:
 - "80"
 links:
 - seleniumhub:hub
browsermobproxy:
 image: sskorol/browsermob-proxy:2.1.1
 ports:
 - "9090-9191:9090-9191"
 expose:
 - "9090-9191"
 links:
 - seleniumhub:hub_sel
 - firefoxnode:node_ff
 - chromenode:node_ch</pre>
</div>
</div>
<div class="paragraph">
<p>If you missed my <a href="http://qa-automation-notes.blogspot.com/2016/04/docker-selenium-and-bit-of-allure-how.html">article</a> about <code>docker-selenium</code> customization, you can pull above images from appropriate <a href="https://github.com/sskorol/docker-selenium">fork</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_har_viewer">HAR viewer</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To provide extensive network statistics in test results reports, we&#8217;ll use one of the best <a href="http://www.softwareishard.com/blog/har-viewer">HAR Viewer</a>, which supports really nice embedded mode.</p>
</div>
<div class="paragraph">
<p>Java implementation requires both front-end and backend involvement. You may already know that <a href="http://allure.qatools.ru">Allure</a> supports <code>html</code> attachments. To be able to use embedded HAR Viewer, we need to create our own template first. This could be done using <a href="https://github.com/spullara/mustache.java">mustache</a> library.</p>
</div>
<div class="paragraph">
<p>Template may look like the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-html" data-lang="html">&lt;!DOCTYPE HTML&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;link rel="stylesheet" href="../styles.css"&gt;
    &lt;link rel="stylesheet" href="css/spinner.css"&gt;
    &lt;script src="https://code.jquery.com/jquery-2.1.4.min.js"
            integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=" crossorigin="anonymous"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="js/har-viewer.js"&gt;&lt;/script&gt;
    &lt;script&gt;
        $(window).load(function() {
            $(".se-pre-con").fadeOut("slow");;
        });
    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="loader" class="se-pre-con"&gt;&lt;/div&gt;
&lt;div class="har" data-har="{{link}}" height="{{height}}px"&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
</div>
</div>
<div class="paragraph">
<p>Where <code>har-viewer.js</code> is the official script for HAR Viewer embedding.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-javascript" data-lang="javascript">(function () {
    var har = document.createElement("script");
    har.src = "http://www.softwareishard.com/har/viewer/har.js";
    har.setAttribute("id", "har");
    har.setAttribute("async", "true");
    document.documentElement.firstChild.appendChild(har);
})();</code></pre>
</div>
</div>
<div class="paragraph">
<p>Note that <code>{{link}}</code> is a mandatory reference to the HAR file, produced while test execution. I left <code>{{height}}</code> option configurable as well, as default value is quite low, and you may want to manage it by yourself depending on screen resolution.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_har_storage">HAR storage</h2>
<div class="sectionbody">
<div class="paragraph">
<p>A bit painful topic. I&#8217;ve already played with <a href="https://github.com/pavel-paulau/harstorage">harstorage</a> project, but it seems quite unstable with latest version of BMP, and requires pretty old software dependencies.</p>
</div>
<div class="paragraph">
<p>To avoid dependencies hell and configuration overhead, we&#8217;ll use much easier approach. Produced HAR files will be stored on a lightweight Web Server, e.g. <a href="https://www.lighttpd.net">lighttpd</a>, and then referenced in code while HAR template generation.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_rest_browsermob_proxy_client">REST Browsermob Proxy client</h2>
<div class="sectionbody">
<div class="paragraph">
<p>To establish connection with <code>docker-browsermob-proxy</code> image via REST we need to find out its internal IP address first. Here&#8217;s a script, which could help us:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-bash" data-lang="bash">#!/bin/bash
PROXY_NAME=`docker ps --format {{.Names}} | grep 'proxy'`
IP=`docker inspect --format {{.NetworkSettings.IPAddress}} $PROXY_NAME`
echo $IP</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we execute it from java code, we&#8217;ll be able to access remote BMP instance running in Docker container.</p>
</div>
<div class="paragraph">
<p>REST client is available on <a href="https://github.com/sskorol/browsermob-proxy-rest">GitHub</a>. So you may want to build it first before moving to next parts.</p>
</div>
<div class="paragraph">
<p>To simplify interaction with proxy there was created a <a href="https://github.com/sskorol/docker-selenium-samples/blob/master/src/main/java/com/blogspot/notes/automation/qa/core/ProxyServer.java">ProxyServer</a> wrapper, which allows establishing connection with a remote server. As I&#8217;ve mentioned above, IP address is exposed dynamically, but default port (9090) is consumed from <a href="https://github.com/sskorol/docker-selenium-samples/blob/master/src/test/resources/properties/config.properties">config.properties</a>.</p>
</div>
<div class="paragraph">
<p>After new BMP instance creation we need to obtain a port, which will be used by <code>WebDriver</code>. Now we&#8217;re ready to send a request on HAR file creation.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java" data-lang="java">this.browserMobProxy = new BrowsermobProxyRestClient(this.ip, port);
this.port = browserMobProxy.getPort();
this.browserMobProxy.setPort(this.port);
this.browserMobProxy.newHar(this.initialPageId, true, true, true);</code></pre>
</div>
</div>
<div class="paragraph">
<p>That&#8217;s all we need for getting Selenium Proxy instance.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java" data-lang="java">public Proxy getSeleniumProxy() {
	final String actualProxy = ip + ":" + port;
	return new Proxy().setHttpProxy(actualProxy).setFtpProxy(actualProxy).setSslProxy(actualProxy);
}</code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_har_files_processing">HAR files processing</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Depending on proxy server location, network configuration and HAR size, it could take long to retrieve recorded network statistics. To avoid wasting time on HAR processing, we&#8217;ll supply it async via <code>CompletableFuture</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java" data-lang="java">CompletableFuture.supplyAsync(() -&gt; proxy.getBrowserMobProxy().getHarAsString())
	.whenComplete((har, err) -&gt; {
		if (saveHar(HTTPD_DIR + File.separator + harName, har))
			attachHtml(attachmentName, HAR_TEMPLATE, getScope(harAddress, HAR_VIEW_HEIGHT));
		proxy.disposeProxy();
	});</code></pre>
</div>
</div>
<div class="paragraph">
<p>If HAR file is successfully saved in a shared httpd folder, we&#8217;ll use Allure annotations to perform custom html attachment.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlightjs highlight"><code class="language-java" data-lang="java">@Attachment(value = "{0}", type = "text/html")
public static byte[] attachHtml(String name, String templateName, Map&lt;String, Object&gt; args) {
	String outName = "target" + File.separator + "attachment" + COUNTER.incrementAndGet();
	try {
		execute(templateName, outName, args);
		return toByteArray(new File(outName));
	} catch (Exception ignored) {
		return new byte[0];
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>That&#8217;s pretty much it. <a href="https://github.com/sskorol/docker-selenium-samples">docker-selenium-samples</a> contains extensive examples working with proxy / video recording in Docker containers.</p>
</div>
<div class="paragraph">
<p>And here&#8217;s produced output demo:</p>
</div>
<div class="videoblock">
<div class="content">
<iframe width="640" height="480" src="https://www.youtube.com/embed/oxanT-d48N0?rel=0" frameborder="0" allowfullscreen></iframe>
</div>
</div>
</div>
</div>]]></description><link>https://sskorol.github.io/2016/07/18/Tracking-tests-network-statistics-with-Docker.html</link><guid isPermaLink="true">https://sskorol.github.io/2016/07/18/Tracking-tests-network-statistics-with-Docker.html</guid><category><![CDATA[browsermob-proxy]]></category><category><![CDATA[webdriver]]></category><category><![CDATA[allure]]></category><category><![CDATA[docker]]></category><category><![CDATA[harviewer]]></category><category><![CDATA[java]]></category><category><![CDATA[testng]]></category><dc:creator><![CDATA[Sergey Korol]]></dc:creator><pubDate>Mon, 18 Jul 2016 00:00:00 GMT</pubDate></item></channel></rss>