Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Selenium Framework Design in Data-Driven Testing

You're reading from   Selenium Framework Design in Data-Driven Testing Build data-driven test frameworks using Selenium WebDriver, AppiumDriver, Java, and TestNG

Arrow left icon
Product type Paperback
Published in Jan 2018
Publisher Packt
ISBN-13 9781788473576
Length 354 pages
Edition 1st Edition
Languages
Concepts
Arrow right icon
Author (1):
Arrow left icon
Carl Cocchiaro Carl Cocchiaro
Author Profile Icon Carl Cocchiaro
Carl Cocchiaro
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Building a Scalable Selenium Test Driver Class for Web and Mobile Applications FREE CHAPTER 2. Selenium Framework Utility Classes 3. Best Practices for Building Selenium Page Object Classes 4. Defining WebDriver and AppiumDriver Page Object Elements 5. Building a JSON Data Provider 6. Developing Data-Driven Test Classes 7. Encapsulating Data in Data-Driven Testing 8. Designing a Selenium Grid 9. Third-Party Tools and Plugins 10. Working Selenium WebDriver Framework Samples

The singleton driver class

In this section, a Java singleton class will be used to create the driver class. This will force the user to use the same object for all instances where the WebDriver is required. The WebDriver events will never get out of sync during the run, and all WebDriver events will get sent to the correct browser or mobile device instance. And since the instance of the class is created on a single thread, referencing it won't interfere with other WebDriver instances running on the same node simultaneously.

As per Wikipedia (https://en.wikipedia.org/wiki/Singleton_pattern):

"In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects. The term comes from the mathematical concept of a singleton."

Requirements

In order to start building the framework, users must import the required JAR files into their project to use the Selenium WebDriver, AppiumDriver, and TestNG APIs. Additionally, there will be various Java JAR files required, such as Apache, Spring, File I/O, and other utilities as the framework develops:

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.ios.IOSDriver;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.edge.EdgeOptions;
import org.openqa.selenium.firefox.*;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.LocalFileDetector;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.safari.SafariDriver;
import org.openqa.selenium.safari.SafariOptions;
import org.testng.*;
A good source location for finding these JAR files is https://mvnrepository.com/.

The class signature

The class should be named something obvious such as Driver.java, CreateDriver.java, SeleniumDriver.java, and so on. Since this will be a Java singleton class, it will contain a private constructor and a static getInstance method as follows:

/**
* Selenium Singleton Class
*
* @author CarlCocchiaro
*
*/
@SuppressWarnings("varargs")
public class CreateDriver {

// constructor
private CreateDriver() {
}

/**
* getInstance method to retrieve active driver instance
*
* @return CreateDriver
*/
public static CreateDriver getInstance() {
if ( instance == null ) {
instance = new CreateDriver();
}

return
instance;
}
}

Class variables

Initially, when building the class, there will be various private and public variables used that should be declared at the top of the class. This organizes the variables into one place in the file, but of course, this is a coding style guideline. Some of the common variables required to start are as follows:

public class CreateDriver {
// local variables
private static CreateDriver instance = null;
private String browserHandle = null;
private static final int IMPLICIT_TIMEOUT = 0;

private
ThreadLocal<WebDriver> webDriver =
new ThreadLocal<WebDriver>();

private
ThreadLocal<AppiumDriver<MobileElement>> mobileDriver =
new ThreadLocal<AppiumDriver<MobileElement>>();

private
ThreadLocal<String> sessionId =
new ThreadLocal<String>();

private
ThreadLocal<String> sessionBrowser =
new ThreadLocal<String>();

private
ThreadLocal<String> sessionPlatform =
new ThreadLocal<String>();

private
ThreadLocal<String> sessionVersion =
new ThreadLocal<String>();

private
String getEnv = null;
}

JavaDoc

Before introducing the common methods in this driver class, it is prudent to note that requiring JavaDoc for all methods in the class will be helpful for users who are learning the framework. The JavaDoc can be built automatically in Java using a build tool such as Maven, Gradle, or Ant. An example of the JavaDoc format is as follows:

/**
* This is the setDriver method used to create the Selenium WebDriver
* or AppiumDriver instance!
*
*
@param parameter 1
* @param parameter 2
* @param parameter 3
* @param parameter 4
*
* @throws Exception
*/

Parameters

The driver class will be designed with various get and set methods. The main setDriver method can take parameters to determine the browser or mobile type, platform to run on, environment for testing, and a set of optional preferences to allow changing driver behavior on the fly:

@SafeVarargs
public final void setDriver(String browser,
String platform,
String environment,
Map<String, Object>... optPreferences)

Examples of some of the parameters of setDriver are as follows:

  • browser: Chrome, Firefox, Internet Explorer, Microsoft Edge, Opera, Safari (iPhone/iPad, or Android for mobile)
  • platform: Linux, Windows, Mac, Sierra, Win10 (iPhone/iPad, or Android for mobile)
  • environment: Local, remote, and Sauce Labs
  • optPrefs: Map of driver preferences (this will be covered later in detail)

Class methods

All the methods in this class should pertain to the web or mobile driver. This includes things such as setDriver, getDriver, getCurrentDriver, getSessionID/Browser/Version/Platform, driverWait, driverRefresh, and closeDriver. Each will be outlined in this section:

  • setDriver: The setDriver methods (standard and overloaded) will allow users to create a new instance of the driver for testing browser or mobile devices. The method will take parameters for browser, platform, environment, and optional preferences. Based on these preferences, the WebDriver/AppiumDriver of choice will be created. Here are some key points of the method, including a code sample:
  • The driver preferences are set up using the DesiredCapabilities class
  • The method will be segregated according to the browser or mobile type, platform, and environment
  • The method will be overloaded to allow switching back and forth between multiple drivers running concurrently

The following code demonstrates the standard setDriver method:

/**
* setDriver method
*
* @param browser
* @param environment
* @param platform
* @param optPreferences
* @throws Exception
*/
@SafeVarargs
public final void setDriver(String browser,
String environment,
String platform,
Map<String, Object>... optPreferences)
throws Exception {

DesiredCapabilities caps = null;
String localHub = "http://127.0.0.1:4723/wd/hub";
String getPlatform = null;

switch (browser) {
case "firefox":
caps = DesiredCapabilities.firefox();
webDriver.set(new FirefoxDriver(caps));

break;
case "chrome":
caps = DesiredCapabilities.chrome();
webDriver.set(new ChromeDriver(caps));

break;
case "internet explorer":
caps = DesiredCapabilities.internetExplorer();
webDriver.set(new
InternetExplorerDriver(caps));

break;
case "safari":
caps = DesiredCapabilities.safari();
webDriver.set(new SafariDriver(caps));

break;
case "microsoftedge":
caps = DesiredCapabilities.edge();
webDriver.set(new EdgeDriver(caps));

break;
case "iphone":
case "ipad":
if (browser.equalsIgnoreCase("ipad")) {
caps = DesiredCapabilities.ipad();
}

else {
caps = DesiredCapabilities.iphone();
}

mobileDriver.set(new IOSDriver<MobileElement>(
new URL(localHub), caps));

break;
case "android":
caps = DesiredCapabilities.android();
mobileDriver.set(new
AndroidDriver<MobileElement>(
new URL(localHub), caps));

break;
}
}

Here is the overloaded setDriver method:

/** 
* overloaded setDriver method to switch driver to specific WebDriver
* if running concurrent drivers
*
* @param driver WebDriver instance to switch to
*/
public void setDriver(WebDriver driver) {
webDriver.set(driver);

sessionId.set(((RemoteWebDriver) webDriver.get())
.getSessionId().toString());

sessionBrowser.set(((RemoteWebDriver) webDriver.get())
.getCapabilities().getBrowserName());

sessionPlatform.set(((RemoteWebDriver) webDriver.get())
.getCapabilities().getPlatform().toString());

setBrowserHandle(getDriver().getWindowHandle());
}

/**
* overloaded setDriver method to switch driver to specific AppiumDriver
* if running concurrent drivers
*
* @param driver AppiumDriver instance to switch to
*/
public void setDriver(AppiumDriver<MobileElement> driver) {
mobileDriver.set(driver);

sessionId.set(mobileDriver.get()
.getSessionId().toString());

sessionBrowser.set(mobileDriver.get()
.getCapabilities().getBrowserName());

sessionPlatform.set(mobileDriver.get()
.getCapabilities().getPlatform().toString());
}
  • getDriver and getCurrentDriver: The getDriver and getCurrentDriver methods (standard and overloaded) will allow users to retrieve the current driver, whether that be browser or mobile. The driver should be instantiated at the beginning of the test, and will remain available throughout the test by using these methods. Since many of the Selenium WebDriver methods require the driver to be passed to it, these methods will allow users to retrieve the currently active session:
/**
* getDriver method will retrieve the active WebDriver
*
* @return WebDriver
*/
public WebDriver getDriver() {
return webDriver.get();
}

/**
* getDriver method will retrieve the active AppiumDriver
*
* @param mobile boolean parameter
* @return AppiumDriver
*/
public AppiumDriver<MobileElement> getDriver(boolean mobile) {
return mobileDriver.get();
}

/**
* getCurrentDriver method will retrieve the active WebDriver
* or AppiumDriver
*
* @return WebDriver
*/
public WebDriver getCurrentDriver() {
if ( getInstance().getSessionBrowser().contains("iphone") ||
getInstance().getSessionBrowser().contains("ipad") ||
getInstance().getSessionBrowser().contains("android") ) {

return
getInstance().getDriver(true);
}

else
{
return getInstance().getDriver();
}
}
  • driverWait and driverRefresh: The driverWait method will "pause" the script for the designated amount of time in seconds, although this should not be used to synchronize event handling. The driverRefresh method will reload the currently active browser page:
/**
* driverWait method pauses the driver in seconds
*
* @param seconds to pause
*/
public void driverWait(long seconds) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(seconds));
}

catch
(InterruptedException e) {
// do something
}
}

/**
* driverRefresh method reloads the current browser page
*/
public void driverRefresh() {
getCurrentDriver().navigate().refresh();
}
  • closeDriver: The closeDriver method will retrieve the current driver and call the WebDriver's quit method on it, browser or mobile:
/**
* closeDriver method quits the current active driver
*/
public void closeDriver() {
try {
getCurrentDriver().quit();
}

catch ( Exception e ) {
// do something
}
}
You have been reading a chapter from
Selenium Framework Design in Data-Driven Testing
Published in: Jan 2018
Publisher: Packt
ISBN-13: 9781788473576
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image