com.paypal.selion.configuration.Config Maven / Gradle / Ivy
/*-------------------------------------------------------------------------------------------------------------------*\
| Copyright (C) 2014-2016 PayPal |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance |
| with the License. |
| |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software distributed under the License is distributed |
| on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for |
| the specific language governing permissions and limitations under the License. |
\*-------------------------------------------------------------------------------------------------------------------*/
package com.paypal.selion.configuration;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.lang.StringUtils;
import org.openqa.selenium.remote.CommandExecutor;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.testng.ISuite;
import org.testng.ITestContext;
import com.paypal.selion.internal.platform.grid.MobileNodeType;
import com.paypal.selion.logger.SeLionLogger;
import com.paypal.selion.platform.grid.EventListener;
import com.paypal.selion.platform.grid.browsercapabilities.DefaultCapabilitiesBuilder;
import com.paypal.selion.platform.html.support.events.ElementEventListener;
/**
* A configuration object that contains properties needed throughout SeLion. These options can be configured via the
* TestNG formatted testng-suite.xml file. The testng-suite.xml file is used to override the default settings, so only
* the data you want to modify from default values should be specified in the suite configuration file. Any data not
* found in the testng-suite.xml file will use the built-in defaults.
*
* Note that some configuration properties are global-only in scope. Any value set for these applies to all suite tests
* executed (possibly in parallel). Properties that must be specified for global use are specified below with
* "(GLOBAL)". These properties cannot be used in SeLionLocal configuration instances. The others can be specified for
* Global or Local (test) scope.
*
*
*
* <!-- If parameter is empty string or omitted, please see defaults -->
*
* <!-- SELENIUM CONFIGURATION -->
*
* <!-- optional, defaults to "" or localhost when runLocally is true (GLOBAL) -->
* <parameter name="seleniumhost" value="" />
* <!-- optional, defaults to 4444 (GLOBAL) -->
* <parameter name="seleniumport" value="" />
* <!-- optional, defaults to *firefox -->
* <parameter name="browser" value="*firefox" />
* <!-- optional, defaults to false (GLOBAL) -->
* <parameter name="runLocally" value="true" />
* <!-- optional, turns automatic screen shots for click handlers on/off, defaults to true (GLOBAL) -->
* <parameter name="autoScreenShot" value="true" />
* <!-- optional, used when runLocally is true, defaults to 'default' -->
* <parameter name="profileName" value="SeleniumProfile" />
*
* <!-- SELION FILES LOCATION -->
*
* <!-- optional, default to selionFiles (GLOBAL) -->
* <parameter name="basedir" value="" />
* <!-- optional, default to ${selionFiles.basedir}/selionLogs (GLOBAL) -->
* <parameter name="workDir" value="" />
*
*
* All other configuration settings can be set in a similar fashion.
*
*
* Also, system properties and/or environment variables can also be used to configure SeLion. The values used should
* always start with "SELION_" and end with the value you would like the set. The variable equals the
* {@link ConfigProperty} variable name. So, for instance, to set the execution_timeout to "180000", the following
* system property or environment variable should be set prior to initializing SeLion:
*
*
* SELION_EXECUTION_TIMEOUT = 180000
*
*
* The order of initialization for Configuration values is
*
* - System properties (Highest Precedence)
*
- Environment variables
* - From a testng-suite.xml file
* - SeLion defaults
*
*/
public final class Config {
private static volatile XMLConfiguration xmlConfig;
private Config() {
// Utility class. So hide the constructor
}
static XMLConfiguration getConfig() {
if (xmlConfig != null) {
return xmlConfig;
}
initConfig();
return xmlConfig;
}
/**
* Parses suite parameters and generates SeLion Config object
*
* @param suite
* list of parameters from configuration file within <suite></suite> tag
*/
public synchronized static void initConfig(ISuite suite) {
SeLionLogger.getLogger().entering(suite);
Map initialValues = new HashMap();
for (ConfigProperty prop : ConfigProperty.values()) {
String paramValue = suite.getParameter(prop.getName());
// empty values may be valid for some properties
if (paramValue != null) {
initialValues.put(prop, paramValue);
}
}
initConfig(initialValues);
SeLionLogger.getLogger().exiting();
}
/**
* Parses configuration file and extracts values for test environment
*
* @param context
* list of parameters includes values within <suite></suite> and <test></test>
* tags
*/
public synchronized static void initConfig(ITestContext context) {
SeLionLogger.getLogger().entering(context);
Map initialValues = new HashMap();
Map testParams = context.getCurrentXmlTest().getLocalParameters();
if (!testParams.isEmpty()) {
for (ConfigProperty prop : ConfigProperty.values()) {
// Check if a selionConfig param resides in the
String newValue = testParams.get(prop.getName());
// accept param values that are empty in initialValues.
if (newValue != null) {
initialValues.put(prop, newValue);
}
}
}
ConfigManager.addConfig(context.getCurrentXmlTest().getName(), new LocalConfig(initialValues));
SeLionLogger.getLogger().exiting();
}
/**
* Reads and parses configuration file Initializes the configuration, reloading all data
*/
public synchronized static void initConfig() {
SeLionLogger.getLogger().entering();
Map initialValues = new HashMap();
initConfig(initialValues);
SeLionLogger.getLogger().exiting();
}
/**
* Prints SeLion Config Values
*/
public static void printSeLionConfigValues() {
SeLionLogger.getLogger().entering();
StringBuilder builder = new StringBuilder("SeLion configuration: {");
boolean isFirst = true;
for (ConfigProperty configProperty : ConfigProperty.values()) {
if (!isFirst) {
builder.append(", ");
}
builder.append(String.format("(%s: %s)", configProperty,
Config.getConfig().getString(configProperty.getName())));
isFirst = false;
}
builder.append("}\n");
SeLionLogger.getLogger().info(builder.toString());
SeLionLogger.getLogger().exiting();
}
private static void loadInitialValues() {
for (ConfigProperty configProps : ConfigProperty.values()) {
xmlConfig.setProperty(configProps.getName(), configProps.getDefaultValue());
}
}
private static void loadValuesFromUser(Map initialValues) {
if (!initialValues.isEmpty()) {
for (Entry eachConfig : initialValues.entrySet()) {
xmlConfig.setProperty(eachConfig.getKey().getName(), eachConfig.getValue());
}
}
}
private static void loadValuesFromEnvironment() {
final String PREFIX = "SELION_";
for (ConfigProperty configProps : ConfigProperty.values()) {
String envValue = System.getenv(PREFIX + configProps.name());
if (StringUtils.isNotBlank(envValue)) {
xmlConfig.setProperty(configProps.getName(), envValue);
}
// Now load system properties variables (if defined).
String sysValue = System.getProperty(PREFIX + configProps.name());
if (StringUtils.isNotBlank(sysValue)) {
xmlConfig.setProperty(configProps.getName(), sysValue);
}
}
}
/**
* Initializes the configuration, reloading all data while adding the supplied initialValues to the
* configuration.
*
* @param initialValues
* The initial set of values used to configure SeLion
*/
public synchronized static void initConfig(Map initialValues) {
SeLionLogger.getLogger().entering(initialValues);
// only do this if the global config is not already initialized.
if (xmlConfig == null) {
xmlConfig = new XMLConfiguration();
// don't auto throw, let each config value decide
xmlConfig.setThrowExceptionOnMissing(false);
// because we can config on the fly, don't auto-save
xmlConfig.setAutoSave(false);
// Set defaults
loadInitialValues();
}
/*
* otherwise, update the global config
*/
// Load in our supplied values (if defined)
loadValuesFromUser(initialValues);
// Load in environment & system variables (if defined)
loadValuesFromEnvironment();
// Init Selenium configuration
boolean runLocally = xmlConfig.getBoolean(ConfigProperty.SELENIUM_RUN_LOCALLY.getName());
if (runLocally) {
xmlConfig.setProperty(ConfigProperty.SELENIUM_HOST.getName(), "localhost");
}
SeLionLogger.getLogger().exiting();
}
/**
* Returns a configuration property String value based off the {@link ConfigProperty}
*
* @param configProperty
* The configuration property value to return
* @return The configuration property String value
*/
public static String getConfigProperty(ConfigProperty configProperty) {
checkArgument(configProperty != null, "Config property cannot be null");
return Config.getConfig().getString(configProperty.getName());
}
/**
* Returns a configuration property String value based off the {@link ConfigProperty}
*
* @param configProperty
* String Property Name
* @return The configuration property String values
*/
public static String getConfigProperty(String configProperty) {
checkArgument(configProperty != null, "Config property cannot be null");
return Config.getConfig().getString(configProperty);
}
/**
* Returns a configuration property int value based off the {@link ConfigProperty}
*
* @param configProperty
* The configuration property value to return
* @return The configuration property int value
*/
public static int getIntConfigProperty(ConfigProperty configProperty) {
checkArgument(configProperty != null, "Config property cannot be null");
return Config.getConfig().getInt(configProperty.getName());
}
/**
* Returns a configuration property boolean value based off the {@link ConfigProperty}
*
* @param configProperty
* The configuration property value to return
* @return The configuration property boolean value
*/
public static boolean getBoolConfigProperty(ConfigProperty configProperty) {
checkArgument(configProperty != null, "Config property cannot be null");
return Config.getConfig().getBoolean(configProperty.getName());
}
/**
* Checks if property exists in the configuration
*
* @param propertyName
* String Property Name
* @return true or false
*/
public static boolean checkPropertyExists(String propertyName) {
checkArgument(propertyName != null, "Property name cannot be null");
return Config.getConfig().containsKey(propertyName);
}
/**
* Sets a SeLion configuration value. This is useful when you want to override or set a setting.
*
* @param configProperty
* The configuration element to set
* @param configPropertyValue
* The value of the configuration element
* @throws IllegalArgumentException
* If problems occur during the set
*/
public static synchronized void setConfigProperty(ConfigProperty configProperty, String configPropertyValue) {
checkArgument(configProperty != null, "Config property cannot be null.");
checkArgument(configPropertyValue != null, "Config property value cannot be null.");
Config.getConfig().setProperty(configProperty.getName(), configPropertyValue);
}
/**
* SeLion config properties
*/
public enum ConfigProperty {
// Settings specific to SeLion
/**
* Automatically take screen shots.
*/
AUTO_SCREEN_SHOT("autoScreenShot", "true", true),
/**
* Selenium host might be localhost or another location where a Selenium server is running. Used when
* {@link ConfigProperty#SELENIUM_RUN_LOCALLY} is false.
* Default is set to ""
*/
SELENIUM_HOST("seleniumhost", "", true),
/**
* Selenium port, any port where Selenium is running. Used when {@link ConfigProperty#SELENIUM_RUN_LOCALLY}
* is false
* Default is set to 4444
*/
SELENIUM_PORT("seleniumport", "4444", true),
/**
* The firefox profile that is to be used for local/remote runs.
* Use this when you would like to have firefox work with your custom firefox profile.
* You can either specify the name of the profile or you can specify the directory location of your firefox
* profile.
* The framework internally first assumes it to be a profile name. If that assumption fails we fail-over to
* assuming it to be the firefox profile directory. If that also fails we will work with an anonymous firefox
* profile.
*
* WARNING:
* Please be aware that if your firefox profile directory is very huge (above ~10 MB) then there are chances
* that it can crash your local JVM (be it your desktop or your fusion build job).
*/
SELENIUM_FIREFOX_PROFILE("firefoxProfile", "", false),
/**
* The name of the JSON file that contains the configuration customization info needed for saucelabs. By
* default, the configurations specified at Sauce labs
* Configurations are applicable.
*/
SELENIUM_SAUCELAB_GRID_CONFIG_FILE("saucelabGridConfigFile", "", true),
/**
* The path to the chromedriver executable on the local machine. This parameter is taken into consideration for
* local runs involving the Google Chrome browser.
*/
SELENIUM_CHROMEDRIVER_PATH("chromeDriverPath", "", true),
/**
* The path to the PhantomJS executable on the local machine. This parameter is taken into consideration for
* local runs involving the PhantomJS browser.
*/
SELENIUM_PHANTOMJS_PATH("phantomjsPath", "", true),
/**
* The path to the IEDriver executable on the local machine. This parameter is taken into consideration for
* local runs involving the IE browser.
*/
SELENIUM_IEDRIVER_PATH("ieDriverPath", "", true),
/**
* The path to the EdgeDriver executable on the local machine. This parameter is taken into consideration for
* local runs involving the Edge browser.
*/
SELENIUM_EDGEDRIVER_PATH("edgeDriverPath", "", true),
/**
* Use this parameter to set the user agent for firefox when working with Mobile version. This parameter should
* be set in conjunction with the parameter {@link ConfigProperty#BROWSER}
*/
SELENIUM_USERAGENT("userAgent", "", false),
/**
* Use this parameter to set the Proxy server name to be used.
*/
SELENIUM_PROXY_HOST("proxyServerHost", "", true),
/**
* Use this parameter to set the Proxy server port to be used.
*/
SELENIUM_PROXY_PORT("proxyServerPort", "", true),
/**
* Use this parameter to indicate if your remote runs are to be run against the sauce lab grid or against your
* own grid. This flag is required when running against the Sauce lab grid because we need to disable fetching
* of the WebDriver node IP and Port details.
*/
SELENIUM_USE_SAUCELAB_GRID("useSauceLabGrid", "false", true),
/**
* Use this parameter to execute mobile test cases using respective mobile driver. The valid values are
* {@link MobileNodeType}
*/
MOBILE_NODE_TYPE("mobileNodeType", "", false),
/**
* Use this parameter to provide SeLion with a custom capabilities provider. The value for this parameter
* would be the fully qualified class name which is a sub-class of {@link DefaultCapabilitiesBuilder}.
* If more than one custom capabilities providers are required, please separate their fully qualified class
* names with commas.
*/
SELENIUM_CUSTOM_CAPABILITIES_PROVIDER("customCapabilities", "", true),
/**
* Use this parameter to provide SeLion with a custom listener which can be plugged into {@link RemoteWebDriver}
* {@link CommandExecutor}. If the fully qualified class implements {@link EventListener} then SeLion will
* invoke the custom implementation provided by you as and when the relevant events happen. If more than one
* custom listeners are required, please separate the fully qualified class names with commas.
*/
SELENIUM_WEBDRIVER_EVENT_LISTENER("webDriverEventListener", "", true),
/**
* Flip this parameter to true if you would like a browser to be spawned locally on your machine
* and run automation tests there. Default is set to false which means your tests are always going to be
* run against a Remote Grid environment as pointed to by {@link ConfigProperty#SELENIUM_HOST}.
*/
SELENIUM_RUN_LOCALLY("runLocally", "false", true),
/**
* This parameter represents the folder which would contain the mobile app. This parameter is currently only
* useful for local runs. This is the folder from which applications would be searched for by SeLion when it
* comes to mobile automation in local runs. Please ensure that all the built applications reside in this
* folder. If no value is provided, SeLion assumes that the application is available under a directory named
* "Applications" in the current working directory.
*/
MOBILE_APP_FOLDER("mobileAppFolder", System.getProperty("user.dir") + File.separator + "Applications", true),
/**
* This parameter represents the name of the app that is to be spawned. Specifying the name of the mobile app
* should suffice.
*
* Note: Use of this parameter is not recommended for test suites which test different mobile
* applications or different versions of the same mobile applications.
*/
MOBILE_APP_NAME("mobileAppName", "", false),
/**
* This parameter represents the fully qualified path of the app that is to be spawned. For app exist in the
* local disk this should be an absolute path, for app exist in the remote location it should be http URL and
* for app exist in sauce cloud it can be sauce storage like "sauce-storage:testApp.apk".
*/
MOBILE_APP_PATH("appPath", "", false),
/**
* This parameter represents the language to be used. By default it is always English represented
* as en
*/
MOBILE_APP_LANGUAGE("mobileAppLanguage", "en", false),
/**
* This parameter represents the locale to be used. By default it is always US English represented
* as en_US
*/
MOBILE_APP_LOCALE("mobileAppLocale", "en_US", false),
/**
* This parameter represents device.
*/
MOBILE_DEVICE("mobileDevice", "", false),
/**
* This parameter represents the device type.
*/
MOBILE_DEVICE_TYPE("mobileDeviceType", "", false),
/**
* Use this parameter to provide SeLion with a custom element listener that implements
* {@link ElementEventListener}. SeLion will invoke the custom implementation when the relevant events happen.
* If more than one custom listeners is needed, please separate the fully qualified class names with commas.
*/
ELEMENT_EVENT_LISTENER("elementEventListener", "", true),
/**
* This parameter is used to pass SauceLabs user name
*/
SAUCELAB_USER_NAME("sauceUserName", "", true),
/**
* This parameter is used to pass SauceLabs user name
*/
SAUCELAB_API_KEY("sauceApiKey", "", true),
/**
* This parameter is used to pass SauceLabs parent tunnel user id
*/
SAUCELAB_TUNNEL_USER_ID("sauceTunnelUserId", "", true),
/**
* This parameter is used to pass SauceLabs tunnel identifier
*/
SAUCELAB_TUNNEL_ID("sauceTunnelId", "", true),
/**
* Directory with page asset files to read info about GUI controls from.
* Default is set to GUIData in resources
*/
GUI_DATA_DIR("GUIDataDir", "GUIData", true),
/**
* Site will show country used for tests.
* Default is set to US
*/
SITE_LOCALE("siteLocale", "US", false),
/**
* mobile platform test suite is designed for (iOS or Android)
* Default is set to undefined
*/
MOBILE_PLATFORM("mobilePlatform", "undefined", false),
/**
* Browser specified by user.
* Default is set to firefox
*/
BROWSER("browser", "*firefox", false),
/**
* version specified by user when working with custom browser needs.
*/
BROWSER_CAPABILITY_VERSION("version", "", false),
/**
* Turn this flag ON to see GUI actions such as loading a URL, click/setting text etc., being logged into the
* test reports that get generated by SeLion.
*
*/
ENABLE_GUI_LOGGING("enableGUILogging", "false", true),
/**
* The base directory for SeLion files
* Default is set to selionFiles
*/
BASE_DIR("baseDir", "selionFiles", true),
/**
* The work directory of SeLion
*/
WORK_DIR("workDir", BASE_DIR.defaultValue + "/selionWorkDir", true),
/**
* platform is specified by user.
* Default is set to ANY Supporting values are: ANDROID, ANY, LINUX, MAC, UNIX, VISTA, WINDOWS, XP.
*/
BROWSER_CAPABILITY_PLATFORM("platform", "ANY", false),
/**
* Should javascript capability be enabled on the browser for the AUT. By default javascript will be enabled on
* the client browser, but this flag can be used to toggle this setting.
*/
BROWSER_CAPABILITY_SUPPORT_JAVASCRIPT("enableJavaScript", "true", false),
/**
* Set the Height of the Browser Window
* Should be a whole number
*/
BROWSER_HEIGHT("browserHeight", "", false),
/**
* Set the Width of the Browser Window
* Should be a whole number
*/
BROWSER_WIDTH("browserWidth", "", false),
/**
* Timeout for an execution command, in milliseconds.
*
* Used in SeLion to configure Selenium timeouts
* Default is set to 120000
*/
EXECUTION_TIMEOUT("executionTimeout", "120000", false),
/**
* Automatically attempt to download various webdriver dependencies (chromedriver, etc) if they are not
* available.
* Default is set to false
*/
DOWNLOAD_DEPENDENCIES("downloadDependencies", "false", true),
/**
* Timeout for downloading dependencies, in milliseconds.
*
* Used in SeLion to configure the download timeout
* Default is set to 600000
*/
DOWNLOAD_TIMEOUT("downloadTimeout", "600000", true),
/**
* Automatically log pages source code.
* Used in conjunction with {@link ConfigProperty#AUTO_SCREEN_SHOT}.
* Default is set to true
*/
LOG_PAGES("logPages", "true", true),
/**
* Maximum duration of a session duration in milliseconds. Session will be forcefully terminated if it takes
* longer.
* The value of this parameter is used as the value of sessionTimeout for ios-driver and selendroid.
* This configuration affects LOCAL EXECUTION RUNS only i.e., when {@link ConfigProperty#SELENIUM_RUN_LOCALLY}
* is set to true.
* The unit is milliseconds.
* Default is set to 1800000 milliseconds.
*/
MOBILE_DRIVER_SESSION_TIMEOUT("sessionTimeout", "1800000", false),
/**
* Selendroid Server port to use.
* Defaults to the value used by Selendroid (8080)
*/
SELENDROID_SERVER_PORT("selendroidServerPort", "8080", true),
/**
* Device Serial to use.
* Default is selected automatically by Selendroid
*/
SELENDROID_DEVICE_SERIAL("selendroidDeviceSerial", "", true),
/**
* Force Reinstall the Selendroid Server and AUT.
* Default is set to false
*/
SELENDROID_SERVER_FORCE_REINSTALL("selendroidServerForceReinstall", "false", true),
/**
* Timeout that will be used to start Android emulators.
* The value for this parameter is used as the value of timeoutEmulatorStart for selendroid.
* This configuration affects LOCAL EXECUTION RUNS only i.e., when {@link ConfigProperty#SELENIUM_RUN_LOCALLY}
* is set to true.
* The unit is milliseconds.
* Default is set to 300000 milliseconds.
*/
SELENDROID_EMULATOR_START_TIMEOUT("timeoutEmulatorStart", "300000", false),
/**
* Maximum time in milliseconds to wait for the selendroid-server to come up on the device.
* The value for this parameter is used as the value of serverStartTimeout for selendroid.
* This configuration affects LOCAL EXECUTION RUNS only i.e., when {@link ConfigProperty#SELENIUM_RUN_LOCALLY}
* is set to true.
* The unit is milliseconds.
* Default is set to 20000 milliseconds.
*/
SELENDROID_SERVER_START_TIMEOUT("serverStartTimeout", "20000", false),
/**
* To print debug info (about Browser/Selenium Version/Client OS) for user.
* Default is set to true
*/
PRINT_DEBUG_INFO("printDebugInfo", "true", true);
private String name;
private String defaultValue;
private boolean isGlobalScopeOnly;
ConfigProperty(String name, String defaultValue, boolean globalScopeOnly) {
checkArgument(name != null, "Config property name can not be null.");
checkArgument(defaultValue != null, "Config property default value cannot be null.");
this.name = name;
this.defaultValue = defaultValue;
this.isGlobalScopeOnly = globalScopeOnly;
}
/**
* Returns the name of this configuration property
*
* @return The name of this configuration property
*/
public String getName() {
return this.name;
}
/**
* Returns the default value for this configuration property
*
* @return The default String value for this configuration property
*/
public String getDefaultValue() {
return this.defaultValue;
}
/**
* Find the Enum for the specified property name.
*
* @return The ConfigProperty Enum for the specified name if found or null if not found.
*/
public static ConfigProperty find(String name) {
for (ConfigProperty prop : ConfigProperty.values()) {
if (prop.getName().equals(name)) {
return prop;
}
}
return null;
}
/**
* Answer if the property is a global only property (i.e only Suite scope param / System / Env Property)
*
* @return true if the property is only supported as a global property.
*/
public boolean isGlobalScopeOnly() {
return this.isGlobalScopeOnly;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy