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 Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
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
Estimated delivery fee Deliver to Ecuador

Standard delivery 10 - 13 business days

$19.95

Premium delivery 3 - 6 business days

$40.95
(Includes tracking information)

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 Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Ecuador

Standard delivery 10 - 13 business days

$19.95

Premium delivery 3 - 6 business days

$40.95
(Includes tracking information)

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 the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact [email protected] with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at [email protected] using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on [email protected] with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on [email protected] within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on [email protected] who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on [email protected] within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela