By Kohsuke Kawaguchi There has always been some overlap between Hudson users and Selenium users. As a result, the support for Selenium in Hudson, such as the Selenium Grid plugin, has generally been good. But while this Selenium Grid support, for example, does make it easier for you to run cross-platform, cross-browser tests, setting up the right OS/browser combinations, especially in the environment that doesn’t use virtualization, can be tedious.
This is where Sauce OnDemand comes into play. Sauce OnDemand solves this problem by offering browsers running in the cloud. But these browsers need to be able to talk to the web server being tested, which is most likely inside a firewall. Although Sauce OnDemand offers a SSH port forwarding option to handle this, setting up and and then tearing them down (or keeping them going all the time) is time consuming, especially when you are running your tests on a CI server that spans across multiple computers.
I wrote the new “Sauce OnDemand” plugin to fix this problem. With this plugin, Hudson will set up and tear down tunnels automatically for you.
Once you install a plugin from Hudson’s update center, go to the system configuration and specify your Sauce OnDemand credential:
Then, for each job that uses Sauce OnDemand, tell Hudson to set up SSH tunnels before the build. Hudson will tear them down at the end of the build.
Your projects don't need anything in their build scripts to do this, which saves a lot of time if you have multiple projects/modules that use Sauce OnDemand. This also avoids the complexity of maintaining a persistent connection, which has its own complications. SSH tunnels on Sauce OnDemand starts very quickly, normally about 10 seconds, so the impact of this to the total build time is minimal.
Host name auto-allocation
Once you start using Sauce OnDemand extensively in Hudson, you’ll notice one problem. Normally you hard-code the host name that browsers connect to (which points to the cloud side of the tunnel and then forwards it back into your intranet to your webapp), but if you do that, you won’t be able to run such tests concurrently on Hudson, since the tunnel setting is global to your account. In other words, imagine hard-coding your test to send HTTP requests to “example.org”, and you have two active branches of that project in development now. If the builds of those branches happen to run at the same time, their tunnel setup collides! In the Hudson plugin, I added a mechanism to let Hudson auto-generate a unique host name when it sets up a tunnel. To do this, specify “AUTO” where you normally specify the domain name (“example.org” in the above example). Hudson will generate a random host name and make that host name available as the environment variable named SAUCE_ONDEMAND_HOST. Your test should then look up this value and pass it to Selenium when you connect to it.
Under the hood
The implementation of this is done in two parts. First I wrote a library that performs SSH tunnel setup and tear down, and then I wrote a Hudson plug-in around it. The former is reusable on its own, and would be useful if you want to take the same idea and apply it elsewhere other than Hudson. My next post will talk more about this library, so stay tuned! Kohsuke Kawaguchi, the creator of Hudson, wrote the majority of Hudson's core single-handedly. He is a founder of InfraDNA, which provides products, services, and support for Hudson.