<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>OpenSourceTester</title>
    <link href="http://opensourcetester.co.uk/feed.xml" rel="self"/>
    <link href="http://opensourcetester.co.uk" />
    <updated>2015-08-12T14:02:45+00:00</updated>
    <id>http://opensourcetester.co.uk/</id>
    <author>
        <name>OpenSourceTester</name>
    </author>
    
    <entry>
        <title>Execute asynchronous JavaScript from Selenium</title>
        <link href="http://opensourcetester.co.uk/2015/08/12/asynchronous-javascript-functions-from-selenium-webdriver"/>
        <updated>2015-08-12T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2015/08/12/asynchronous-javascript-functions-from-selenium-webdriver</id>
        <content type="html">&lt;p&gt;When implementing end user acceptance tests in the browser using &lt;a href=&quot;https://code.google.com/p/selenium&quot;&gt;Selenium-Webdriver&lt;/a&gt; it’s a good idea to follow these rules:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Wherever possible test the site from the perspective of the user i.e. with no access to the internals of the page&lt;/li&gt;
  &lt;li&gt;If you really need some data exposed from JavaScript and made available to the test (that the user wouldn’t see) - have some kind of ‘debug’ mode where JavaScript events are logged to a debug JS object in the page which you can query from Webdriver using synchronous &lt;code&gt;execute_script&lt;/code&gt; calls.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Occasionally however it might be that you can’t add debug objects to the page (it’s not under your control for some reason) and perhaps to know some asynchronous event has occurred it would be useful to, for example, register for an event.&lt;/p&gt;

&lt;p&gt;Until recently I didn’t think this was possible from Selenium…however I was completely wrong!&lt;/p&gt;

&lt;p&gt;I stumbled across this &lt;a href=&quot;http://blog.jthoenes.net/2013/08/16/waiting-for-a-javascript-event-with-seleniumcapybara/&quot;&gt;blog post&lt;/a&gt; which shows you how to do it.&lt;/p&gt;

&lt;p&gt;I thought it was worth expanding a little bit on this with some working examples and more links.&lt;/p&gt;

&lt;p&gt;It turns out there is a method called &lt;code&gt;execute_async_script&lt;/code&gt; which exists in most language bindings.  In the JavaDoc it’s also well documented with &lt;a href=&quot;http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/JavascriptExecutor.html&quot;&gt;example scripts&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have converted one to Ruby so you can prove to yourself this really works. If you run this you should observe the client code blocking until the asynchronous JavaScript has returned.  The Selenium method has an implicit callback (accessed via &lt;code&gt;arguments[arguments.length - 1]&lt;/code&gt;) which we pass as the first argument to the asynchronous &lt;code&gt;setTimeout&lt;/code&gt; JavaScript function. The Benchmark result proves this behaves as expected.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;selenium-webdriver&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;benchmark&amp;#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Selenium&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;WebDriver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:firefox&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;navigate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://www.example.com&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bridge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setScriptTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# needs to be &amp;gt; setTimeout value&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Benchmark&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;realtime&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute_async_script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;window.setTimeout(arguments[arguments.length - 1], 4000);&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;fail&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Times do not match!&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that the &lt;code&gt;setScriptTimeout&lt;/code&gt; method exists in the &lt;a href=&quot;https://github.com/SeleniumHQ/selenium/blob/master/rb/lib/selenium/webdriver/remote/bridge.rb#L144&quot;&gt;bridge&lt;/a&gt; class and so it’s not accessible via the public API in the Ruby Bindings (hence the &lt;code&gt;send&lt;/code&gt; hack). This millisecond value must be higher than the time you think your callback will return in otherwise the method will return and report a timeout.&lt;/p&gt;

&lt;p&gt;For a more tangible example here we register for a custom JavaScript event and accessing some of the event data…you can copy the html to a separate file and run it on your own machine.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;example&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;  &amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;    &amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;      #green-box {&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;        height: 50px;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;        width: 50px;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;        background-color: green;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;      }&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;    &amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;    &amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;      window.onload = function() {&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;        greenBox = document.getElementById(&amp;#39;green-box&amp;#39;);&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;        var myEvent = new CustomEvent(&amp;quot;green-box-click&amp;quot;, {&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;          detail: {&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;            username: &amp;quot;matt&amp;quot;,&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;          },&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;          bubbles: true&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;        });&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;        window.addEventListener(&amp;quot;green-box-click&amp;quot;, function(e) {&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;          document.getElementById(&amp;#39;status&amp;#39;).textContent = &amp;#39;clicked by:&amp;#39; + e.detail[&amp;#39;username&amp;#39;];&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;        })&lt;/span&gt;

&lt;span class=&quot;sh&quot;&gt;        greenBox.onclick = function() {&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;          greenBox.dispatchEvent(myEvent);&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;        }&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;      }&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;    &amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;  &amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;  &amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;    &amp;lt;div id=&amp;#39;green-box&amp;#39;&amp;gt;&amp;lt;span id=&amp;#39;status&amp;#39;&amp;gt;click me&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;  &amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sh&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;no&quot;&gt;example&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;selenium-webdriver&amp;#39;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Selenium&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;WebDriver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:firefox&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;navigate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;file:///home/matt/workspace/selenium-debug/test.html&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:bridge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setScriptTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute_async_script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&amp;quot;var callback = arguments[arguments.length - 1];&lt;/span&gt;
&lt;span class=&quot;s2&quot;&gt;    window.addEventListener(&amp;#39;green-box-click&amp;#39;, function(e) {callback(e.detail[&amp;#39;username&amp;#39;])});&amp;quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;driver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quit&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As Johannes points out in his &lt;a href=&quot;http://blog.jthoenes.net/2013/08/16/waiting-for-a-javascript-event-with-seleniumcapybara/&quot;&gt;blog post&lt;/a&gt; in running such code you have the potential to affect the behaviour of the page under test. Double check that the page functions as expected after your code has executed and be aware of issues such as an event not bubbling correctly up the DOM.&lt;/p&gt;

&lt;p&gt;Hopefully this has given some more insight into executing asynchronous JavaScript from Selenium, certainly not something you would want to do unless you really had to but worth knowing about.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>Rerun failing tests with Cucumber - a solution for nondeterministic UI tests?</title>
        <link href="http://opensourcetester.co.uk/2015/05/13/cucumber-rerun-formatter"/>
        <updated>2015-05-13T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2015/05/13/cucumber-rerun-formatter</id>
        <content type="html">&lt;p&gt;The evolution of acceptance test automation, or at least my experience of it has been something like this:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2005 - 2008&lt;/em&gt; : QA runs automated test on their machine pior to raising deployment ticket&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2009 - 2012&lt;/em&gt; : CI runs automated tests - downstream, everybody ignores them&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2012 - present&lt;/em&gt; : Continuous Delivery…UI tests broken, no deployments…now we have your attention!&lt;/p&gt;

&lt;p&gt;So hopefully you have arrived at stage 3 and have done the following to ensure your UI tests are as resilient as possible:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Followed Martin Fowler’s &lt;a href=&quot;http://martinfowler.com/bliki/TestPyramid.html&quot;&gt;test pyramid&lt;/a&gt; and not implemented every conceivable system test via Selenium&lt;/li&gt;
  &lt;li&gt;Implemented sane retry logic to find UI elements&lt;/li&gt;
  &lt;li&gt;Isolated your UI using stub backends to guard against unexpected data&lt;/li&gt;
  &lt;li&gt;Added spoonfuls of helpful debug logging to highlight issues&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But perhaps a couple of your tests still appear now and again be nondeterministic and people are getting frustrated.&lt;/p&gt;

&lt;p&gt;This can happen, UI testing is hard and no matter how much you defend against it peculiarities of the runtime environment can conspire against you.&lt;/p&gt;

&lt;p&gt;In this instance it might be handy to have ‘one more go’ when you get some failures and Cucumber’s rerun formatter allows this.&lt;/p&gt;

&lt;p&gt;Caveat - generally I would say a nondeterminstic test should either be fixed for good or deleted however sometimes the world is just not that perfect, maybe for example you aren’t able to improve underlying infrastrucre issues etc etc. Hence this may still be a valid course of action.&lt;/p&gt;

&lt;h2 id=&quot;the-example&quot;&gt;The Example&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mcrmfc/cucumber-rerun-example&quot;&gt;This&lt;/a&gt; is about the simplest example I could come up with.&lt;/p&gt;

&lt;p&gt;The test will fail 50% of the time, allowing you to see the rerun kicking in on selected runs.&lt;/p&gt;

&lt;p&gt;You can run the test using &lt;code&gt;bundle exec rake&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The test should be run for a second time if it fails and should terminate with an appropriate exit code.&lt;/p&gt;

&lt;p&gt;You can see some examples of this working in the project’s &lt;a href=&quot;https://travis-ci.org/mcrmfc/cucumber-rerun-example/builds&quot;&gt;Travis&lt;/a&gt; build.&lt;/p&gt;

&lt;h2 id=&quot;other-thoughts&quot;&gt;Other Thoughts&lt;/h2&gt;

&lt;p&gt;Another useful thing might be to run any failing tests from previous CI runs first and you could probably adapt this approach to do just that!&lt;/p&gt;

&lt;h2 id=&quot;credit&quot;&gt;Credit&lt;/h2&gt;

&lt;p&gt;I just thought I would illustrate with an example what others have already highlighted:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.mattheworiordan.com/post/42587188567/automatically-retrying-failing-non-deterministic&quot;&gt;http://blog.mattheworiordan.com/post/42587188567/automatically-retrying-failing-non-deterministic&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://blog.crowdint.com/2011/08/22/auto-retry-failed-cucumber-tests.html&quot;&gt;http://blog.crowdint.com/2011/08/22/auto-retry-failed-cucumber-tests.html&lt;/a&gt;&lt;/p&gt;

</content>
    </entry>
    
    <entry>
        <title>From zero to tested with Centos7, Chrome and Selenium</title>
        <link href="http://opensourcetester.co.uk/2015/01/16/from-zero-to-tested-with-centos7-and-chrome"/>
        <updated>2015-01-16T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2015/01/16/from-zero-to-tested-with-centos7-and-chrome</id>
        <content type="html">&lt;p&gt;If you are restricted to &lt;a href=&quot;http://www.centos.org/&quot;&gt;Centos&lt;/a&gt; in your CI environments and you need to run browser tests previous solutions include running in PhantomJS, an old version of Firefox under Xvfb or farming out to a Selenium Grid.&lt;/p&gt;

&lt;p&gt;With Centos7 you now have another option as Chrome is fully supported on this OS.&lt;/p&gt;

&lt;p&gt;You can easily run a headless (ish…&lt;a href=&quot;http://en.wikipedia.org/wiki/Xvfb&quot;&gt;Xvfb&lt;/a&gt;) Chrome browser.&lt;/p&gt;

&lt;p&gt;Here I show you the bare minimum required to get from nothing to a working example.&lt;/p&gt;

&lt;p&gt;Once you have it working you would need to consider repeatability e.g. provisioning the environment via something like Puppet, spinning it up in a Docker container or maybe just a simple script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grab a Centos 7 VM&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;vagrant init matyunin/centos # a good community base image at time of writing&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;vagrant up&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;vagrant ssh&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;as-root&quot;&gt;As root&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Add google yum repo&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; /etc/yum.repos.d/google-chrome.repo&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[google-chrome]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;name=google-chrome - \$basearch&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;baseurl=http://dl.google.com/linux/chrome/rpm/stable/\$&lt;/span&gt;basearch
&lt;span class=&quot;go&quot;&gt;enabled=1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;gpgcheck=1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;as-vagrant&quot;&gt;As vagrant&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Install dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;sudo yum install -y ruby ruby-devel gcc xorg-x11-server-Xvfb google-chrome-stable&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;gem install selenium-webdriver headless&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;version=`curl -s http://chromedriver.storage.googleapis.com/LATEST_RELEASE`&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;curl -s &amp;quot;http://chromedriver.storage.googleapis.com/$version/chromedriver_linux64.zip&amp;quot; &amp;gt; chromedriver.zip&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;unzip chromedriver.zip &amp;amp;&amp;amp; sudo mv chromedriver /usr/local/bin/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Create test script&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;cat &amp;lt;&amp;lt; EOF &amp;gt; test.rb&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;require &amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;require &amp;#39;headless&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;require &amp;#39;selenium-webdriver&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;headless = Headless.new&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;headless.start&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;driver = Selenium::WebDriver.for :chrome&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;driver.navigate.to &amp;#39;http://google.com&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;puts driver.title&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;headless.destroy&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;EOF&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;run-test&quot;&gt;Run test&lt;/h2&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;ruby test.rb&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;celebrate&quot;&gt;Celebrate!&lt;/h2&gt;
</content>
    </entry>
    
    <entry>
        <title>Selenium 141 - Alternatives to BrowserMob Proxy</title>
        <link href="http://opensourcetester.co.uk/2013/08/15/selenium-141-browsermob-proxy-alternatives"/>
        <updated>2013-08-15T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2013/08/15/selenium-141-browsermob-proxy-alternatives</id>
        <content type="html">&lt;h2 id=&quot;selenium-issue-141&quot;&gt;Selenium Issue 141&lt;/h2&gt;

&lt;p&gt;The long story of &lt;a href=&quot;https://code.google.com/p/selenium/issues/detail?id=141&quot;&gt;Selenium Issue 141&lt;/a&gt; is not worth recounting here as it has been covered in depth by Selenium core committers &lt;a href=&quot;http://blog.rocketpoweredjetpants.com/2013/06/the-unix-philosophy-webdriver-and-http.html&quot;&gt;Simon Stewart&lt;/a&gt; and &lt;a href=&quot;http://www.theautomatedtester.co.uk/blog/2013/the-tale-of-selenium-bug-141.html&quot;&gt;David Burns&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a nutshell issue 141 is a hotly contested debate as to whether Selenium-Webdriver should provide public API for querying HTTP status codes and response headers.&lt;/p&gt;

&lt;p&gt;I pretty much agree with the Selenium guys and can see how introducing this API would be the start of a very long and slippery slope for the project. However in the day to day work of an automation developer it is often essential to have access this information, for example most Web Apps have to do some kind of tracking which takes the form of a request for a 1x1 image with a query string containing the tracking key value pairs and we are frequently asked to validate these calls.&lt;/p&gt;

&lt;h2 id=&quot;browsermob---the-solutionmaybe&quot;&gt;BrowserMob - the solution….maybe&lt;/h2&gt;

&lt;p&gt;The conventional wisdom is that you should use the Selenium approved scriptable proxy &lt;a href=&quot;http://bmp.lightbody.net/&quot;&gt;BroweserMob Proxy&lt;/a&gt; to get around this problem.&lt;/p&gt;

&lt;p&gt;Up until recently I followed this thinking and had used BrowserMob with reasonable success (see my earlier post about &lt;a href=&quot;http://opensourcetester.co.uk/2012/01/04/browsermob-through-proxy/&quot;&gt;using BrowserMob through a proxy&lt;/a&gt;, however I had never had to use it in a critical CI pipeline and when I did things got a little less appealing.&lt;/p&gt;

&lt;p&gt;There is no doubt that BrowserMob is a great project but using it via the &lt;a href=&quot;https://github.com/jarib/browsermob-proxy-rb&quot;&gt;Ruby bindings&lt;/a&gt; I found that all too often the Java process would not shut down cleanly after a test run (particularly if the test run failed for some other reason) meaning that on subsequent runs the port was locked and the proxy would not restart.&lt;/p&gt;

&lt;p&gt;All these problems are solvable of course and I intend to keep using BrowserMob and contribute any fixes if I can.&lt;/p&gt;

&lt;p&gt;However for the project I was on I needed something bullet proof which limited the amount of moving parts in my CI pipeline to capture and validate tracking calls from a mediaplayer.&lt;/p&gt;

&lt;h2 id=&quot;browser-extensions---an-alternative-approach&quot;&gt;Browser Extensions - an alternative approach…&lt;/h2&gt;

&lt;p&gt;These trials took me to an alternative approach - browser extensions!&lt;/p&gt;

&lt;p&gt;Starting with Chrome I knocked together an extension that uses the &lt;a href=&quot;http://developer.chrome.com/extensions/webRequest.html&quot;&gt;chrome.webRequest&lt;/a&gt; api to capture network requests and push them back into the page under test via local storage.  I then raise custom events which the page under test can register for.&lt;/p&gt;

&lt;p&gt;Of course this assumes you are in control of the page under test, in my case I was testing a component on a test page so that was fine, I listened for the custom events and pushed them out into the DOM so I could scrape them using Selenium as normal.  If this is not the case for you (which is likely) I think you could still use this solution, for example by updating the extension to push the events into a global object which you could query by injecting JavaScript from Selenium.  Of course this is not an uber-clean but no solution in this area is!&lt;/p&gt;

&lt;p&gt;I won’t go into the code as you can have a &lt;a href=&quot;https://github.com/mcrmfc/chrome-netscraper&quot;&gt;play for yourself&lt;/a&gt;, it turns out to be very simple and of course it is a bullet proof and fast way of capturing this information. &lt;/p&gt;

&lt;h2 id=&quot;but-what-about-the-other-browsers&quot;&gt;But what about the other browsers?&lt;/h2&gt;

&lt;p&gt;Of course this only addresses Chrome…to compete with BrowserMob we need to be able to cover as many of the other browsers supported by Selenium.&lt;/p&gt;

&lt;p&gt;For this I used &lt;a href=&quot;http://crossrider.com/&quot;&gt;Crossrider&lt;/a&gt; which provides a limited api but allows you to generate extensions for Chrome, Firefox, IE and Safari.&lt;/p&gt;

&lt;p&gt;You cannot be as sophisticated as you can using the Chrome APIs directly but you can still accomplish a fair amount.&lt;/p&gt;

&lt;p&gt;Again feel free to have a play around with the simple &lt;a href=&quot;https://github.com/mcrmfc/crossrider-netscraper&quot;&gt;crossrider extension&lt;/a&gt; I wrote to scrape net requests.&lt;/p&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions…&lt;/h2&gt;

&lt;p&gt;There is no ‘right’ way of dealing with the lower level aspects of web automation. In some cases using BrowserMob makes perfect sense and should be your go to solution.  However if you need a resilient way of capturing net requests, blocking net requests, accessing response codes or headers then a browser extension might just be the way to go.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>Building Erlang-r16 and Elixir on OSX using HomeBrew</title>
        <link href="http://opensourcetester.co.uk/2013/08/06/erlangr16-osx"/>
        <updated>2013-08-06T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2013/08/06/erlangr16-osx</id>
        <content type="html">&lt;p&gt;A quick one just in case anybody is struggling to build Erlang-r16 on OSX. I wanted to play around with &lt;a href=&quot;http://elixir-lang.org&quot;&gt;Elixir&lt;/a&gt; the latest and slightly more offbeat (dare I say hipster) functional language to hit the big time, Elixir runs on the Erlang VM and you need Erlang-r16 to build and run Elixir.&lt;/p&gt;

&lt;p&gt;To install Erlang-r16 on OSX using &lt;a href=&quot;http://brew.sh/&quot;&gt;homebrew&lt;/a&gt; you in theory just need to add the &lt;a href=&quot;https://github.com/Homebrew/homebrew-versions&quot;&gt;homebrew-versions&lt;/a&gt; tap and brew install:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;brew tap homebrew/versions&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install erlang-r16&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However I got compile errors when running the install (note I think this may be even specific to the latest MacBooks with the new Haswell chips).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;erl -noshell -noinput -run prepare_templates gen_asn1ct_rtt \&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           asn1rtt_check.beam asn1rtt_ext.beam asn1rtt_per_common.beam asn1rtt_real_common.beam asn1rtt_ber.beam asn1rtt_per.beam asn1rtt_uper.beam &amp;gt;asn1ct_rtt.erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;erlc -W  +debug_info -I/private/tmp/erlang-r16-HFuS/otp-OTP_R16B/lib/stdlib -Werror -o../ebin asn1ct_rtt.erl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Running Erlang&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;asn1ct_rtt.erl:1: syntax error before: Running&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;asn1ct_rtt.erl:14: no module definition&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;make[2]: *** [../ebin/asn1ct_rtt.beam] Error 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;make[1]: *** [opt] Error 2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;make: *** [secondary_bootstrap_build] Error 2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The reason for this is that newer Macs with the latest versions of X-Code use &lt;a href=&quot;http://llvm.org/releases/2.9/docs/CommandGuide/html/llvmgcc.html&quot;&gt;LLVM-GCC&lt;/a&gt; and not &lt;a href=&quot;http://gcc.gnu.org/&quot;&gt;GNU GCC&lt;/a&gt;.  Homebrew now attempts to build with LLVM by default which is probably sensible as this is the platform compiler, however it is likely for a fair number of packages this won’t work as their builds have not been tested on LLVM.  This seems to be the case with the latest Erlang versions.&lt;/p&gt;

&lt;p&gt;The additional problem at the moment seems to be that the Homebrew project is currently changing the way they handle the situation around cross compiling with different C compilers.&lt;/p&gt;

&lt;p&gt;You can use the &lt;a href=&quot;https://github.com/Homebrew/homebrew-versions&quot;&gt;homebrew-versions&lt;/a&gt; tap to install a specific gcc e.g.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;brew tap homebrew/versions&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install gcc48&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However in Homebrew 0.9.4 at least there seems to be no way of telling it to use these GCC versions when building. You can specify &lt;code&gt;--use-gcc&lt;/code&gt; or set the HOMEBREW_CC environment variable but neither worked for me.  &lt;a href=&quot;https://github.com/Homebrew/homebrew-versions/issues/142&quot;&gt;This issue&lt;/a&gt; got me thinking as the only success people had seemed to have is where they had the apple-gcc42 compiler.&lt;/p&gt;

&lt;p&gt;When you do &lt;code&gt;export HOMEBREW_CC=gcc&lt;/code&gt; Homebrew seems to be hardcoded to look for the apple-gcc42 package and not any from the homebrew-versions tap.  I think &lt;a href=&quot;https://github.com/mxcl/homebrew/pull/20251&quot;&gt;this pull request&lt;/a&gt; will make this integration smoother.&lt;/p&gt;

&lt;p&gt;For the time being then, to get a working Elixir and Erlang do the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;export HOMEBREW_CC=gcc&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew update&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew tap homebrew/dupes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install apple-gcc42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install erlang-r16&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install elixir&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can probably avoid exporting HOMEBREW_CC and just use (but I haven’t tested this method):&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;brew update&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew tap homebrew/dupes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install apple-gcc42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install --use-gcc erlang-r16&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;brew install elixir&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This gets the 4.2 GCC that currently Homebrew is hardcoded to look for, indeed you can see this if you run &lt;code&gt;brew --config&lt;/code&gt; as it now lists a GCC-4.2 value which would have been absent before:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;HOMEBREW_VERSION: 0.9.4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;ORIGIN: https://github.com/mxcl/homebrew&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;HEAD: 6b5b347332f7fdad35a5deab79fa71018e02a2b4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;HOMEBREW_PREFIX: /usr/local&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;HOMEBREW_CELLAR: /usr/local/Cellar&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;CPU: quad-core 64-bit haswell&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;OS X: 10.8.4-x86_64&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Xcode: 4.6.3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;CLT: 4.6.0.0.1.1365549073&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;GCC-4.2: build 5666&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;LLVM-GCC: build 2336&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Clang: 4.2 build 425&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;X11: N/A&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;System Ruby: 1.8.7-358&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Perl: /usr/bin/perl&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Python: /usr/bin/python&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Ruby: /Users/matthewrobbins/.rbenv/shims/ruby&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

</content>
    </entry>
    
    <entry>
        <title>Git Clone via SSH using Jenkins on Windows</title>
        <link href="http://opensourcetester.co.uk/2013/06/28/jenkins-windows-ssh"/>
        <updated>2013-06-28T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2013/06/28/jenkins-windows-ssh</id>
        <content type="html">&lt;p&gt;This blog post is nothing revolutionary but more of a note to self so that I never have to learn this painful lesson again!&lt;/p&gt;

&lt;p&gt;My current team has Windows specific CI dependencies, hence I had no choice but to setup our Jenkins instance on Windows.  The cleanest way to do this is to use the &lt;a href=&quot;https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins+as+a+Windows+service&quot;&gt;Jenkins Installer&lt;/a&gt; which installs Jenkins as a Windows Service.&lt;/p&gt;

&lt;p&gt;That works fine, but of course the first challenge you face is cloning your Git repo over SSH (the default for the Jenkins Git plugin).&lt;/p&gt;

&lt;p&gt;I’ll assume you have done the following:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Installed &lt;a href=&quot;https://code.google.com/p/msysgit/downloads/list&quot;&gt;Git Client&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Created &lt;a href=&quot;https://help.github.com/articles/generating-ssh-keys#platform-windows&quot;&gt;SSH Keys&lt;/a&gt; and ensured that you can successfully clone a repo from your Git Bash (running as current user).&lt;/p&gt;

    &lt;p&gt;Note: In theory you should not use passwordless keys as anybody obtaining your key will have access to your account.  However for Jenkins you cannot have a password as the Job would hang when attempting to clone.  From Git Bash this problem is solved using &lt;a href=&quot;https://help.github.com/articles/working-with-ssh-key-passphrases#platform-windows&quot;&gt;ssh-agent&lt;/a&gt; but this won’t work in Jenkins as we are using the Git plugin and not the shell.&lt;/p&gt;

    &lt;p&gt;Bottom line - for Jenkins use a passwordless key - you can mitigate the risk by having a dedicated Jenkins Git User and only allowing them pull access.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Set up the Git plugin in Jenkins via ‘Manage Jenkins’ and point it to the Git cmd file on the system, as in the screenshot below:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/images/jenkins_git_plugin.png&quot; alt=&quot;jenkins_git_plugin&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now we get to the tricky part.  When Jenkins runs as a Windows Service it does not run under a normal user account, it runs under the “Local System Account”.  Hence even though you have Git Clone working as the current user it will fail in Jenkins.&lt;/p&gt;

&lt;p&gt;To solve this problem we need to put our private ssh key in the correct location for the Local System Account.&lt;/p&gt;

&lt;p&gt;First of all we need to find out where this user’s home directory is, since it will not exist under C:\Users…&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Download &lt;a href=&quot;http://download.sysinternals.com/files/PSTools.zip&quot;&gt;PSTools&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Extract to a conventiant location and using a command prompt navigate to that location (or add to path if you prefer)&lt;/li&gt;
  &lt;li&gt;Start the PsExec tool by running:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;PsExec.exe -i -s cmd.exe&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Now we need to find out where this user’s home directory is:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;echo %userprofile%&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;For me this location was:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;C:\Windows\system32\config\systemprofile&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Now you can open Git Bash within this shell by running the following command:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;C:\Program Files (x86)\Git\bin\sh –login –i&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;You can copy your existing private key into the correct location for the Local System User, for me this was something like the following:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;cd ~&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;cp /c/Users/matt/.ssh/id_rsa ~/.ssh/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;Finally you can test that you can successfully authenticate to Github as the Local System User:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;ssh -T git@github.com&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;If all is successful you should see the usual message:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;Hi username! You&amp;#39;ve successfully authenticated, but GitHub does not provide shell access.&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All that’s left to do now is test from Jenkins…Huzzah!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>3DES Zeros Padding with Ruby and Openssl</title>
        <link href="http://opensourcetester.co.uk/2012/11/29/zeros-padding-3des-ruby-openssl"/>
        <updated>2012-11-29T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2012/11/29/zeros-padding-3des-ruby-openssl</id>
        <content type="html">&lt;p&gt;Although many encryption libraries exist for Ruby (and here I am talking ‘C’ Ruby in the main) you will most typically want to use &lt;a href=&quot;http://openssl.org&quot;&gt;Openssl&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently I needed to encrypt a simple JSON string using 3DES (ECB mode).  &lt;/p&gt;

&lt;p&gt;IMPORTANT - You should never use ECB mode it is insecure and highly prone to brute force attacks….but I had no choice this is what the external service required.&lt;/p&gt;

&lt;p&gt;It all seemed so simple and my initial script looked something like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;openssl&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;base64&amp;#39;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;json&amp;#39;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;#CIPHER&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;des&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;OpenSSL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Cipher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Cipher&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;des-ede3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;yourchosendeskey&amp;#39;&lt;/span&gt; 

&lt;span class=&quot;c1&quot;&gt;#ENCRYPTION&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encrypt&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;edata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;{&amp;quot;somekey&amp;quot;:&amp;quot;somevalue&amp;quot;}&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;b64data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Base64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#remove EOL insterted in Base64 encoding&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Although this worked perfectly in my local test harness the external PHP service failed to decrypt the data.  The reason for this is all to do with padding.&lt;/p&gt;

&lt;p&gt;Certain encryption schemes (such as 3DES) are known as &lt;a href=&quot;http://en.wikipedia.org/wiki/Block_cipher&quot;&gt;‘Block Cipers’&lt;/a&gt; and operate on a fixed block size i.e. in order for the data to encrypt/decrypt successfully it must be presented as a multiple of the required block size (in this case 8 bytes).&lt;/p&gt;

&lt;p&gt;Openssl ensures this by inserting PKCS#5 padding, this padding scheme is preferred because it can be easily be distinguished from the actual data and allows for basic integrity or password checking.&lt;/p&gt;

&lt;p&gt;Sadly (and possibly unsuprisingly) the PHP library I was integrating with did not use Openssl and instead used MCRYPT which uses ‘Zeros Padding’ and not PKCS#5.&lt;/p&gt;

&lt;p&gt;Openssl does not support Zeros Padding out of the box but you can do this yourself by telling Openssl not to pad the data and ensuring the data is a multiple of the block size by adding ‘/0’ characters at the end of the data, the code looks something like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;#ENCRYPTION&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;block_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;padding&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#Tell Openssl not to pad&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encrypt&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;{&amp;quot;somekey&amp;quot;:&amp;quot;somevalue&amp;quot;}&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\0&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;until&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bytesize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block_length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;#Pad with zeros&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;edata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;des&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final&lt;/span&gt; 
&lt;span class=&quot;n&quot;&gt;b64data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Base64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsub&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;IMPORTANT - you should choose a much better encryption scheme and padding mechanism, but if you really have to integrate with some ‘interesting’ PHP this may help!&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>Setting two space indent for Gherkin Features in Vim</title>
        <link href="http://opensourcetester.co.uk/2012/11/26/two-level-gherkin-indent-vim"/>
        <updated>2012-11-26T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2012/11/26/two-level-gherkin-indent-vim</id>
        <content type="html">&lt;p&gt;Users of Vim (or GVim, Macvim etc) who write &lt;a href=&quot;https://github.com/cucumber/cucumber/wiki/Gherkin&quot;&gt;Gherkin Feature files&lt;/a&gt; will know that for most installations (on Mac certainly) you appear to have auto-magical support for Gherkin Feature file syntax i.e. nice colours, auto format etc.&lt;/p&gt;

&lt;p&gt;This is possible because the distribution of Vim installed on the machine, or which you installed comes shipped with Tim Pope’s excellent &lt;a href=&quot;https://github.com/tpope/vim-cucumber&quot;&gt;vim-cucumber plugin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If your Vim does not ship with this you should most certainly install it right away!&lt;/p&gt;

&lt;p&gt;I have always auto-indented using gg=G and never really thought too much about the indent level.  It turns out that presently the vim-cucumber plugin does not specify this (although I note that it is commented out in the source at the bottom of the &lt;a href=&quot;https://github.com/tpope/vim-cucumber/blob/master/syntax/cucumber.vim&quot;&gt;syntax file&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;My vimrc defines this globally as follows:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;set expandtab&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set tabstop=4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;set shiftwidth=4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So of course I was getting 4 level indent in my feature files.&lt;/p&gt;

&lt;p&gt;The current team I am working with was not keen on this and I can see their point it does seem excessive, 2 would seem more than enough and in fact is what is used in the examples on &lt;a href=&quot;http://cukes.info&quot;&gt;cukes.info&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So how best to do this?&lt;/p&gt;

&lt;p&gt;One option would be to navigate to the file relevant to your Vim install location:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;#&lt;/span&gt;Examples
&lt;span class=&quot;go&quot;&gt;/Applications/MacVim-snapshot-64/MacVim.app/Contents/Resources/vim/runtime/syntax/cucumber.vim&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/usr/share/vim/vim73/syntax/cucumber.vim&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And change this line:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;&amp;quot; vim:set sts=2 sw=2:&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;set sts=2 sw=2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a hack though (when you reinstall vim this change would be lost) and will need to be done for all copies of vim on the machine.&lt;/p&gt;

&lt;p&gt;The answer is to use Vim’s ftplugin functionality.&lt;/p&gt;

&lt;p&gt;First of all you need to switch this on in your vimrc, adding the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;filetype plugin indent on&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The you have two options, firstly you can create a file ‘~.vim/after/ftplugin/cucumber.vim’ and add the following:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;setlocal expandtab&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;setlocal shiftwidth=2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;setlocal softtabstop=2&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Or add the config directly into your .vimrc:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;au FileType cucumber setl sw=2 sts=2 et&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is obviously common knowledge to experienced Vim users but may be useful for anybody out there who is relatively new to Vim and wants to customize syntax on a per language basis in a clean way.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>Cucumber and the global scope problem - bring on page objects and the MGF pattern</title>
        <link href="http://opensourcetester.co.uk/2012/08/06/cucumber-page-object-global"/>
        <updated>2012-08-06T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2012/08/06/cucumber-page-object-global</id>
        <content type="html">&lt;p&gt;There is no argument, &lt;a href=&quot;http://cukes.info&quot;&gt;Cucumber&lt;/a&gt; has added a new dimension to acceptance testing, Gherkin Features are &lt;strong&gt;living executable requirements&lt;/strong&gt; and that for me is the benefit we should never loose sight of.&lt;/p&gt;

&lt;p&gt;So you’ve clocked this and created a bunch of automated tests driven from you’re features….but can too much Gherkin be a problem?&lt;/p&gt;

&lt;p&gt;In my experience it can and it’s something you need to keep a close eye on to avoid you’re tests becoming as big a maintenance burden as the application code.&lt;/p&gt;

&lt;h2 id=&quot;the-global-scope-problem&quot;&gt;The Global Scope Problem&lt;/h2&gt;

&lt;p&gt;For a project with just a few features you can quite happily get away with a project structure that looks something like that below. All your steps in a single file containing the automation code for your features.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;/~features/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ /~step-definitions/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /-steps.rb&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ /-example1.feature&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ /-example2.feature&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ /~support/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /-env.rb/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is fine for a small project, but let’s say you get above 10-15 scenarios, soon the steps file will become very big and you will start spreading steps over a few files with roughly representative names. Then you run headfirst into the ‘Global Scope Problem’….&lt;/p&gt;

&lt;p&gt;Cucmber has the concept of a &lt;a href=&quot;https://github.com/cucumber/cucumber/wiki/a-whole-new-world&quot;&gt;‘World’ object&lt;/a&gt;, a kind of giant mixin which allows your Features, Steps and Support files to share context through the use of Ruby instance variables (the ones preceded by @ characters).  Whilst this is essential to the functioning of Cucumber it is also our enemy.  &lt;/p&gt;

&lt;p&gt;As you’re project grows this shared scope can cause chaos, an IDE or editor that understands Cucumber syntax will help, but ultimately you will have features mapping to steps which could be in any steps file and where state can be affected by any other step in any file via instance variables.&lt;/p&gt;

&lt;p&gt;This can end up as mess of procedural spaghetti.&lt;/p&gt;

&lt;h2 id=&quot;the-page-object-solution-and-the-mgf-pattern&quot;&gt;The Page Object solution and the MGF Pattern&lt;/h2&gt;

&lt;p&gt;An excellent &lt;a href=&quot;http://blog.josephwilk.net/cucumber/page-object-pattern.html&quot;&gt;blog post&lt;/a&gt; by Joseph Wilk got me thinking seriously about this when I was working on a project which was being bitten hard by the global scope problem.  Integrating the Page Object Pattern into your Cucumber tests is really your only option for containing the problem of global scope.&lt;/p&gt;

&lt;p&gt;At this point I am going to introduce what I am calling the MGF pattern, which stands for ‘Model, Glue, Feature’.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Model - You’re page objects&lt;/li&gt;
  &lt;li&gt;Glue - The step definitions&lt;/li&gt;
  &lt;li&gt;Feature - The Gherkin Features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Page Object Pattern will be familiar to most of those reading this blog so I won’t go over it again.  However I will suggest the following ‘Golden Rules’.  I have adapted these from Simon Stewart’s &lt;a href=&quot;http://code.google.com/p/selenium/wiki/PageObjects#Summary&quot;&gt;wiki page&lt;/a&gt; on the Selenium site because as with most things he has it nailed:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;PageObject methods return other PageObjects or Self (whenever a page load is triggered)…&lt;/li&gt;
  &lt;li&gt;Assertions should nearly always be in the Glue (step defs) not Page Objects (exception - ‘correct location’ check)&lt;/li&gt;
  &lt;li&gt;Different results for the same action are different methods (‘save_expecting_error’, ‘save_expecting_submit’)&lt;/li&gt;
  &lt;li&gt;Never call steps from steps (add helpers to objects if compounding steps are needed)&lt;/li&gt;
  &lt;li&gt;Have a hash of element locators in each PageObject (or register &lt;a href=&quot;https://github.com/jnicklas/capybara/#xpath-css-and-selectors&quot;&gt;custom locators&lt;/a&gt; with Capybara)&lt;/li&gt;
  &lt;li&gt;NEVER pollute test code with page internals i.e. no css xpath in test code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Page objects possess all the knowledge about the application under test, the Glue simply binds the objects to the Gherkin features.&lt;/p&gt;

&lt;p&gt;If you follow this pattern I would expect you to end up with a project layout something like that below.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;/~features/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ /~examples/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /~step-definitions/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / / /-steps.rb&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /-signin.feature&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /-dashboard.feature&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ /~support/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /-env.rb/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / /~objects/&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / / /-signin.rb&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;/ / / /-dashboard.rb&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;intergrating-capybara&quot;&gt;Intergrating Capybara&lt;/h2&gt;

&lt;p&gt;Many people including myself like using Capybara and so it is worth noting how to integrate this into your Page Objects. Because Page Objects will live outside the Cucumber ‘World’ then you have to options available:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Include the Capybara::DSL module in you’re page objects&lt;/li&gt;
  &lt;li&gt;Pass around an instance of a Capybara Session&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The advantage of the first method is that you only have to do this in a ‘base’ class which all other objects can inherit from and obtain those methods,  the advantage of the second method is that you could potentially pass in a mock if you wanted to unit test you’re page objects (though the value of doing this is debatable and could fill an entire blog post).&lt;/p&gt;

&lt;p&gt;Below is an example base class page object which may help get you started. In this example @session is an instance of an object which acts as a container for our current page and is the only variable that couples the step definitions (or Glue) it also acts as a way of storing data that needs to persist across a test run e.g. user.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GenericPage&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Capybara&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DSL&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Capybara&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Matchers&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RSpec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Matchers&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:url&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@session&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;correct_page?&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;should&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;have_css&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ELEMENTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;page check element&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;element_exists?&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_selector?&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ELEMENTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;current_url&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;page&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_url&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SigninPage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;GenericPage&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;LOCATION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://myapp.com/signin&amp;#39;&lt;/span&gt;

  &lt;span class=&quot;no&quot;&gt;ELEMENTS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;page check element&amp;#39;&lt;/span&gt;            &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;.myapp-signin &amp;gt; h1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;page check value&amp;#39;&lt;/span&gt;              &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Weclcome to MyApp&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;username&amp;#39;&lt;/span&gt;                      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;#username&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;password&amp;#39;&lt;/span&gt;                      &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;#password&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;save&amp;#39;&lt;/span&gt;                          &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;#submit_button&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;session&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;visit&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Capybara&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visit&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LOCATION&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;signin_expecting_success&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signin&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;DashboardPage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;signin_expecting_error_using&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unique&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;signin&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;SigninErrorPage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;kp&quot;&gt;private&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;signin&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fill_in&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ELEMENTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;username&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:with&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;username&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fill_in&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ELEMENTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;password&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:with&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@session&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;click_on&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ELEMENTS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;save&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;Adding Page Objects and following the MGF pattern will help you combat the ‘Global Scope’ problem that can hit on large projects using Cucumber to drive automated tests.  It will mean changes can be isolated to single points in the code and add logical structure which will reduce the maintenance burden.&lt;/p&gt;

&lt;h2 id=&quot;update&quot;&gt;Update…&lt;/h2&gt;

&lt;p&gt;I have just finshed reading some excellent posts on &lt;a href=&quot;http://www.natontesting.com/&quot;&gt;Nathaniel Ritmeyer’s blog&lt;/a&gt; which elaborate on how we can &lt;a href=&quot;http://www.natontesting.com/2012/05/31/managing-your-page-objects/&quot;&gt;manage page objects&lt;/a&gt; thus tackling the issues of step coupling. He also maintains &lt;a href=&quot;http://www.natontesting.com/2012/07/30/siteprism-1-3/&quot;&gt;SitePrism&lt;/a&gt; which looks like an interesting dsl for page objects (and removes the need for the ugly constants I have in the examples above).&lt;/p&gt;

&lt;p&gt;Anyway I think I will follow up this post in a couple of months and elaborate on the issues around coupling in our glue code and how best we can minimize what is one of the major problems with Cucumber.&lt;/p&gt;
</content>
    </entry>
    
    <entry>
        <title>Passing parameters to a downstream Hudson (Jenkins) job</title>
        <link href="http://opensourcetester.co.uk/2012/08/03/pass-parameters-hudson"/>
        <updated>2012-08-03T00:00:00+00:00</updated>
        <id>http://opensourcetester.co.uk/2012/08/03/pass-parameters-hudson</id>
        <content type="html">&lt;p&gt;I wanted to run an acceptance test in a downstream job.  However I needed to grab the value of a build parameter from the upstream job.  It turns out Hudson (Jenkins) does not support this ‘out of the box’.&lt;/p&gt;

&lt;p&gt;You can add a &lt;a href=&quot;http://wiki.hudson-ci.org/display/HUDSON/Parameterized+Trigger+Plugin&quot;&gt;plugin&lt;/a&gt;, however this was going to cause a time delay in my environment as I did not have admin rights to do this.&lt;/p&gt;

&lt;p&gt;So a thought struck me…trigger the downstream job from the shell in the upstream and use the REST API.&lt;/p&gt;

&lt;p&gt;Now this is all fine and to be fair there is &lt;a href=&quot;http://wiki.hudson-ci.org/display/HUDSON/Remote+access+API&quot;&gt;reference&lt;/a&gt; on the Hudson wiki but it is not totally obvious.&lt;/p&gt;

&lt;p&gt;You can’t do a get with a query string it needs to be a POST with params, below is an example using curl.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-console&quot; data-lang=&quot;console&quot;&gt;&lt;span class=&quot;go&quot;&gt;json=&amp;quot;{\&amp;quot;parameter\&amp;quot;: [{\&amp;quot;name\&amp;quot;: \&amp;quot;NAMESPACE\&amp;quot;, \&amp;quot;value\&amp;quot;: \&amp;quot;test\&amp;quot;}, {\&amp;quot;name\&amp;quot;: \&amp;quot;ENVIRONMENT\&amp;quot;, \&amp;quot;value\&amp;quot;: \&amp;quot;production\&amp;quot;}], \&amp;quot;\&amp;quot;: \&amp;quot;\&amp;quot;}&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;url=&amp;quot;https://ci.mysite.co.uk/hudson/job/mysite-acceptance-tests/build&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;curl -X POST $url -d token=FRAMEWORKS --data-urlencode json=&amp;quot;$json&amp;quot; -k -E &amp;quot;/data/certs/mycert.pem&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You’ll notice you need the security token in order to run this. This can be set in the upstream job ‘Configure &amp;gt; Trigger Builds Remotely &amp;gt; Authentication Token’&lt;/p&gt;

&lt;p&gt;The funny thing is I did all of this and then realised the version of curl on the Red Hat 5 system I was on didn’t support –data-urlencode, luckily –data sufficed for my needs.&lt;/p&gt;
</content>
    </entry>
    
</feed>
