Book Image

Selenium Framework Design in Data-Driven Testing

By : Carl Cocchiaro
Book Image

Selenium Framework Design in Data-Driven Testing

By: Carl Cocchiaro

Overview of this book

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.
Table of Contents (15 chapters)
Title Page
Dedication
Packt Upsell
Contributors
Preface

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

Note

The Oracle Java doc for varargs is located at https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html.

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