Enroll in Selenium Training

So far in the previous chapters of Selenium Cucumber Automation Framework series we have covered File Reader Manager and Page Object Manager. In this chapter we will learn How to Design WebDriver Manager in Selenium Cucumber Framework.

Why do we need WebDriver Manager or some called it as WebDriver Factory or Browser Factory?

Till now we have been creating driver within the Step file and we kind of explicitly tell our script to start Chrome Driver. This means later if we need to change Chrome to Firefox, we have to go into every test script to change the same. Which is like bhrrhhhhhhh. On top of it our test is handling the logic of creating WebDriver . This is as equal as you visit some restaurant and you are cooking your meal by yourself instead of enjoying eating your meal. The test should not be worried about how to start the driver. Test should just need a driver to execute the script. Like you in restaurant just know what to eat. So lets bring the waiter ops I mean to say WebDriver Manager in between to handle this task for us.

Design WebDriver Manager

The only responsibility of the WebDriver Manager is to get us the WebDriver, when we ask for it. To accomplish this we will be doing the below activities:

  • Specify new WebDriver Properties in the Configuration File
  • Create Enums for DriverType and EnvironmentType
  • Write new Method to read the above properties
  • Design a WebDriver Manager
  • Modify the Steps file to use the new WebDriver Manager in the script

Step 1 : Add WebDriver Properties in the Configuration file

Keep yourself in a place of WebDriver Manager and think what all the information you need to start a new webdriver. If I get into his shoes, I would ask for:

  • Environment Name: Test can run on Local or on Remote Machine or on cloud
  • Browser Name: Test can ask for any browser
  • ImplicitlyWait: This can be required by WebDriver
  • DriverPath: In case of Chrome

After passing all the above information to the Configuration file, it will look like this:

Configuration.properties

environment=local
browser=chrome
windowMaximize=true
driverPath=C:\\ToolsQA\\Libs\\Drivers\\chromedriver.exe
implicitlyWait=20
url=http://www.shop.demoqa.com

Step 2 : Create Enums for DriverType and EnvironmentType

It is always consider a good approach to create enums for all the hard coded values in the project, so define the standard.

  1. Create a New Package and name it as enums, by right click on the src/test/java and select New >> Package. We will be keeping all the project enums in this package.

  2. Create a New Enum  and name it as DriverType, by right click on the above created Package and select New >> Enum.

  3. Add three different value as of now. There can be other browsers as well but let's just take Chrome, Firefox, and IExplorer.

DriverType.java

package enums;

public enum DriverType {
	FIREFOX,
	CHROME,
	INTERNETEXPLORER
}
  1. The same way creates another Enum class for EnvironmentType and add Local & Remote to it.

EnvironmentType.java

package enums;

public enum EnvironmentType {
	LOCAL,
	REMOTE,
}

Step 3 : Write a new Method to Read new properties

Start writing the getMethods() for all the newly added properties in the ConfigFileReader class.

ConfigFileReader.java

package dataProviders;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import enums.DriverType;
import enums.EnvironmentType;

public class ConfigFileReader {	
	private Properties properties;
	private final String propertyFilePath= "configs//Configuration.properties";

	public ConfigFileReader(){
		BufferedReader reader;
		try {
			reader = new BufferedReader(new FileReader(propertyFilePath));
			properties = new Properties();
			try {
				properties.load(reader);
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException("Configuration.properties not found at " + propertyFilePath);
		}		
	}

	public String getDriverPath(){
		String driverPath = properties.getProperty("driverPath");
		if(driverPath!= null) return driverPath;
		else throw new RuntimeException("Driver Path not specified in the Configuration.properties file for the Key:driverPath");		
	}

	public long getImplicitlyWait() {		
		String implicitlyWait = properties.getProperty("implicitlyWait");
		if(implicitlyWait != null) {
			try{
				return Long.parseLong(implicitlyWait);
			}catch(NumberFormatException e) {
				throw new RuntimeException("Not able to parse value : " + implicitlyWait + " in to Long");
			}
		}
		return 30;		
	}

	public String getApplicationUrl() {
		String url = properties.getProperty("url");
		if(url != null) return url;
		else throw new RuntimeException("Application Url not specified in the Configuration.properties file for the Key:url");
	}

	public DriverType getBrowser() {
		String browserName = properties.getProperty("browser");
		if(browserName == null || browserName.equals("chrome")) return DriverType.CHROME;
		else if(browserName.equalsIgnoreCase("firefox")) return DriverType.FIREFOX;
		else if(browserName.equals("iexplorer")) return DriverType.INTERNETEXPLORER;
		else throw new RuntimeException("Browser Name Key value in Configuration.properties is not matched : " + browserName);
	}

	public EnvironmentType getEnvironment() {
		String environmentName = properties.getProperty("environment");
		if(environmentName == null || environmentName.equalsIgnoreCase("local")) return EnvironmentType.LOCAL;
		else if(environmentName.equals("remote")) return EnvironmentType.REMOTE;
		else throw new RuntimeException("Environment Type Key value in Configuration.properties is not matched : " + environmentName);
	}

	public Boolean getBrowserWindowSize() {
		String windowSize = properties.getProperty("windowMaximize");
		if(windowSize != null) return Boolean.valueOf(windowSize);
		return true;
	}

}

Explanation

  • getBrowserWindowSize() : Retrieve the property using getProperty method of Properties class. Null check is performed and in case of null by default value is returned as true. In case of not null, String value is parsed to Boolean.
  • getEnvironment() : EnvironmentType.Local is returned in case of Null and if the value is equal to Local. Which means that in case of missing environment property, execution will be carried on local machine.
  • getBrowser() : Default value is returned as DriverType.Chrome in case of Null. Exception is thrown if the value does not match with anything.

Step 4: Design a WebDriver Manager

Now it is the time to design the WebDriver Manager. The most awaited task of this chapter. The only thing which we need to keep in mind is that the manager would expose only two method for now which are getDriver() and closeDriver(). GetDriver method will decide if the driver is already created or needs to be created. GetDriver method further call the method createDriver(), which will decide that the remote driver is needed or local driver for the execution. Accordingly, CreateDriver method would make a call let's say to createLocalDriver(). CreateLocalDriver method will further decide which type of driver needs to be created.

WebDriverManager.java

package managers;

import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import enums.DriverType;
import enums.EnvironmentType;

public class WebDriverManager {
	private WebDriver driver;
	private static DriverType driverType;
	private static EnvironmentType environmentType;
	private static final String CHROME_DRIVER_PROPERTY = "webdriver.chrome.driver";

	public WebDriverManager() {
		driverType = FileReaderManager.getInstance().getConfigReader().getBrowser();
		environmentType = FileReaderManager.getInstance().getConfigReader().getEnvironment();
	}

	public WebDriver getDriver() {
		if(driver == null) driver = createDriver();
		return driver;
	}

	private WebDriver createDriver() {
		   switch (environmentType) {	    
	        case LOCAL : driver = createLocalDriver();
	        	break;
	        case REMOTE : driver = createRemoteDriver();
	        	break;
		   }
		   return driver;
	}

	private WebDriver createRemoteDriver() {
		throw new RuntimeException("RemoteWebDriver is not yet implemented");
	}

	private WebDriver createLocalDriver() {
        switch (driverType) {	    
        case FIREFOX : driver = new FirefoxDriver();
	    	break;
        case CHROME : 
        	System.setProperty(CHROME_DRIVER_PROPERTY, FileReaderManager.getInstance().getConfigReader().getDriverPath());
        	driver = new ChromeDriver();
    		break;
        case INTERNETEXPLORER : driver = new InternetExplorerDriver();
    		break;
        }

        if(FileReaderManager.getInstance().getConfigReader().getBrowserWindowSize()) driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(FileReaderManager.getInstance().getConfigReader().getImplicitlyWait(), TimeUnit.SECONDS);
		return driver;
	}	

	public void closeDriver() {
		driver.close();
		driver.quit();
	}

}

Step 5: Modify the Steps file to use the new WebDriver Manager in the script

Now start using WebDriver Manager in the script to create a new driver.

Steps.java

package stepDefinitions;

import org.openqa.selenium.WebDriver;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.When;
import managers.PageObjectManager;
import managers.WebDriverManager;
import pageObjects.CartPage;
import pageObjects.CheckoutPage;
import pageObjects.HomePage;
import pageObjects.ProductListingPage;

public class Steps {
	WebDriver driver;
	HomePage homePage;
	ProductListingPage productListingPage;
	CartPage cartPage;
	CheckoutPage checkoutPage;
	PageObjectManager pageObjectManager;	
	WebDriverManager webDriverManager;
	
	
	@Given("^user is on Home Page$")
	public void user_is_on_Home_Page(){
		webDriverManager = new WebDriverManager();
		driver = webDriverManager.getDriver();
		pageObjectManager = new PageObjectManager(driver);
		homePage = pageObjectManager.getHomePage();
		homePage.navigateTo_HomePage();	
	}

	@When("^he search for \"([^\"]*)\"$")
	public void he_search_for(String product)  {
		homePage.perform_Search(product);
	}

	@When("^choose to buy the first item$")
	public void choose_to_buy_the_first_item() {
		productListingPage = pageObjectManager.getProductListingPage();
		productListingPage.select_Product(0);
		productListingPage.clickOn_AddToCart();		
	}

	@When("^moves to checkout from mini cart$")
	public void moves_to_checkout_from_mini_cart(){
		cartPage = pageObjectManager.getCartPage();
		cartPage.clickOn_Cart();
		cartPage.clickOn_ContinueToCheckout();	
	}
	
	@When("^enter personal details on checkout page$")
	public void enter_personal_details_on_checkout_page(){
		checkoutPage = pageObjectManager.getCheckoutPage();
		checkoutPage.fill_PersonalDetails();	
	}
	
	@When("^select same delivery address$")
	public void select_same_delivery_address(){
		checkoutPage.check_ShipToDifferentAddress(false);
	}
	
	@When("^select payment method as \"([^\"]*)\" payment$")
	public void select_payment_method_as_payment(String arg1){
		checkoutPage.select_PaymentMethod("CheckPayment");
	}

	@When("^place the order$")
	public void place_the_order() {
		checkoutPage.check_TermsAndCondition(true);
		checkoutPage.clickOn_PlaceOrder();		
		webDriverManager.quitDriver();
	}	
}

Run the Cucumber Test

Run as JUnit

Now we are all set to run the Cucumber test. Right Click on TestRunner class and Click Run As  >> JUnit TestCucumber will run the script the same way it runs in Selenium WebDriver and the result will be shown in the left hand side project explorer window in JUnit tab.

Project Explorer

Design WebDriver Manager

File Reader Manager as Singleton Design Pattern
File Reader Manager as Singleton Design Pattern
Previous Article
Sharing Test Context between Cucumber Step Definitions
Sharing Test Context between Cucumber Step Definitions
Next Article
Lakshay Sharma
I’M LAKSHAY SHARMA AND I’M A FULL-STACK TEST AUTOMATION ENGINEER. Have passed 16 years playing with automation in mammoth projects like O2 (UK), Sprint (US), TD Bank (CA), Canadian Tire (CA), NHS (UK) & ASOS(UK). Currently, I am working with RABO Bank as a Chapter Lead QA. I am passionate about designing Automation Frameworks that follow OOPS concepts and Design patterns.
Reviewers
Virender Singh's Photo
Virender Singh

Similar Articles

Feedback