tech corner v1

Many automated testing suites built on Selenium WebDriver rely on locally stored driver executable files to run tests in a web browser. This works fine, until your web browser updates itself automatically, and suddenly you find that your web browser’s version and your web browser’s driver version are out of sync, resulting in an error message like below (in this example I’m using Chrome version 83, and ChromeDriver version 81):

Exception in thread "main" org.openqa.selenium.SessionNotCreatedException: 
    session not created: This version of ChromeDriver only supports Chrome version 81
 

You know the drill... Now you need to go out and download the latest driver version, update your master branch, send out a message to your team members to update their browsers, update your CI machines' browsers (if you have them), etc.

I say enough! Time spent updating web browsers and driver files is time wasted (if you disagree, I might suggest some new hobbies). Let's solve this problem.

Using the WebDriverManager library to keep driver files updated

Web browser driver files are traditionally stored somewhere in the testing suite project code itself. Below is an example of a basic WebDriver factory class that uses driver files stored in the project's resources directory:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

public class WebDriverFactory {

    private static final String DRIVER_DIR = "src/test/resources/";

    public static WebDriver getWebDriver(String browserName) {
        switch (browserName.toLowerCase()) {
            case "chrome":
                return getChromeDriver();
            case "firefox":
                return getFirefoxDriver();
            case "internet explorer":
                return getInternetExplorerDriver();
            default:
                throw new IllegalArgumentException("Match case not found for browser: " 
                        + browserName);
        }
    }

    private static WebDriver getChromeDriver() {
        System.setProperty("webdriver.chrome.driver", DRIVER_DIR + "chromedriver.exe");
        return new ChromeDriver();
    }

    private static WebDriver getFirefoxDriver() {
        System.setProperty("webdriver.gecko.driver", DRIVER_DIR + "geckodriver.exe");
        return new FirefoxDriver();
    }

    private static WebDriver getInternetExplorerDriver() {
        System.setProperty("webdriver.ie.driver", DRIVER_DIR + "IEDriverServer.exe");
        return new InternetExplorerDriver();
    }
}
 

As mentioned above, this works fine until the version of the driver executable is no longer compatible with the version of the web browser being used. So how do we fix this?

The solution I've found utilizes the WebDriverManager library created by GitHub user bonigarcia. WebDriverManager will automatically select and download the correct driver file for the version of the web browser that tests are being executed on. Using the WebDriverManager library is straightforward. Start by adding the library to your project. My project uses Maven and I'll be using WebDriverManager version 4.0.0 (the latest at the time of writing), so I'm going to add the following dependency to my POM file:

        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>4.0.0</version>
            <scope>test</scope>
        </dependency>
 

Next, I'm going to modify my WebDriverFactory.java class methods to use WebDriverManager to handle my driver files. Below is an example with the "old way" intentionally commented out. Notice that I am no longer referencing any locally stored driver files in my code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    private static WebDriver getChromeDriver() {
//        System.setProperty("webdriver.chrome.driver", DRIVER_DIR + "chromedriver.exe");
        WebDriverManager.chromedriver().setup();
        return new ChromeDriver();
    }

    private static WebDriver getFirefoxDriver() {
//        System.setProperty("webdriver.gecko.driver", DRIVER_DIR + "geckodriver.exe");
        WebDriverManager.firefoxdriver().setup();
        return new FirefoxDriver();
    }

    private static WebDriver getInternetExplorerDriver() {
//        System.setProperty("webdriver.ie.driver", DRIVER_DIR + "IEDriverServer.exe");
        WebDriverManager.iedriver().setup();
        return new InternetExplorerDriver();
    }
 

That's all there is to it. WebDriverManager will check the version of your web browser, and then download and use the correct driver file automatically.

If you want to pass option arguments to the browsers, you can do so as you normally would:

1
2
3
4
5
6
    private static WebDriver getChromeDriver() {
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        WebDriverManager.chromedriver().setup();
        return new ChromeDriver(options);
    }
 

Additional note: I recently came across a problem where WebDriverManager was not selecting the correct driver version on some Jenkins VMs (WebDriverManager was working fine on my local machine). I don't know what caused this, but clearing the WebDriverManager resolution cache before launching the browser fixed the issue for me:

1
2
3
4
    private static WebDriver getChromeDriver() {
        WebDriverManager.chromedriver().clearResolutionCache().setup();
        return new ChromeDriver();
    }

Stay tuned for more automation tips and tricks in our Technology Corner!

We love sharing best practices with the test automation community.  Check out my previous post on how to view multiple JUnit Assertion Errors in a single test execution.

tapQA is here to help! Contact us as we'd love to help you maximize your test automation efforts!

Jared H

Jared Hoernemann

Jared Hoernemann is a Senior Automation Engineer specializing in designing and coding test automation scripts and frameworks from the ground up, as well as mentoring other developers. Jared designs, implements, and executes automated tests for web browsers, APIs of all kinds, and databases.

Have a QA question?

Our team would love to help!

Invalid Email