Monday, 21 April 2014

PhantomJS embedder for Selenium GhostDriver

There is quite a few Drivers for Selenium2/WebDriver. Two of them are particulary interesting, because they allow fast headless browser tests - HtmlUnitDriver and PhantomJSDriver.

Using HtmlUnitDriver is piece of cake, because HtmlUnit is pure java library, but disadvantage is limited JavaScript execution support, making it usable for mostly static html sites only.

PhantomJSDriver from GhostDriver project allows to employ PhantomJS, which is a headless WebKit, much much closer to real web browser. As native binary having it's dependencies staticaly linked, PhantomJS does not need any installation. Just unzip it somewhere.

Selenium 2 has annoying habit of needing to specify full path to browser binary when Driver instace is being created. For most common browsers like Chrome or Firefox, some basic discovery is performed, but it usualy fails for me and it is same story with PhantomJS now.

Most probably, you will get folowing exception

java.lang.IllegalStateException: The path to the driver executable must be set by the phantomjs.binary.path capability/system property/PATH variable; for more information, see https://github.com/ariya/phantomjs/wiki. The latest version can be downloaded from http://phantomjs.org/download.html
 at com.google.common.base.Preconditions.checkState(Preconditions.java:177)
 at org.openqa.selenium.phantomjs.PhantomJSDriverService.findPhantomJS(PhantomJSDriverService.java:237)
 at org.openqa.selenium.phantomjs.PhantomJSDriverService.createDefaultService(PhantomJSDriverService.java:182)
 at org.openqa.selenium.phantomjs.PhantomJSDriver.<init>(PhantomJSDriver.java:99)

Another obstacle usualy is different Operating System between developer's machine (MacOS, Windows) and continuous integration server (Linux). Because PhantomJS is native application, therefore every OS needs it's own binary to execute and you'll need to distribute right versions to every host that will ever build/test your project.

To escape from both annoyances, I've created Phanbedder. Tiny library that bundles PhantomJS binaries and unpacks right one for you on any of supported platform - Linux, Windows and Mac OSX.


File phantomjs = Phanbedder.unpack(); //Phanbedder to the rescue!
DesiredCapabilities dcaps = new DesiredCapabilities();
dcaps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, phantomjs.getAbsolutePath());
PhantomJSDriver driver = new PhantomJSDriver(dcaps);

//Usual Selenium stuff follows
try {
 driver.get("https://www.google.com");
 WebElement query = driver.findElement(By.name("q"));
 query.sendKeys("Phanbedder");
 query.submit();
 Assertions.assertThat(driver.getTitle()).contains("Phanbedder");
} finally {
 driver.quit();
}

To run code above you'll need following dependencies. Number 1.9.7. in artifactId stands for PhantomJS version bundeled inside.

    
      net.anthavio
      phanbedder-1.9.7
      1.0.0
    

    
      com.github.detro.ghostdriver
      phantomjsdriver
      1.1.0
    

Because this library is targeting various OSes, testing is tricky. I have tested it on Mac OS X 10.6, Windows 7 and I've also gave it a spin on travis-ci (good) and Cloudbees Jenkins (great). Source code is hosted on GitHub and deployed into maven central again using Cloudbees Cloud@DEV

Happy Phanbedding!

No comments:

Post a Comment