Bundling ChromeDriver with your test code

This post will just exemplify one way of maintaining the chrome drivers used for running automated tests with WebDriver and the Chrome browser without having to update and install the ChromeDriver to all possible nodes where tests will be running. The ChromeDriver will simply be bundled with the running tests and put under source control as for all other test ware.

Downloading links
http://code.google.com/p/selenium/wiki/ChromeDriver

Bundling
Start by putting the the drivers under the resource folder so that they will be picked up by Maven per default.

<project root>/src/main/resources/chromedriver/mac/chromedriver
<project root>/src/main/resources/chromedriver/windows/chromedriver.exe

Implementation
There are of course different drivers for different OS types and this needs to be handled using the os.name system property.

As per the ChromeDriver usage instructions (here) a system property has to be set pointing to the ChromeDriver server to use for the Chrome browser bridging. We will not point to a fixed location in the file system, instead well get the path by using the Class.getResource which will enable us to bundle ChromeDriver inside our test framework even if it is bundled into a jar file.

Basically what should be done are the following steps.

  • Determine OS type
  • Get the Chrome Driver resource and make sure it is executable using File.setExecutable(true). This is due to when packaged in a jar the execution attributes ‘x’ will be removed on Mac (and assumed on Linux too).
  • Set the “web driver.chrome.driver” system property.
  • Check that a Chrome installation exists in the default location [OPTIONAL]
private static WebDriver driver = null;
// The ChromeDriver locations under the resource folder
private static String MAC_DRIVER = "/chromedriver/mac/chromedriver";
private static String WINDOWS_DRIVER = "/chromedriver/windows/chromedriver.exe";

public static void setupChromeDriver() {
   // OS type
   if (System.getProperty("os.name").contains("Mac")) {
      File cDriver = new File(Tester.class.getResource(MAC_DRIVER).getFile());

      // Is it executable
      if (!cDriver.canExecute()) {
         cDriver.setExecutable(true);
      }
      System.setProperty("webdriver.chrome.driver", Tester.class.getResource(MAC_DRIVER).getFile());

      // Now checking for existence of Chrome executable.'
      if (!new File("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome").exists()) {
         throw new RuntimeException(errorMessage);
      }
   } else {
      System.setProperty("webdriver.chrome.driver", Tester.class.getResource(WINDOWS_DRIVER).getFile());

      // Now checking for existence of Chrome executable.'
      if (!new File(System.getProperty("user.home") + "/AppData/Local/Google/Chrome/Application/chrome.exe").exists()) {
         throw new RuntimeException(errorMessage);
      }
   }

   ChromeOptions options = new ChromeOptions();
   options.addArguments("--start-maximized");
   options.addArguments("--ignore-certificate-errors");
   driver = new ChromeDriver(options);
}

Test case example
Pretty straight on from here, setup WebDriver through the implemented method above and run a simple open page test to see that things worked out.

private static WebDriver driver = null;
public static void setupChromeDriver(){
   ...
}

@BeforeClass
public static void setupTestClass() throws Exception {
   setupChromeDriver();
}

@Test
public void demoTestCase() throws Exception {
   driver.get("http://code.google.com/p/selenium/wiki/ChromeDriver");
   Thread.sleep(1000);
}
Advertisements

Extending WebTest for FitNesse and Selenium

WebTest is Selenium wrapper used in FitNesse test cases. It contains a number of methods that makes it easy to write GUI based test. However it only supports a limited number of methods (WebTest reference) and in most cases there is a need for tweaking these or simply adding new ones.

Extending the com.neuri.webfixture.WebTest class should be a simple thing to do if it had not been for the private Selenium instance attribute.

This short post will describe an approach for how to be able to extend the com.neuri.webfixture.WebTest class, the example is based on webtestfixtures version 2.01.

Using reflection to get the selenium instance

For all calls to the Selenium RC API to work the Selenium instance hidden in the super class needs to be used. This instance can only be fetched using reflection. Add the method below to your extending class and you will get access to the Selenium instance simply by calling getSeleniumInstance()


protected Selenium getSeleniumInstance() {
  try {
    Field privateInstance = com.neuri.webfixture.WebTest.class.getDeclaredField("instance");
    privateInstance.setAccessible(true);
    Selenium seleniumInstance = (Selenium) privateInstance.get(this);
    return seleniumInstance;
  } catch (NoSuchFieldException ndfe) {
    // Do nothing!
  } catch (IllegalAccessException iae) {
    // Do nothing!
  }
  return null;
}

Usage example
Retrieve the Selenium instance and you have access to the Selenium RC API, in the example below getTitle().


public class UnitTHWebTest extends com.neuri.webfixture.WebTest {
  protected Selenium getSeleniumInstance() {...}

  public boolean pageContainsTitleText(String text) {
    Selenium si = getSeleniumInstance();
    if (si.getTitle().equalsIgnoreCase(text)) {
      return true;
    } else {
      return false;
    }
  }
}

Download from: