Browser unaware Selenium tests. STEP 2: Creating the browser initialization methods for Chrome and Firefox

Published by

on

In this second post of the ‘browser unaware Selenium tests’ series, i will show what the methods that start Chrome and Firefox look like, based on the selected OSs from the previous post.

2. Starting the browser

Once the drivers needed in the test project were downloaded and stored in the project, the browser related methods can be created. This chapter focuses on creating methods for starting the browsers and closing them. It makes sense for all these methods to be in the same place. Therefore a browser dedicated class should be created, which will hold the start/close and other browser related methods that will be used across the test project.

2.1. Hardcoding the browser versus not

Whenever you write Selenium tests, one of the first steps in each test represents opening the browser. Ideally you want to be able to run the same test on several browsers seamlessly. You don’t normally want to have a test configured in such a way that it only runs on one browser. That means you need to have a way of generating a browser instance based on a parameter you will provide when the test starts to run, for those cases when you want to run the same test on different browsers.

There might be situations when you do need to only run the test on one specified browser. Such situations might include: the application you are testing only runs on that browser, as per the requirements; there is a bug in another browser or in the test framework for a specific browser, and you cannot run certain test steps except on another, specified browser; your requirement clearly specifies what browser to test on and it is the only one required. For this scenario, you will hardcode the browser in the test. 

If you have no requirement which restricts you to running tests on just one browser, than you should use the approach of not hardcoding the browser in the test. The good news is that, if, let’s say you want to run a test on 3 different browsers, you don’t need to write 3 tests, one for each browser. Instead you will write the test not taking into account what the browser is. You are only interested in the test steps, and what actually needs to be done in a test. The test will be ‘browser unaware’.  

A dedicated class will be created for storing all the methods which start up the browser. In this class, called ‘BrowserGetter’, you will find a method for starting up the Chrome browser (named ‘getChromeDriver()’). If your test requires you to only use Chrome in the test class, you will call this ‘getChromeDriver()’ method, which will start your Chrome browser. In the same class, ‘BrowserGetter’, you will also find a method for starting up the Firefox browser (named ‘getFirefoxDriver()’), which you will call from a test where Firefox is the mandatory browser to be used. These are explained in subchapter 2.2.

For those tests where you won’t hardcode the browser, a method called ‘getDriver()’ can also be found in the ‘BrowserGetter’ class. Based on a System property that you can change before running any test, it allows you to create an instance of a browser corresponding to the value of the System property.

2.2. Creating the methods for starting the specific browsers

Whether you want to hardcode the browser in the tests or not, you will need a method for starting each browser. 

For now, in this subchapter, the methods for starting the Chrome and the Firefox browsers are described. The ‘BrowserGetter’ demoed here can be found at: https://github.com/iamalittletester/selenium-tutorial/blob/master/src/main/java/browser/BrowserGetter.java

2.2.1. Chrome

As i mentioned in the previous blog post, you need to consider on what OSs the tests will be run. Let’s say you decided to use Chrome on Windows, Linux and Mac. A new method for starting Chrome will be created in the ‘BrowserGetter’ class which will start the browser on all these three selected OSs. The entire method is found here, and the explanation on what it does follows. The name of the method is ‘getChromeDriver()’ and it returns a value of type WebDriver.

public WebDriver getChromeDriver() {
        if (!IS_OS_WINDOWS && !IS_OS_LINUX && !IS_OS_MAC) {
            throw new RuntimeException("Could not 
                 initialize browser due to unknown operating system!");
        }
        if (IS_OS_WINDOWS) {
            setProperty("webdriver.chrome.driver", 
                  "src/test/resources/browserBinaries/chromedriver.exe");
        }
        if (IS_OS_LINUX) {
            setProperty("webdriver.chrome.driver", 
                  "src/test/resources/browserBinaries/chromedriver");
        }
        if (IS_OS_MAC) {
            setProperty("webdriver.chrome.driver", 
                  "src/test/resources/browserBinaries/chromedriverMac");
        }
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        return driver;
    }

What this suggested method does:

  • It uses some properties defined in the SystemUtils class from the Apache Commons Library, to determine what the OS is. These properties are of boolean type, and they will return true, as follows: IS_OS_WINDOWS will return true when the OS on which the code where you are using it is Windows; IS_OS_LINUX will return true if the OS on which the code is executing is Linux; IS_OS_MAC will be true when the code is executing on Mac. In order to use the SystemUtils class, the following import must be declared in the import section of the ‘BrowserGetter’ class:
import static org.apache.commons.lang3.SystemUtils.*;
  • The browser initializing method first checks whether the operating system is anything but the desired ones (Windows, Linux, Mac), and if it is, an exception is thrown and no browser will be initialized. This is because in the setup of this project only drivers corresponding to these operating systems are downloaded and stored, and so no other driver can be used to start the browser, except for those for Windows, Linux and Mac. There is no point in doing anything else if the OS detected is not the expected one, that is why an exception will be thrown.
if (!IS_OS_WINDOWS && !IS_OS_LINUX && !IS_OS_MAC) {
            throw new RuntimeException("Could not 
                 initialize browser due to unknown operating system!");
        }
  • If the operating system is one of the expected ones, a system property called ‘webdriver.chrome.driver’ needs to be set and to point to the location of the driver file. If the operating system is Windows, the system property needs to be set to the location of the .exe driver file; if the OS is Linux, the system property needs to point to the location of the Linux driver file; same for the Mac OS. Setting the system property is done using the method ‘setProperty’ from Java’s System class, for which the following import must be declared in the import section of the ‘BrowserGetter’ class:
import static org.apache.commons.lang3.SystemUtils.*;
  • So, for Windows, setting the ‘webdriver.chrome.driver’ system property to the location of the Chrome Windows driver file is done:
if (IS_OS_WINDOWS) {
            setProperty("webdriver.chrome.driver", 
                     "src/test/resources/browserBinaries/chromedriver.exe");
        }
  • For Linux, setting the ‘webdriver.chrome.driver’ system property to the location of the Chrome Linux driver file is done:
if (IS_OS_LINUX) {
            setProperty("webdriver.chrome.driver",       
                "src/test/resources/browserBinaries/chromedriver");
        }
  • For Mac, the corresponding code is:
if (IS_OS_MAC) {
            setProperty("webdriver.chrome.driver", 
               "src/test/resources/browserBinaries/chromedriverMac");
        }
  • After successfully setting the ‘webdriver.chrome.driver’ system property, the Chrome driver will be initialized, by the following code: 
WebDriver driver = new ChromeDriver();
  • This will open the browser and store the driver instance in a WebDriver variable. As you noticed, on the right side of this assignment a new ChromeDriver() instance is created, but on the left side, the type of variable to which this instance is stored is of WebDriver. The WebDriver is the interface which is implemented (indirectly) by all the specific drivers, like ChromeDriver, FirefoxDriver, etc. All of the tests should use a driver variable of type WebDriver. You will see in the method for instantiating a browser based on a parameter why this is useful.
  • The size of the browser however will not be the same every time it opens. It depends on how the browser works, and usually, on the size of the last opened window. Therefore, in order to keep the tests consistent, you should maximize the browser window, once the browser is open. Otherwise, you can’t know for sure how large the size of the window will be when a test is running, and how much of the page you want to test is in view, or how the page renders (if its’ design is responsive). Maximizing the window once there is a window open is done by the following code:
driver.manage().window().maximize();

When the Chrome initialization method needs to be called from a test, the ‘driver’ variable (declared to store the new ChromeDriver() instance) will be needed in the test. Selenium methods need a valid driver instance in order to interact with the browser. Therefore, the method created for starting Chrome needs to return a valid driver instance, which, in the test, will be stored to a WebDriver variable or field.

The last line of code from the initialization method will return the newly initialized ChromeDriver instance:

return driver;

In a test, in the declaration section, the WebDriver field needs to be created:

private WebDriver driver;

Calling the ‘getChromeDriver()’ method from a test can be done like this:

driver = browserGetter.getChromeDriver();

Keep in mind that the Chrome initialization method presented in this subchapter is a suggestion, since it takes into account the OSs on which the tests will be run. If, let’s say, you know for a fact that you will only run the tests on Windows, you can use a simplified version of this method:

public WebDriver getChromeDriver() {
        setProperty("webdriver.chrome.driver", 
               "src/test/resources/browserBinaries/chromedriver.exe");
        WebDriver driver = new ChromeDriver();
        driver.manage().window().maximize();
        return driver;
    }

This simplified version of the initialization method will: set the ‘webdriver.chrome.driver’ system property to point to the location of the ‘chromedriver.exe’ file (so the Windows driver file), initialize the ChromeDriver() and store the resulting driver instance to a WebDriver variable, maximize the window, then return the driver instance, to be used in tests that call this method.

2.2.2. Firefox

Starting the Firefox browser is done in a similar fashion to the Chrome one. In my GitHub project, in the same class where the Chrome related method is declared, namely BrowserGetter, you can find the ‘getFirefoxDriver()’. It looks like:

public WebDriver getFirefoxDriver() {
        if (!IS_OS_WINDOWS && !IS_OS_LINUX && !IS_OS_MAC) {
            throw new RuntimeException("Could not 
               initialize browser due to unknown operating system!");
        }
        if (IS_OS_WINDOWS) {
            setProperty("webdriver.gecko.driver", 
                "src/test/resources/browserBinaries/geckodriver.exe");
        }
        if (IS_OS_LINUX) {
            setProperty("webdriver.gecko.driver", 
                "src/test/resources/browserBinaries/geckodriver");
        }
        if (IS_OS_MAC) {
            setProperty("webdriver.gecko.driver", 
                "src/test/resources/browserBinaries/geckodriverMac");
        }
        WebDriver driver = new FirefoxDriver();
        driver.manage().window().maximize();
        return driver;
    }

In this method, the first check that is made is related to the OS on which the test will run. If it is an unkown OS (so not Windows, Linux or Mac) a new Exception will be raised and no browser will be started, since the code project only stores driver files for the known OSs. In this case, there are 3 driver files, corresponding to Firefox and to the OSs: Windows, Linux, Mac. These driver files, named ‘geckodriver.exe’ (for Windows), ‘geckodriver’ (for Linux) and ‘geckodriverMac’ (for Mac) can be found in the project, in the location ‘src/test/resources/browserBinaries’.

For each of the supported OSs, the path to the corresponding geckodriver location needs to be set as the value of the ‘webdriver.gecko.driver’ system property, exactly as this is set up above for the ‘chromedriver’ files. 

Once the ‘webdriver.gecko.driver’ system property is pointing to the correct location of the required driver for each OS, a new driver instance can be spawned. This time the driver is of type ‘FirefoxDriver’:

WebDriver driver = new FirefoxDriver();

Everything else is exactly the same in the Firefox method as is in the Chrome method. At this point, the setup of the browser is done, and you can return the ‘driver’ instance to the calling test.

In a test class, in the declaration section, the WebDriver field needs to be created:

private WebDriver driver;

Calling the ‘getFirefoxDriver()’ method from a test can be done like this:

driver = browserGetter.getFirefoxDriver();

If you are not interested in enabling the browser for all OSs, you could use a simplified version of the ‘getFirefoxDriver()’ method. Let’s say you only want to run the tests on Windows. In this case, the checks regarding the OS on which the tests run can be removed, and the remaining code of the method can be:

public WebDriver getFirefoxDriver() {
       setProperty("webdriver.gecko.driver", 
              "src/test/resources/browserBinaries/geckodriver.exe");
        WebDriver driver = new FirefoxDriver();
        driver.manage().window().maximize();
        return driver;
    }

At this point, you have two methods you could use in your tests: one for opening the Chrome browser and the other one for opening a Firefox instance. But using these methods in your tests will hardcode the browser, meaning you will run a test on the same browser each time. Should you wish to switch to the other one, you would need to find all the tests where the browser initialization method was called and change that bit to the other browser you want. In order to have an easier way of switching browsers, i will show you how to use System properties, in the next blog post of this series.

2 responses to “Browser unaware Selenium tests. STEP 2: Creating the browser initialization methods for Chrome and Firefox”

  1. vladimir100vladimir100 Avatar

    Why don’t you use Boni Garcia’s WebDriverManager to load a specific driver? You do not need to specify directories for the drivers. The program is shorter and reliable.

    Like

  2. […] Browser unaware Selenium tests. STEP 2: Creating the browser initialization methods for Chrome and Firefox – Corina Pip – https://imalittletester.com/2020/03/25/browser-unaware-selenium-tests-step-2-creating-the-browser-in… […]

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Blog at WordPress.com.