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
Selenium Framework Design in Data-Driven Testing
Selenium Framework Design in Data-Driven Testing

Selenium Framework Design in Data-Driven Testing: Build data-driven test frameworks using Selenium WebDriver, AppiumDriver, Java, and TestNG

eBook
$27.98 $39.99
Paperback
$48.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing
Table of content icon View table of contents Preview book icon Preview Book

Selenium Framework Design in Data-Driven Testing

Building a Scalable Selenium Test Driver Class for Web and Mobile Applications

In this chapter, we will cover designing and building the Java test driver class required to create and use the Selenium WebDriver API and AppiumDriver API for automated testing. The driver class is the central location for all aspects and preferences of the browser and mobile devices, platforms and versions to run on, support for multithreading, support for the Selenium Grid Architecture, and customization of the driver. This chapter will cover the following topics:

  • Introduction
  • The singleton driver class
  • Using preferences to support browsers and platforms
  • Using preferences to support mobile device simulators, emulators, and real devices
  • Multithreading support for use in parallel and distributed testing
  • Passing optional arguments and parameters to the driver
  • Selenium Grid Architecture support using the RemoteWebDriver and AppiumDriver classes
  • Third-party grid architecture support, including the Sauce Labs Test Cloud
  • Using property files to select browsers, devices, versions, platforms, languages, and so on
Selenium headquarters website

Introduction

In this chapter, users will be introduced to data-driven testing, the Selenium Page Object Model, and Don't Repeat Yourself (DRY) approaches to testing, all of which work hand-in-hand with each other, and are required for scalable frameworks. Let's briefly discuss each.

Data-driven testing

The premise of data-driven testing is that test methods and test data are separated to allow the adding of new test permutations without changing the test methods, to reduce the amount of code, reduce the amount of maintenance required for testing, and to store common libraries in a central location—those being the page object classes. Data is encapsulated in a central location such as a database, JSON, or CSV file, property file, or an Excel spreadsheet, to name a few. Test methods then allow dynamic data to be passed into them on the fly using parameters and data providers of choice. The test methods themselves become "templates" for positive, negative, boundary, and/or limit testing, extending coverage of the suite of tests with limited code additions.

TestNG data-driven testing tip:

http://testng.org/doc/documentation-main.html

Selenium Page Object Model

The Selenium Page Object Model is based on the programming concepts that a page object class should include all aspects of the page under test, such as the elements on the page, the methods for interacting with those elements, variables, and properties associated with the class. Following that concept, there is no data stored in the page object class. The test classes themselves call methods on the page object instances they are testing, but have no knowledge of the granular elements in the class. Finally, the actual test data is encapsulated outside the test class in a central location. In other words, there is an abstract layer created between the tests and the actual page object classes. This reduces the amount of code being written and allows them to be reused in various testing scenarios, thus following the DRY approaches to programming. From a maintenance point of view, changes to methods and locators are made in limited, central places, reducing the amount of time required to maintain ever-changing applications.

DRY 

DRY approaches to creating page object and test classes simply mean promoting the use of common classes, locators, methods, and inheritance to eliminate and avoid repeating the same actions over and over in multiple places. Instead, abstract base classes are created, containing all common objects and methods, and used as libraries to be called using parameters, which vary based on the data that is passed into them from the test classes. All subclasses derived from these base classes inherit all the common code, objects, locators, and methods, and enforce all of the abstract methods required by the base class. In essence, this approach avoids common copy and paste actions that result in duplicate code in multiple places.

As per Wikipedia (https://en.wikipedia.org/wiki/Data-driven_testing):

"Data-driven testing (DDT) is a term used in the testing of computer software to describe testing done using a table of conditions directly, as test inputs and verifiable outputs as well as the process where test environment settings and control are not hardcoded. In the simplest form the tester supplies the inputs from a row in the table and expects the outputs which occur in the same row. The table typically contains values which correspond to boundary or partition input spaces. In the control methodology, test configuration is "read" from a database."

What you will learn

Users will learn how to design and build the Java singleton class required to control the Selenium driver of choice for the Application Under Test (AUT).

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
}
}

Using preferences to support browsers and platforms

The browser preferences and behavior can be set to specific defaults when the driver is created, set on the fly using optional parameters, or set as system properties. Preferences can be set for different languages, geolocations, focus, download folders, and so on. This section will cover the basics of how to set default preferences and capabilities in the driver method.

The Selenium HQ documentation on Desired Capabilities is located at https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities.

Browser preferences

  • Firefox: Preferences for this browser are set using the FirefoxProfile class, the FirefoxOptions class, and Desired Capabilities. The list of preferences and options set in the profile are then passed to the driver as DesiredCapabilites. The following example shows various profile preferences passed into the driver as default settings using both profile preferences and Desired Capabilities:
switch (browser) {
case "firefox":
caps = DesiredCapabilities.firefox();

FirefoxOptions ffOpts = new FirefoxOptions();
FirefoxProfile ffProfile = new FirefoxProfile();
ffProfile.setPreference("browser.autofocus",
true
);

caps.setCapability(FirefoxDriver.PROFILE,
ffProfile);

caps.setCapability("marionette",
true);

webDriver.set(new FirefoxDriver(caps));

// Selenium 3.7.x
// webDriver.set(new FirefoxDriver(ffOpts.merge(caps)));
}

break;
}

Firefox preferences can be found by typing the following into the Firefox location bar: about:config or at https://github.com/mozilla/geckodriver/.

accessibility.AOM.enabled; false
accessibility.accesskeycausesactivation; true
accessibility.blockautorefresh; false
...
  • Chrome: Preferences for this browser are set using the ChromeOptions class and Desired Capabilities. The list of preferences and/or arguments are then passed to the driver as DesiredCapabilites. The following example shows various preferences and arguments passed into the driver as default settings using both preferences and Desired Capabilities:

switch (browser) {
case "chrome":
caps = DesiredCapabilities.chrome();

ChromeOptions chOptions = new ChromeOptions();
Map<String, Object> chromePrefs =
new HashMap<String, Object>();

chromePrefs.put("credentials_enable_service",
false);
chOptions.setExperimentalOption("prefs",
chromePrefs);
chOptions.addArguments("--disable-plugins",
"--disable-extensions",
"--disable-popup-blocking");

caps.setCapability(ChromeOptions.CAPABILITY,
chOptions);

caps.setCapability("applicationCacheEnabled",
false);

webDriver.set(new ChromeDriver(caps));

// Selenium 3.7.x
// webDriver.set(new ChromeDriver(chOptions.merge(caps)));

break;
}

Chrome preferences can be found by typing the following into the Chrome location bar: chrome://flags or https://sites.google.com/a/chromium.org/chromedriver/capabilities.
  • Internet Explorer, Safari, and Microsoft Edge: Preferences for these browsers are also set using the InternetExplorerOptions, SafariOptions, EdgeOptions classes, and Desired Capabilities. Users can query for the available options and capabilities for each of these browsers. The following code sample shows an abbreviated case for each.

For Internet Explorer:

switch (browser) {
case "internet explorer":
caps = DesiredCapabilities.internetExplorer();

InternetExplorerOptions ieOpts =
new InternetExplorerOptions();

ieOpts.requireWindowFocus();

ieOpts.merge(caps);
caps.setCapability("requireWindowFocus",
true);

webDriver.set(new InternetExplorerDriver(caps));

// Selenium 3.7.x
// webDriver.set(new InternetExplorerDriver(
ieOpts.merge(caps))
);

break;
}

For Safari:


switch
(browser) {
case "safari":
caps = DesiredCapabilities.safari();

SafariOptions safariOpts = new SafariOptions();
safariOpts.setUseCleanSession(true);

caps.setCapability(SafariOptions.CAPABILITY,
safariOpts);
caps.setCapability("autoAcceptAlerts",
true);

webDriver.set(new SafariDriver(caps));

// Selenium 3.7.x
// webDriver.set(new SafariDriver(safariOpts.merge(caps)));

break;
}

For Microsoft Edge:

switch(browser) {
case "microsoftedge":
caps = DesiredCapabilities.edge();

EdgeOptions edgeOpts = new EdgeOptions();
edgeOpts.setPageLoadStrategy("normal");

caps.setCapability(EdgeOptions.CAPABILITY,
edgeOpts);
caps.setCapability("requireWindowFocus",
true);


webDriver.set(new EdgeDriver(caps));

// Selenium 3.7.x
// webDriver.set(new EdgeDriver(edgeOpts.merge(caps)));

break
;
}

Platforms

There are some specific system properties that need to be set for each driver; specifically, the path to the local driver in the GIT repository of the project. By storing the driver in the project, users will not have to download or install the drivers for each browser when testing locally from their IDE. The path also depends on the OS of the development platform. The following examples are for Windows platforms:

  • Firefox:
    System.setProperty("webdriver.gecko.driver","gecko_driver_windows_path/geckodriver.exe");
  • Chrome:
    System.setProperty("webdriver.chrome.driver","chrome_driver_windows_path/chromedriver.exe");
  • IE:
    System.setProperty("webdriver.ie.driver","ie_driver_windows_path/IEDriverServer.exe");
  • Edge:
    System.setProperty("webdriver.edge.driver","edge_driver_windows_path/MicrosoftWebDriver.exe");
  • Safari: The Safari driver is now built into the browser by Apple

Using preferences to support mobile device simulators, emulators, and real devices

The mobile device preferences and behaviors can be set to specific defaults when the driver is created, set on the fly using optional parameters, or set as system properties. Preferences can be set for loading applications on the device, device options, timeouts, platform versions, device versions, and so on. This is accomplished using the Desired Capabilities class, as with browser testing. The following section provides examples of some of the mobile simulator, emulator, and physical device preferences.

iOS preferences

Preferences for iPhone/iPad mobile devices are set using the Desired Capabilities class. Capabilities are set for the iPhone and iPad simulators, or physical devices. The following example shows various capabilities for these iOS devices:

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

else
{
caps = DesiredCapabilities.iphone();
}

caps.setCapability("appName",
"https://myapp.com/myApp.zip");

caps.setCapability("udid",
"12345678"); // physical device
caps.setCapability("device",
"iPhone"); // or iPad

mobileDriver.set(new IOSDriver<MobileElement>
(new URL("http://127.0.0.1:4723/wd/hub"),
caps));

break;

The Desired Capabilities for iOS and Android can be found at http://appium.io/slate/en/master/?java#the-default-capabilities-flag.

Android preferences

Android: Preferences for these mobile devices are set using the Desired Capabilities class. Capabilities are set for Android Emulators, or physical devices. The following example shows various capabilities for these Android devices:

switch(browser) {
case "android":
caps = DesiredCapabilities.android();

caps.setCapability("appName",
"https://myapp.com/myApp.apk");

caps.setCapability("udid",
"12345678"); // physical device
caps.setCapability("device",
"Android");

mobileDriver.set(new AndroidDriver<MobileElement>
(new URL("http://127.0.0.1:4723/wd/hub"),
caps));

break;

Multithreading support for parallel and distributed testing

In order to leverage the TestNG parallel testing features, users must create a separate thread for each driver instance to control event processing requests. This is done in Java using the ThreadLocal<T> class. By declaring variables with this class, each thread has its own initialized copy of the variable, and can return specifics of that session. The following variables are declared in the singleton driver class, and have getter and setter methods to retrieve the session ID, browser, platform, and version:

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>();

Key points:

  • The set methods are called by the setDriver methods during instantiation of the driver.
  • The get methods are stored in the singleton driver class and can be called after the driver is created. Users can retrieve session parameters for each specific instance of the driver that is running.
  • To leverage the separate instances during parallel test runs, TestNG suite parameters must also be used. For example:
<suite name="Parallel_Test_Suite" preserve-order="true" parallel="classes" thread-count="10">

These are examples of the getter methods for the driver class:

/**
* getSessionId method gets the browser or mobile id
* of the active session
*
* @return String
*/
public String getSessionId() {
return sessionId.get();
}

/**
* getSessionBrowser method gets the browser or mobile type
* of the active session
*
* @return String
*/
public String getSessionBrowser() {
return sessionBrowser.get();
}

/**
* getSessionVersion method gets the browser or mobile version
* of the active session
*
* @return String
*/
public String getSessionVersion() {
return sessionVersion.get();
}

/**
* getSessionPlatform method gets the browser or mobile platform
* of the active session
*
* @return String
*/
public String getSessionPlatform() {
return sessionPlatform.get();
}

How to set:

The session ID, browser, version, and platform can be set during driver creation in the setDriver methods as follows:

getEnv = "local";
getPlatform = platform;

if ( browser.equalsIgnoreCase("iphone") ||
browser.equalsIgnoreCase("android") ) {

sessionId.set(((IOSDriver<MobileElement>)
mobileDriver.get()).getSessionId().toString());

sessionId.set(((AndroidDriver<MobileElement>)
mobileDriver.get()).getSessionId().toString());

sessionBrowser.set(browser);
sessionVersion.set(caps.getCapability("deviceName").toString());
sessionPlatform.set(getPlatform);
}

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

sessionBrowser.set(caps.getBrowserName());
sessionVersion.set(caps.getVersion());
sessionPlatform.set(getPlatform);
}

Passing optional arguments and parameters to the driver

In many instances, users will want to change the default behavior of the browser before the test starts, or on the fly when creating a new driver during the test run. We previously covered setting default preferences and options in the setDriver method to keep the test environment static. Now, we can alter the default preferences using the varargs parameter in Java, as an optional parameter to the setDriver method. Here are the basics:

  • The varargs parameter to setDriver will be a Map<String, Object> type
  • Map can be passed into the driver when creating a new browser instance, or by setting a JVM argument of mapped preferences
  • JVM arguments used to pass in mapped preferences can be done in a TestNG XML file as a parameter, an IDE Run Configuration using a JVM arg, or as a -Dswitch to the command-line executable
  • Each browser type will need to process the map of Desired Capabilities, preferences, and options

varargs

The following example shows how to use the varargs parameter in the setDriver method, which is called optPreferences. This is the setDriver method so far, from what we have built:

@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();
FirefoxProfile ffProfile = new FirefoxProfile();

ffProfile.setPreference("browser.autofocus",
true);
caps.setCapability(FirefoxDriver.PROFILE,
ffProfile);
caps.setCapability("marionette",
true);
System.setProperty("webdriver.gecko.driver",
"gecko_driver_windows_path/geckodriver.exe");

if ( optPreferences.length > 0 ) {
processFFProfile(ffProfile, optPreferences);
}

webDriver.set(new FirefoxDriver(caps));
break;
case "chrome":
caps = DesiredCapabilities.chrome();
ChromeOptions chOptions = new ChromeOptions();

Map<String, Object> chromePrefs =
new HashMap<String, Object>();
chromePrefs.put("credentials_enable_service",
false);
chOptions.setExperimentalOption("prefs",
chromePrefs);
chOptions.addArguments("--disable-plugins",
"--disable-extensions",
"--disable-popup-blocking");
caps.setCapability(ChromeOptions.CAPABILITY,
chOptions);
caps.setCapability("applicationCacheEnabled",
false);
System.setProperty("webdriver.chrome.driver",
"chrome_driver_windows_path/chromedriver.exe");

if ( optPreferences.length > 0 ) {
processCHOptions(chOptions, optPreferences);
}

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

InternetExplorerOptions ieOpts =
new InternetExplorerOptions();

ieOpts.requireWindowFocus();
ieOpts.merge(caps);
caps.setCapability("requireWindowFocus",
true);
System.setProperty("webdriver.ie.driver",
"ie_driver_windows_path/IEDriverServer.exe");

if ( optPreferences.length > 0 ) {
processDesiredCaps(caps, optPreferences);
}

webDriver.set(new InternetExplorerDriver(caps));
break;
}

// etc...
}

The parameter for setDriver

The next example shows how to pass Map into the setDriver method using the varargs parameter:

// first, create a map for the key:value pairs to pass into the driver
Map<String, Object> preferences = new HashMap<String, Object>;

// then put the key:value pairs into the map
preferences.put("applicationCacheEnabled",false);
preferences.put("network.cookie.cookieBehavior", 0);

// then, pass the map into the setDriver method
CreateDriver.getInstance().setDriver("firefox",
"Windows 10",
"local",
preferences);

JVM argument – -Dswitch

Finally, the next example shows how to set the optional browser preferences as a JVM argument using the TestNG parameter attribute in the suite XML file:

// pass in the key:value pairs as a runtime argument
-Dbrowserprefs=applicationCacheEnabled:false,
network.cookie.cookieBehavior:0


// pass in the key:value pairs as a TestNG XML parameter
<test name="Selenium TestNG Test Suite">
<parameter name="browser" value="chrome" />
<parameter name="platform" value="Windows 10" />
<parameter name="browserPrefs" value="intl.accept_languages:fr" />

<classes>
<class name="com.myproject.MyTest" />
</classes>
</test>

// for convenience, create a setPreferences method
// to build the map to pass into the driver
public Map<String, Object> setPreferences() {
Map<String, Object> prefsMap = new HashMap<String, Object>();
List<String> allPrefs = Arrays.asList(
System.getProperty("browserPrefs").split(",", -1));

// extract the key/value pairs and pass to map...
for ( String getPref : allPrefs ) {
prefsMap.put(getPref.split(":")[0], getPref.split(":")[1]);
}

return prefsMap;
}

// set JVM arg, call this method on-the-fly, create new driver
if ( System.getProperty("browserPrefs") != null ) {
CreateDriver.getInstance().setDriver("firefox",
"Windows 10",
"local",
CreateDriver.getInstance().setBrowserPrefs()
);
}

Parameter processing methods

Once the optional preferences are passed into the setDriver method, the user then has to process those options. For instance, there may be DesiredCapabilities,  ChromeOptions, or FirefoxProfile preferences that need to be processed. First, for each driver-type instance, there needs to be a check to see if the options have been passed in, then if so, they have to be processed. Each type will be outlined as shown here:

/**
* Process Desired Capabilities method to override default browser
* or mobile driver behavior
*
* @param caps - the DesiredCapabilities object
* @param options - the key: value pair map
* @throws Exception
*/
private void processDesiredCaps(DesiredCapabilities caps,
Map<String,
Object>[] options
)
throws Exception {

for
( int i = 0; i < options.length; i++ ) {
Object[] keys = options[i].keySet().toArray();
Object[] values = options[i].values().toArray();

for
( int j = 0; j < keys.length; j++ ) {
if ( values[j] instanceof Integer ) {
caps.setCapability(keys[j].toString(),
(int) values[j]);
}
else if ( values[j] instanceof Boolean) {
caps.setCapability(keys[j].toString(),
(boolean) values[j]);
}
else if ( isStringInt(values[j].toString()) ) {
caps.setCapability(keys[j].toString(),

Integer.valueOf(values[j].toString()));
}
else if ( Boolean.parseBoolean(values[j].toString()) ) {
caps.setCapability(keys[j].toString(),

Boolean.valueOf(values[j].toString()));
}
else {
caps.setCapability(keys[j].toString(),
values[j].toString());
}
}
}
}

/**
* Process Firefox Profile Preferences method to override default
* browser driver behavior
*
* @param caps - the FirefoxProfile object
* @param options - the key: value pair map
* @throws Exception
*/
private void processFFProfile(FirefoxProfile profile, Map<String, Object>[] options) throws Exception {
for (int i = 0; i < options.length; i++) {
Object[] keys = options[i].keySet().toArray();
Object[] values = options[i].values().toArray();

// same as Desired Caps except the following difference
for (int j = 0; j < keys.length; j++) {
if (values[j] instanceof Integer) {
profile.setPreference(keys[j].toString(),
(int) values[j]);
}

// etc...
}
}
} /**
* Process Chrome Options method to override default browser
* driver behavior
*
* @param caps - the ChromeOptions object
* @param options - the key: value pair map
* @throws Exception
*/
private void processCHOptions(ChromeOptions chOptions, Map<String, Object>[] options) throws Exception {
for (int i = 0; i < options.length; i++) {
Object[] keys = options[i].keySet().toArray();
Object[] values = options[i].values().toArray();

// same as Desired Caps except the following difference

for (int j = 0; j < keys.length; j++) {
if (values[j] instanceof Integer) {
values[j] = (int) values[j];
chOptions.setExperimentalOption("prefs", options[i]);
}

// etc...
}
}
}

Selenium Grid Architecture support using the RemoteWebDriver and AppiumDriver classes

When creating a WebDriver instance, users will pass specified preferences, options, and capabilities to the driver running locally in their environment. As previously mentioned, users can store the actual Chrome driver, Firefox driver, and other driver files in their repo, so they won't have to be installed in each development environment. They can then point the local driver instance to the repo location using a desired capability.

Now, when designing and using the Selenium Grid Architecture to run tests against, the user will have to cast the browser or mobile capabilities to the RemoteWebDriver class, or remote AppiumDriver server. This capability should be built into the driver class as well, so the same class can support local, remote, and third-party test platforms. The Selenium Grid Architecture will be discussed in great detail in a separate chapter, but the relevance here is what needs to go into this driver class. Also, keep in mind that users must pass parameters into their driver class to change the environment from local to remote, or thirdParty to direct traffic to the grid nodes.

  • WebDriver: The URL of the remote grid hub, browser capabilities, driver-specific casting, and any Selenium Grid Node capabilities that control directing traffic to the specific Selenium standalone server node
  • AppiumDriver: The URL of the remote grid hub, mobile device capabilities, and any Selenium Grid Node capabilities that control directing traffic to the specific Appium server node

Here is the code for the preceding explanation:

// for each browser instance
if ( environment.equalsIgnoreCase("remote") ) {
// set up the Selenium Grid capabilities...
String remoteHubURL = "http://mygrid-
hub.companyname.com:4444/wd/hub";

caps.setCapability("browserName",
browser);
caps.setCapability("version",
caps.getVersion());
caps.setCapability("platform",
platform);

// unique user-specified name
caps.setCapability("applicationName",
platform + "-" + browser);

webDriver.set(new RemoteWebDriver(new URL(remoteHubURL), caps));
((RemoteWebDriver) webDriver.get()).setFileDetector(
new LocalFileDetector());
}

// for each mobile device instance
if ( environment.equalsIgnoreCase("remote") ) {
// setup the Selenium Grid capabilities...
String remoteHubURL = "http://mygrid-
hub.companyname.com:4444/wd/hub";

caps.setCapability("browserName",
browser);
caps.setCapability("platform",
platform);

// unique user-specified name
caps.setCapability("applicationName",
platform + "-" + browser);

if ( browser.contains("iphone") ) {
mobileDriver.set(new IOSDriver<MobileElement>
(new URL(remoteHubURL),
caps));
}

else {
mobileDriver.set(new AndroidDriver<MobileElement>
(new URL(remoteHubURL),
caps));
}
}

Third-party grid architecture support including the Sauce Labs Test Cloud

When adding support to the driver class for third-party grids such as Sauce Labs or Perfecto Mobile, users must add conditions in the driver class that set specific preferences, credentials, URLs, and so on, to direct traffic to that test platform. They are really just other Selenium grids to run against in the cloud, which free up the tester from all the maintenance requirements of an in-house grid. The condition to run on one of these third-party platforms can be passed as a parameter to the test, specifically environment. For instance, here is an example of a TestNG XML file using parameters to set up the driver:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="My Test Suite" preserve-order="true" parallel="false" thread-count="1" verbose="2">

<!-- suite parameters -->
<!-- "local", "remote", "saucelabs" -->
<parameter name="environment" value="saucelabs" />

<test name="My Feature Test">
<!-- test parameters -->
<parameter name="browser" value="chrome" />
<parameter name="platform" value="Windows 10" />

or

<parameter name="browser" value="iphone"/>
<parameter name="platform" value="iphone"/>

<classes>
<class name="com.myproject.MyTest" />
</classes>
</test>
</suite>

Each provider will require a different RemoteWebDriver URL, credentials to access their test cloud, preferences, and various other features that would allow access to a DMZ inside a corporate Firewall. Here are some examples of specific Sauce Labs Cloud platform requirements:

  • Tunnel: If the web server, or any other servers, are behind a corporate Firewall and not open to the internet, then a unique tunnel will have to be set up and passed to the driver class as a Desired Capability.
  • Remote URL: Sauce Labs has its own RemoteWebDriver URL for accessing its server at http://SAUCE_USERNAME:[email protected]:80/wd/hub.
  • Preferences: Sauce Labs has a set of unique capabilities that allow the passing of when creating the driver for the test. Examples include screen resolution, browser versions (including latest and beta versions), mobile device types (including physical and simulator/emulator devices), Selenium versions, driver versions, session parameters, results processing, and so on.
The Sauce Labs Wiki documentation, which includes Desired Capabilities and Platform Configurator, is located at https://wiki.saucelabs.com/.
// third party preferences for SauceLabs...

if ( environment.equalsIgnoreCase("saucelabs") ) {
// setup the Selenium Grid capabilities...
String remoteHubURL =
"http://SAUCE_USERNAME:SAUCE_ACCESS_KEY
@ondemand.saucelabs.com:80/wd/hub
";

caps.setCapability("screenResolution",
"1920x1080");
caps.setCapability("recordVideo",
false);
caps.setCapability("tunnelIdentifier",
System.getProperty("TUNNEL_IDENTIFIER"));
...
}

Using property files to select browsers, devices, versions, platforms, languages, and many more

Rather than hardcoding default URLs, paths, revisions, mobile device settings, and so on into the driver class itself, it makes more sense to encapsulate all those settings into a properties file. This way, users do not have to traverse through code to change a setting, driver version, or any paths required to support running the driver across platforms such as Windows, iOS, and Linux. Also, different sets of properties can be stored in the file for different environments such as local, remote, or third-party grids. Properties can be stored and retrieved in Java using the Properties class. The following code examples show property file formats, and the use of properties files in the Selenium driver class:

// Properties Class
public class CreateDriver {
private Properties driverProps = new Properties();
private static final String propertyFile = new File
("../myProject/com/path/selenium.properties").getAbsolutePath();

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

DesiredCapabilities caps = null;

// load properties from file...
driverProps.load(new FileInputStream(propertyFile));


switch (browser) {
case "firefox":
caps = DesiredCapabilities.firefox();

// see previous example for caps...
if ( environment.equalsIgnoreCase("local") ) {
if ( platform.toLowerCase().contains("windows") ) {
System.setProperty("webdriver.gecko.driver",
driverProps.getProperty(
"gecko.driver.windows.path"));

}

webDriver.set(new FirefoxDriver(caps));
}

break;
}
}

Here is the selenium.properties file:

// selenium.properties file
# Selenium 3 WebDriver/AppiumDriver Properties File

# Revisions
selenium.revision=3.4.0
chrome.revision=2.30
safari.revision=2.48.0
gecko.revision=0.17.1

# Firefox Settings
gecko.driver.windows.path=../path/geckodriver-v0.17.1-win64/geckodriver.exe
gecko.driver.linux.path=../path/geckodriver-v0.17.1-linux64/geckodriver
gecko.driver.mac.path=../path/geckodriver-v0.17.1-macos/geckodriver

Summary

The Selenium driver class is the "engine" that controls the browser or mobile device under test. It determines which driver type to create, the look and feel of the driver, the default preferences, multithreading capabilities, settings, and whether to run the test locally or on the Selenium grid. It is a self-contained singleton class that creates one instance of the driver that is used throughout the entire test run. All session parameters are retrievable throughout the run, and they can be tracked to allow multiple drivers to run concurrently, in a browser-to-mobile test, or in a parallel/distributed environment.

As we progress through the framework components, users will see how important this class becomes to the integrity of the test. We will start by designing and building utility classes to support the framework.

Left arrow icon Right arrow icon
Download code icon Download Code

Key benefits

  • • A comprehensive guide to designing data-driven test frameworks using the Selenium 3 WebDriver API, AppiumDriver API, Java-Bindings, and TestNG
  • • Learn how to use Selenium Page Object Design Patterns and D.R.Y. (Don’t Repeat Yourself) Approaches to software development in automated testing
  • • Discover the Selenium Grid Architecture and build your own grid for browser and mobile devices
  • • Use third party tools and services like ExtentReports for results processing, reporting, and SauceLabs for cloud-based test services

Description

The Selenium WebDriver 3.x Technology is an open source API available to test both Browser and Mobile applications. It is completely platform independent in that tests built for one browser or mobile device, will also work on all other browsers and mobile devices. Selenium supports all major development languages which allow it to be tied directly into the technology used to develop the applications. This guide will provide a step-by-step approach to designing and building a data-driven test framework using Selenium WebDriver, Java, and TestNG. The book starts off by introducing users to the Selenium Page Object Design Patterns and D.R.Y Approaches to Software Development. In doing so, it covers designing and building a Selenium WebDriver framework that supports both Browser and Mobile Devices. It will lead the user through a journey of architecting their own framework with a scalable driver class, Java utility classes, JSON Data Provider, Data-Driven Test Classes, and support for third party tools and plugins. Users will learn how to design and build a Selenium Grid from scratch to allow the framework to scale and support different browsers, mobile devices, versions, and platforms, and how they can leverage third party grids in the Cloud like SauceLabs. Other topics covered include designing abstract base and sub-classes, inheritance, dual-driver support, parallel testing, testing multi-branded applications, best practices for using locators, and data encapsulation. Finally, you will be presented with a sample fully-functional framework to get them up and running with the Selenium WebDriver for browser testing. By the end of the book, you will be able to design your own automation testing framework and perform data-driven testing with Selenium WebDriver.

Who is this book for?

This book is intended for software quality assurance/testing professionals, software project managers, or software developers with prior experience in using Selenium and Java to test web-based applications.This book is geared towards the quality assurance and development professionals responsible for designing and building enterprise-based testing frameworks.The user should have a working knowledge of the Java, TestNG, and Selenium technologies

What you will learn

  • • Design the Selenium Driver Class for local, remote, and third party grid support
  • • Build Page Object Classes using the Selenium Page Object Model
  • • Develop Data-Driven Test Classes using the TestNG framework
  • • Encapsulate Data using the JSON Protocol
  • • Build a Selenium Grid for RemoteWebDriver Testing
  • • Construct Utility Classes for use in Synchronization, File I/O, Reporting and Test Listener Classes
  • • Run the sample framework and see the benefits of a live data-driven framework in real-time

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Jan 23, 2018
Length: 354 pages
Edition : 1st
Language : English
ISBN-13 : 9781788473576
Vendor :
Selenium
Languages :
Concepts :
Tools :

What do you get with a Packt Subscription?

Free for first 7 days. $19.99 p/m after that. Cancel any time!
Product feature icon Unlimited ad-free access to the largest independent learning library in tech. Access this title and thousands more!
Product feature icon 50+ new titles added per month, including many first-to-market concepts and exclusive early access to books as they are being written.
Product feature icon Innovative learning tools, including AI book assistants, code context explainers, and text-to-speech.
Product feature icon Thousands of reference materials covering every tech concept you need to stay up to date.
Subscribe now
View plans & pricing

Product Details

Publication date : Jan 23, 2018
Length: 354 pages
Edition : 1st
Language : English
ISBN-13 : 9781788473576
Vendor :
Selenium
Languages :
Concepts :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 141.97
Mastering Selenium WebDriver 3.0
$48.99
Selenium WebDriver 3 Practical Guide
$43.99
Selenium Framework Design in Data-Driven Testing
$48.99
Total $ 141.97 Stars icon
Banner background image

Table of Contents

10 Chapters
Building a Scalable Selenium Test Driver Class for Web and Mobile Applications Chevron down icon Chevron up icon
Selenium Framework Utility Classes Chevron down icon Chevron up icon
Best Practices for Building Selenium Page Object Classes Chevron down icon Chevron up icon
Defining WebDriver and AppiumDriver Page Object Elements Chevron down icon Chevron up icon
Building a JSON Data Provider Chevron down icon Chevron up icon
Developing Data-Driven Test Classes Chevron down icon Chevron up icon
Encapsulating Data in Data-Driven Testing Chevron down icon Chevron up icon
Designing a Selenium Grid Chevron down icon Chevron up icon
Third-Party Tools and Plugins Chevron down icon Chevron up icon
Working Selenium WebDriver Framework Samples Chevron down icon Chevron up icon

Customer reviews

Top Reviews
Rating distribution
Full star icon Full star icon Full star icon Full star icon Half star icon 4.4
(13 Ratings)
5 star 69.2%
4 star 7.7%
3 star 15.4%
2 star 7.7%
1 star 0%
Filter icon Filter
Top Reviews

Filter reviews by




Susheel Gawande Feb 22, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Very well written for someone who is beginning to learn working on Selenium as well as advancing to refining and enhancing knowledge. It presents a good information recipe to accomplish the Selenium Framework Design in Data-Driven Testing. I am highly recommending this book.
Amazon Verified review Amazon
MobileMojo Feb 17, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Fantastic technical resource by an industry expert in building Web and mobile test automation frameworks! The book takes a logical approach to designing Selenium frameworks and covers every aspect along the way. The code samples are essential! No other book offers the coverage this one does, just buy it!
Amazon Verified review Amazon
KT Feb 16, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is really helpful. Data driven testing model makes more sense to me. I like the DRY (Don't Repeat Yourself) approach. The downloadable code samples as well as those in print are clearly commented/documented, which is a big help.
Amazon Verified review Amazon
RAJ Jun 14, 2018
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is for someone who actually knows webdriver and java and who wish to develop a framework, this is not for beginners
Amazon Verified review Amazon
Alexey Solovyev Aug 29, 2021
Full star icon Full star icon Full star icon Full star icon Full star icon 5
For me, this book turned out to be a logical and expected continuation of another book "Learning Selenium" from the same publisher. In the same book, information is presented in a clear and understandable form. Everything is described: from creating the first classes to set up a ready-made data-driven test framework. Everything is in demand, everything is needed and everything is on business. I am happy to apply the knowledge from the book in my work! Thank's to the author!
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is included in a Packt subscription? Chevron down icon Chevron up icon

A subscription provides you with full access to view all Packt and licnesed content online, this includes exclusive access to Early Access titles. Depending on the tier chosen you can also earn credits and discounts to use for owning content

How can I cancel my subscription? Chevron down icon Chevron up icon

To cancel your subscription with us simply go to the account page - found in the top right of the page or at https://subscription.packtpub.com/my-account/subscription - From here you will see the ‘cancel subscription’ button in the grey box with your subscription information in.

What are credits? Chevron down icon Chevron up icon

Credits can be earned from reading 40 section of any title within the payment cycle - a month starting from the day of subscription payment. You also earn a Credit every month if you subscribe to our annual or 18 month plans. Credits can be used to buy books DRM free, the same way that you would pay for a book. Your credits can be found in the subscription homepage - subscription.packtpub.com - clicking on ‘the my’ library dropdown and selecting ‘credits’.

What happens if an Early Access Course is cancelled? Chevron down icon Chevron up icon

Projects are rarely cancelled, but sometimes it's unavoidable. If an Early Access course is cancelled or excessively delayed, you can exchange your purchase for another course. For further details, please contact us here.

Where can I send feedback about an Early Access title? Chevron down icon Chevron up icon

If you have any feedback about the product you're reading, or Early Access in general, then please fill out a contact form here and we'll make sure the feedback gets to the right team. 

Can I download the code files for Early Access titles? Chevron down icon Chevron up icon

We try to ensure that all books in Early Access have code available to use, download, and fork on GitHub. This helps us be more agile in the development of the book, and helps keep the often changing code base of new versions and new technologies as up to date as possible. Unfortunately, however, there will be rare cases when it is not possible for us to have downloadable code samples available until publication.

When we publish the book, the code files will also be available to download from the Packt website.

How accurate is the publication date? Chevron down icon Chevron up icon

The publication date is as accurate as we can be at any point in the project. Unfortunately, delays can happen. Often those delays are out of our control, such as changes to the technology code base or delays in the tech release. We do our best to give you an accurate estimate of the publication date at any given time, and as more chapters are delivered, the more accurate the delivery date will become.

How will I know when new chapters are ready? Chevron down icon Chevron up icon

We'll let you know every time there has been an update to a course that you've bought in Early Access. You'll get an email to let you know there has been a new chapter, or a change to a previous chapter. The new chapters are automatically added to your account, so you can also check back there any time you're ready and download or read them online.

I am a Packt subscriber, do I get Early Access? Chevron down icon Chevron up icon

Yes, all Early Access content is fully available through your subscription. You will need to have a paid for or active trial subscription in order to access all titles.

How is Early Access delivered? Chevron down icon Chevron up icon

Early Access is currently only available as a PDF or through our online reader. As we make changes or add new chapters, the files in your Packt account will be updated so you can download them again or view them online immediately.

How do I buy Early Access content? Chevron down icon Chevron up icon

Early Access is a way of us getting our content to you quicker, but the method of buying the Early Access course is still the same. Just find the course you want to buy, go through the check-out steps, and you’ll get a confirmation email from us with information and a link to the relevant Early Access courses.

What is Early Access? Chevron down icon Chevron up icon

Keeping up to date with the latest technology is difficult; new versions, new frameworks, new techniques. This feature gives you a head-start to our content, as it's being created. With Early Access you'll receive each chapter as it's written, and get regular updates throughout the product's development, as well as the final course as soon as it's ready.We created Early Access as a means of giving you the information you need, as soon as it's available. As we go through the process of developing a course, 99% of it can be ready but we can't publish until that last 1% falls in to place. Early Access helps to unlock the potential of our content early, to help you start your learning when you need it most. You not only get access to every chapter as it's delivered, edited, and updated, but you'll also get the finalized, DRM-free product to download in any format you want when it's published. As a member of Packt, you'll also be eligible for our exclusive offers, including a free course every day, and discounts on new and popular titles.