Using Selenium Chrome Driver on Mac OS X

Update (26/06/2015)
Previously I have written a function which waits until a specific element is available on the page, doWhenAvailable. I have find out Selenium has already a similar feature build-in. Its element search functions could wait until an element is available on the page. It can be activated in @BeforeClass method:

driver. manage( .timeouts( ). implicitlyWait(TIMEOUT_TIME,  TimeUnit.SECONDS) ;
//doWhenAvailable(driver, By.id( “view_profile”), WebElement::click); 
driver.findElement(By.id(“view_profile”)).click() ;

 

It took several attempts for me able to use Chrome Driver by using the instructions from its website and I have decided to publish a step by step tutorial.

Selenium allows you to run your tests using several different browsers Chrome, Firefox, InternetExplorer and HTMLUnit. HTMLUnit is not a real browser it is just a browser simulator written in Java, it can execute JavaScript too. Some settings you have to use for each one is different but for all of them you have to start by adding main Selenium dependency to you project. This is the common part.

Creating Maven Project

I have created a new maven project using following pom.xml but you can just add selenium dependency to your own pom.xml if you want. Here is the pom.xml file I have used for my test project:

 

<!--?xml version="1.0" encoding="UTF-8"?-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0</modelversion>
    <groupid>com.deniz.jira</groupid>
    <artifactid>JIRASeleniumTests</artifactid>
    <version>1.0</version>
    <name>JIRASeleniumTests</name>
    <dependencies>
        <!-- This is only required dependency. -->
        <dependency>
            <groupid>org.seleniumhq.selenium</groupid>
            <artifactid>selenium-java</artifactid>
            <version>2.46.0</version>
        </dependency>
        <!-- Selenium does not enforce any unit testing framework and
        it does not have any unit testing features, like asserts so
        we are using JUnit for this. But this is optional and
        you do not need to use any unit testing library if you want. -->
        <dependency>
            <groupid>junit</groupid>
            <artifactid>junit</artifactid>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupid>org.hamcrest</groupid>
            <artifactid>hamcrest-all</artifactid>
            <version>1.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <!-- Using Java 8's Lambda expressions makes code simple.
        Because you will be using a lot of handler to asynchronous methods.
        But this is not required. -->
        <plugins>
            <plugin>
                <groupid>org.apache.maven.plugins</groupid>
                <artifactid>maven-compiler-plugin</artifactid>
                <version>3.3</version>
                <configuration>
                    <source>1.8
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

WebDriver Specific Initialization

For newcomers it is best to stick with Firefox. It is easier to setup. After installing Firefox browser to you system just create a new FirefoxDriver and start running your project. There are no extra step required.

For Chrome in addition to Chrome Browser you have to install Chrome Driver too. You can download Chrome Driver from Chromium web site and put it in a suitable place in your system. Location is not important because we will be providing location of it through a system property to our test execution.

In my case I have put chromedriver executable to Applications folder. So for my JUnit test I have use following setting:

System.setProperty("webdriver.chrome.driver" ,  "/Applications/chromedriver");

Writing Actual Test Codes

We have to initialize our WebDriver instance, since I am using JUnit I have done it in @BeforeClass so it is automatically run before my test cases. You can also do this before every test case using @BeforeTest but it will be a lot slower because you will most probably do extra initialization than shown below. For example logging-in to web site.

@BeforeClass
public static void init() {
    driver = new ChromeDriver(); //init chrome driver
    //driver = new FirefoxDriver(); //uncomment to use Firefox
    driver.get("http://localhost:8080”); //url of website we like to test
    driver.manage().window().setSize(new Dimension(1600, 900)); //resize browser window
    //login to web site
}

You will most probably want browser to automatically closed after your tests are completed. Add driver.quit() to your JUnit teardown method. If you do not each execution will left a new browser window open.

@AfterClass
public static void teardown() {
    driver.quit();
}

Nowadays nearly all web applications will be loaded asynchronously. That mean when page is loaded the element you like to test will not be on the page, it will be generated by a JavaScript code. This makes writing test a little more difficult, you have to wait until related element is created by JavaScript code. I have writing a small helper function and reused it in my test code. It waits until given element (Specified using By) is available on the page and execute the given code block (Consumer) when the element is available:

public   static   void   doWhenAvailable( WebDriver driver ,  By by ,  Consumer consumer )   { 
     ( new   WebDriverWait (driver,  TIMEOUT_TIME ) ).until( ( WebDriver drv )   -&gt;  driver.findElement( by )  !=  null ) ; 
    consumer.accept( driver.findElement( by ) ) ; 
 }

 

Using this method with Java 8 is very readable. For example below code waits until an element with id=“view_profile” is available on the page and when it is available just clicks on it.

doWhenAvailable(driver, By.id("view_profile"), WebElement::click);

Following code performs more complex operation when requested element is available. It wails until <select id=“ts_month_picker_selector” …..> select element is available on the page and select option element which has a value of “Jan”:

doWhenAvailable(driver, By.id("ts_month_picker_selector"), (element) -&gt; {
    Select select = new Select(element);
    select.selectByValue(String.valueOf(“Jan"));
});

You will mostly need to perform other asynchronous operations inside the callback and this will result into callback hell. I am still looking a way to promise style of chaining asynchronous operations.

Tips and Tricks

  • Give every HTML element a unique id field. This will allow you to specify elements easily in your test code.
  • Create a reusable small test library specific to your application. For example you should encapsulate logging-in to test system in a method and reuse that method from every test case.
  • Try to avoid time based waits with Thread.sleep() or any other sleep as much as possible. Because they will increate time to run your tests. But you will probably need this for some AJAX based code. In my case I need it for dynamically filled comboboxes which fills its content as you type. Otherwise you may get StaleElementReferenceException because your driver will be using a previous instance of the same visual element not the one on the page. Instead of sleep you may allow StaleElementReferenceException to occur and re-fetch the element automatically. You can check details from here.
  • At the end of the test if test fails take a screenshot automatically. I will explain it in another post. 
Using Selenium Chrome Driver on Mac OS X, 7.7 out of 10 based on 3 ratings