The configuration of Selenium Foundation projects is an aggregation of several factors:
- Project specification (e.g. -
pom.xml
,build.gradle
) - ServiceLoader provider configuration files:
- Specification of driver plug-ins for local Grid
- Specification of TestNG listener classes
- Specification of JUnit watcher classes
- Configuration settings for...
- ... Selenium Foundation (settings.properties)
- ... TestNG Foundation (testng.properties)
- ... JUnit Foundation (junit.properties)
Note that configuration settings can be overridden via System properties, and reasonable defaults are provided where they make sense. More on this in the next section.
Each release of Selenium Foundation is published in two flavors: s2
for Selenium 2 and s3
for Selenium 3. Most of the code in this project is version-agnostic, built on interfaces that are consistent between the two major versions of the Selenium API. Functionality implemented with interfaces that differ between Selenium 2 and Selenium 3 is contained in flavor-specific folders in the Selenium Foundation project (java-s2
and java-s3
). These features include:
- Concrete configuration:
com.nordstrom.automation.selenium.SeleniumConfig
- Driver wrapper:
com.nordstrom.automation.selenium.interfaces.WrapsDriver
- JSON data utility:
com.nordstrom.automation.selenium.utility.DataUtils
- Local Grid driver plug-ins:
com.nordstrom.automation.selenium.plugins.*
SeleniumConfig
declares settings and methods related to Selenium WebDriver and Grid configuration. This class is built on the Settings API, composed of defaults, stored values, and System properties. SeleniumSettings
declares the constants, property names, and default values for the settings managed by SeleniumConfig
. Defaults can be overridden via System properties or the settings.properties file typically found in your user "home" directory.
The configuration object itself is maintained as a static singleton, ubiquitously available through a static method of the SeleniumConfig
class:
SeleniumConfig config = SeleniumConfig.getConfig();
SeleniumConfig
searches a series of locations for a settings.properties file. This file will typically be stored in your user "home" folder. Any settings declared in this file will override the defaults assigned in the SeleniumSettings
enumeration. Settings that are declared as System properties will override both the defaults assigned by SeleniumSettings
and settings declared in settings.properties. For example:
settings.properties |
---|
selenium.target.host=my.server.com |
selenium.browser.name=chrome |
This sample settings.properties file overrides the values of TARGET_HOST
and BROWSER_NAME
. The latter can be overridden by System property declaration:
-Dselenium.browser.name=firefox
The hierarchy of evaluation produces the following results:
BROWSER_NAME
= firefox;TARGET_HOST
= my.server.com;TARGET_PATH
= /
As mentioned previously, you're able to override defaults in SeleniumConfig
with values defined in a settings.properties file. This file is typically stored in your user "home" folder, but Selenium Foundation employs a file location strategy that searches for settings.properties in a number of places. This strategy is described in detail under DEFAULT_LOCATION_STRATEGY in the documentation for Apache Commons Configuration.
SeleniumConfig
is more than a collection of settings; this class also provides generic interfaces to several core aspects of the WebDriver API for Selenium 3:
- Convert JSON string to
Capabilities
object:getCapabilitiesForJson(String capabilities)
- Convert object to JSON string:
toJson(Object obj)
- Get context class names for Grid dependencies:
getDependencyContexts()
- Create Grid node configuration file from JSON:
createNodeConfig(String jsonStr, URL hubUrl)
- Merge capabilities objects:
mergeCapabilities(Capabilities target, Capabilities change)
The static getConfig()
method returns a SeleniumConfig
object that provides settings and methods related to Selenium WebDriver and Grid configuration. The individual settings managed by SeleniumConfig
are declared by the SeleniumSettings
enumeration. The following sections provide the details of these settings - constants, property names, defaults, interrelationships, and utilization.
Setting | Property Name | Default |
---|---|---|
HUB_HOST |
selenium.hub.host |
(none) |
GRID_PLUGINS |
selenium.grid.plugins |
none |
The HUB_HOST
setting specifies the URL of the Selenium Grid hub server that will supply sessions for your tests. No default value is specified for this setting. If you specify a value for this setting, you must provide the full URL of an active hub server, including the base path. For example:
-Dselenium.hub.host=http://192.168.1.2/wd/hub
If this setting is left undefined or specifies an inactive
localhost
URL, Selenium Foundation will automatically launch a local Grid instance as specified by the local Grid configuration.
The GRID_PLUGINS
setting specifies a semicolon-delimited list of fully-qualified names of local Selenium Grid driver plugin classes.
NOTE: Defining a value for this setting overrides the ServiceLoader specification defined by the associated provider configuration file (com.nordstrom.automation.selenium.DriverPlugin).
SeleniumConfig
provides several methods related to local and remote Selenium Grid configuration:
getSeleniumGrid()
- Get an object that represents the active Selenium Grid. If indicated, this method wil launch a local Grid instance.getHubUrl()
- Get the URL for the configured Selenium Grid hub host. In local Grid configurations, this value will be populated when the Grid is launched.shutdownGrid(boolean localOnly)
- Shut down the active Selenium Grid. To enable shutdown of remote Grid instances, attached Grid nodes must install theLifecycleServlet
:
-servlets org.openqa.grid.web.servlet.LifecycleServlet
By default, the unit tests are configured to run the "support" tests, which don't require browser sessions. The local Grid instance launched for this configuration runs in "servlet container" mode. The Gradle project file defines a set of profiles, one for each supported browser, which specify the corresponding dependencies, settings, and driver plugin needed to run the unit tests for that browser.
Profile | Browser / Appium Engine |
---|---|
chrome | Google Chrome |
edge | Microsoft Edge |
espresso | Android Espresso engine (Appium) |
firefox | Mozilla Firefox |
htmlunit | Gargoyle HtmlUnit |
mac2 | Macintosh Mac2 engine (Appium) |
opera | Opera |
phantomjs | PhantomJS |
safari | Apple Safari |
uiautomator2 | Android UiAutomator2 engine (Appium) |
windows | Microsoft Windows engine (Appium) |
xcuitest | Apple iOS engine (Appium) |
To run the unit tests on a specific browser, add the corresponding option to the Gradle or mvn-build.sh
command line:
Test Runner | Command Line Example | Description |
---|---|---|
Gradle | ./gradlew test -Pbrowsers=htmlunit |
Run Selenium Foundation unit tests on the HtmlUnit headless browser |
mvn-build |
./mvn-build.sh -b espresso |
Build Selenium Foundation and run the Android Espresso unit tests |
Selenium Foundation provides the ability to drive web applications through common desktop browsers. Currently, plug-ins are available for the following browsers:
Browser | Plug-In |
---|---|
Chrome | source |
Edge | source |
Firefox | source |
HtmlUnit | source |
Internet Explorer | source |
Opera | source |
PhantomJS | source |
Safari | source |
In addition to support for desktop browsers, Selenium Foundation provides the ability to drive mobile and desktop applications via Appium. Currently, plug-ins are available for the following automation engines:
Automation Engine | Plug-In |
---|---|
Espresso | source |
Mac2 | source |
UiAutomator2 | source |
Windows | source |
XCUITest | source |
Note that no Java dependencies are required for Selenium Foundation to launch the associated Grid node. However, you'll need to have Appium and its dependencies installed on your system. At a minimum, you need NodeJS
, NPM
(Node Package Manager), and Appium
itself. By default, Selenium Foundation will search for NodeJS
and NPM
on the system path, and expects to find Appium
in the global Node package repository. However, you can supply explicit paths to these item in your settings:
Item | Setting | Property | Default |
---|---|---|---|
NodeJS | NODE_BINARY_PATH |
node.binary.path |
NODE_BINARY_PATH environment variable |
NPM | NPM_BINARY_PATH |
npm.binary.path |
(none) |
Appium | APPIUM_BINARY_PATH |
appium.binary.path |
APPIUM_BINARY_PATH environment variable |
The getCurrentCapabilities()
method converts the configured browser settings into a Capabilities
object:
- If
BROWSER_NAME
is specified, Selenium Foundation uses this name to acquire aCapabilities
object from the active Selenium Grid. - Otherwise, the JSON configuration is acquired from
BROWSER_CAPS
, which can be either a file path (absolute, relative, or simple filename) or a direct value.
As indicated by the sequence above, the desired browser can be specified solely by name. This name can be associated with a Selenium Grid browser "personality", or it may simply specify the name associated with a particular browser by its corresponding driver. If browser name is omitted, a fully-specified JSON capabilities record is acquired from the settings collection.
The getCapabilitiesForName(String browserName)
method enables you to get a Capabilities
object for a specified name or "personality" from the active Selenium Grid. This bypasses the configured default browser specification, allowing you to acquire browser sessions of any type supported by the active Grid.
The easiest way to provide non-default browser sessions to your test methods is to implement the DriverProvider interface:
public class MyChromeTest extends TestNgBase implements DriverProvider {
...
@Override
public WebDriver provideDriver(Method method) {
SeleniumConfig config = SeleniumConfig.getConfig();
URL remoteAddress = config.getSeleniumGrid().getHubServer().getUrl();
Capabilities desiredCapabilities = config.getCapabilitiesForName("chrome");
return GridUtility.getDriver(remoteAddress, desiredCapabilities);
}
}
With this implementation, every test method will be provided with a Chrome browser session regardless of configured default browser specification. Note that the active Selenium Grid must be configured to support Chrome for this to actually work.
SeleniumConfig
provides a getTargetUri()
method that assembles the URI of the target application from five discrete settings:
Constant | Property Name | Default |
---|---|---|
TARGET_SCHEME |
selenium.target.scheme | http |
TARGET_CREDS |
selenium.target.creds | (none) |
TARGET_HOST |
selenium.target.host | localhost |
TARGET_PORT |
selenium.target.port | (none) |
TARGET_PATH |
selenium.target.path | / |
TARGET_PORT
enables you to specify a non-default port number. TARGET_PATH
enables you to specify a base path from which all pages originate. TARGET_CREDS
is used to provide credentials in standard URL format.
There's also a setTargetUri(URI targetUrl)
method that enables you to set this core value and its component settings dynamically. The Selenium Foundation unit tests use this method to set the root of their page navigations to the hub server of the local Grid instance.
The following table documents the timeout settings defined by Selenium Foundation:
Constant | Property Name | Default | Description |
---|---|---|---|
PAGE_LOAD_TIMEOUT |
selenium.timeout.pageload | 30 | Driver page load timeout interval; also used by page load completion and landing page verification features. |
IMPLIED_TIMEOUT |
selenium.timeout.implied | 15 | Driver implicit wait timeout interval; also used by stale element reference refresh feature. |
SCRIPT_TIMEOUT |
selenium.timeout.script | 30 | Driver asynchronous script timeout interval. |
WAIT_TIMEOUT |
selenium.timeout.wait | 15 | Selenium Foundation search context wait timeout interval. |
HOST_TIMEOUT |
selenium.timeout.host | 30 | Selenium Foundation HTTP host wait timeout interval. |
Typically, these settings are not accessed directly. Rather, they are proxied through the WaitType
enumeration to streamline the process of reading the timeout intervals and acquiring search context wait objects.
Written with StackEdit.