-
Notifications
You must be signed in to change notification settings - Fork 17
Testing
WComponents endeavors to provide first class support for automated testing. If you encounter any obstacles please report an issue.
The Selenium testing framework is made up of a few separate utility classes that can be used indepedently, and a few JUnit convenience classes that tie everything together. Either option can be used depending on the application's needs.
Extending from WComponentSeleniumTestCase
is the easiest way to write a Selenium test.
The default contructor will use a PhantomJSWebDriver
and will launch an LDE using the PlainLauncher
configuration.
All you need to do is call getDriver();
to access the Selenium WebDriver
which will be created, launched, cached and shutdown automatically.
public class MyText extends WComponentSeleniumTestCase {
@Test
public void testSomething() {
// Will create/launch/cache the WebDriver, and track it for shutdown at the end of the test.
getDriver().findElement(By.id("my_button_id")).click();
//Framework will automatically wait for page to load an AJAX to finish
Assert.assertFalse("Button should be disabled.", By.id("my_button_id")).isEnabled());
}
}
You can change which component is launched by setting bordertech.wcomponents.lde.component.to.launch
.
You can change which driver to use by calling a non-default constructor:
super(new ChromeWebDriverType());
You can also change the driver by setting the ParameterizedWebDriverType
property:
bordertech.wcomponents.test.selenium.webdriver=org.openqa.selenium.chrome
You can point to an external server by setting launchServer
and the serverUrl
:
bordertech.wcomponents.test.selenium.launchServer=false
bordertech.wcomponents.test.selenium.serverUrl=https://dev.local:8080/app
If you cannot, or do not want to, extend WComponentSeleniumTestCase
, then you can still call all the utility functions.
public class MyTest extends MyAbstractTestClass {
@Test
public void someTest() {
// Will create/launch/cache the WebDriver, and track it for shutdown at the end of the test.
WComponentWebDriver driver = WebDriverCache.getDriver(new ChromeWebDriverType());
// Fetch the page, will automatically wait for the page to be ready
driver.get("http://localhost:8080/app");
// Fetch the dialog, will automatically wait for the page to be ready
SeleniumWDialogWebElement dialog = WComponentSeleniumUtil.getDialog(driver);
String title = dialog.getHeadingText();
Assert.assertEquals("Dialog title does not match.", "MyTitle", title);
}
WebDriverCache
is a convenience class that can be used to create/cache/destroy Selenium WebDriver instances. This cache will ensure that the very heavy start-up cost of drivers is minimized when running multiple tests, and will also handle safe multi-threaded behaviour.
ParameterizedWebDriverType
can be used by tests to determine the WebDriver
implementation at runtime using Configuration
properties. This enables tests to conveniently switch browser types.
WComponentSeleniumUtil
is a static utility class that provides the implementation of all special WComponents functions, such as the wait condition for the page to be ready.
WComponentWebDriver
implements the Selenium WebDriver
interface and wraps the actual driver implementation. The class exposes some custom WComponents functions as well as ensuring the WComponent page has actually loaded between actions.
There are a number of wrapper classes for Selenium WebElement
to wrap WComponent functionality. For example, SeleniumWTableWebElement
provides an API to access pagination controls, cell content, table headers etc. The library of WebElement
wrappers will continue to grow and can be found in the package com.github.bordertech.wcomponents.test.selenium.element
.
The below components are supplied to speed-up development of Selenium tests, but they should be avoided if possible. Using these components requires the test class and the server (LDE) to run in the same JVM. As such using these components will prevent the test from being run against non-dev environments.
These classes are WComponent specific implementations of Selenium's By
interface to search for element. These classes require the LdeLauncher
to be a subclass of SeleniumLauncher
SeleniumLauncher
is an LdeLauncher
subclass of PlainLauncher
that keeps track of the UIContext so that ByWComponent
and ByWcomponentPath
can be used to find elements.
DynamicLauncher
is an LdeLauncher
subclass of SeleniumLauncher
that can dynamically set the launched component at runtime using setComponentToLaunch();
. This launcher is useful if you want to test different sub-components in a test suite without re-launching the server.
ServerCache
is a caching utility class that will launch the LDE server and keep it running between tests. This works like WebDriverCache
to ensure the significant start-up delay only occurs once. Ideally all tests will use the ServerCache
when running in LDE mode, but will defer to an external server if configured to point to a URL. See WComponentSeleniumTestCase
for an example of how this could work.
There are a few JUnit specific classes that bring all the Selenium components together to simplify the testing process. These components can be used for JUnit tests, or otherwise can be used as an example of how to do it.
WComponentSeleniumTestCase
is an abstract class for Selenium testing - extending this class is the easiest way to test WComponents with Selenium.
Constructors The parameterized constructors can be used to define a particular driver instance (e.g. PhantomJS or Chrome), and optionally a target URL (for an already running server).
Property Configuration The boolean property bordertech.wcomponents.test.selenium.launchServer
is used to determine whether to launch a new LDE at start-up, while the String property bordertech.wcomponents.test.selenium.serverUrl
can be used to point to an existing server.
WebDriver The method getDriver()
will create, launch and cache the configured driver automatically. The session will automatically be reset between tests.
###MultiBrowserRunner
MultiBrowserRunner
is a custom JUnit test runner that will execute the test multiple times for each WebDriver
defined in the property bordertech.wcomponents.test.selenium.driverTypes
. The property bordertech.wcomponents.test.selenium.runParallel
can be set to run the different driver tests in parallel. The WebDriverCache
used by the MultiBrowserRunner
will ensure thread-safe behaviour between threads.
The module wc/a8n provides both a javascript and pure DOM "hook" to determine if the page is "ready".
Ready means:
- The DOM is ready.
- Initialization scripts have run.
- There is no pending AJAX.
- There are no pending timeouts (
window.setTimeout
).
DOM
The body
element has an attribute data-wc-domready
which will be false
if the DOM is potentially pending an update and true
when there are no pending updates.
This attribute will always exist (it will never be removed) and will always be either "true" or "false".
JS
The automation module provides a subscribe
method which can be used to register a function that will be called with a boolean, true
if the DOM is "ready" or false
if the DOM is potentially pending an update.
Example:
require(["wc/a8n"], function(a8n) {
a8n.subscribe(function(isReady) {
console.log("isReady:", isReady);
});
});
Static IDs are optional in WComponents but they make certain types of automated testing much easier. Ensure that application developers take the time to set meaningful IDs for WComponents widgets. This is especially important for form controls (as opposed to layout widgets).