-
Notifications
You must be signed in to change notification settings - Fork 18
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).