WDIO is a hugely popular E2E testing framework for Web Applications. This also includes hybrid apps. It can drive a real browser and simulate a user interacting with the app. WDIO can work with app that use any web framework but there are certain advantages if the testing framework integrates with the web framework. If this is the case, the tests could be much simpler to write and mainly, much more reliable. Reliability is of paramount importance for E2E tests that typically struggle with flakiness so any improvement can have significant effect on the TCO of testing process.
Why WDIO
WDIO is a de-facto standard for browser testing in the JavaScript world. Of course there are few more frameworks in the E2E testing space, notably
Cypress but WDIO is the most widely-used and advanced one. One of the biggest advantages of WDIO is that it is a real, active open-source project with passionate developers and a vibrant community. WDIO is not associated with particular frontend technology or company and as this may seems like a limitation, it is actually a big advantage as WDIO is more future-proof as there is no single backer for the continued development. WDIO provides many advanced features in its core, like parallelisation and many, many more over the extensive plugin library. There are many reporters like JUnit, HTLM with screenshots, several runners - local/remote
WebDriver,
Appium,
Puppeteer, browser cloud providers like
SauceLabs,
BrowserStack and many more.
Why WDI5
WDIO can work with any web application but lacks the awareness of the web framework that the application uses.
WDI5, which is a WDIO plugin, bridges this gap and provides two key benefits, namely control locators and synchronisation with the web framework. WDIO supports many types of locators - css, xpath, even plain javascript code but it lacks understanding of the UI5 controls. WDI5 exposes a
browser.byControl() method that accepts a control locator and returns a proxy for the real control. Then the test can assert on the control state or even interact with the control. The second benefit is transparent but equally important – on every element interaction, WDI5 waits for UI5 rendering to complete and for the application to be completely stable. This is similar to the build-in waiting in WDIO but is much more powerful because of the framework awareness. Similarly to Cypress and Protractor, WDI5 will wait for all XHR calls, all ongoing processing, all promises to complete and just then will return the control proxy. Both of those features greatly improve the reliability and simplify the creation and maintenance of E2E tests.
Getting started
Setting up a new test project with WDIO is very easy. You can use the popular console-based wizard that will configure all necessary dependencies.
$> npm i --save-dev @wdio/cli
$> npx wdio config
Then you only need to add the WDI5 dependency to package.json and declare the 'wdi5' service in wdio.conf.js.
Another option is to use the WDI5 yeoman generator that is part of the popular yeoman runner
easy-ui5.
Locating elements
WDI5 supports the control locators, also known as declarative matchers from OPA5. Actually, WDI5 uses UI5 public APIs to delegate finding the control to OPA5 code that works in UI5 runtime.
var search = browser.asControl({
selector: {
id: 'searchField',
viewName: 'sap.ui.demo.cart.view.Home',
}
});
You can use all declarative
control selectors.
Interactions
WDIO, similarly to Selenium controls the browser over the WebDriver protocol. Using it, the test can query the state of the DOM page but also can interact with the page and with the application behind it.
Native events
WDIO encapsulates the
WebDriver protocol and expose the
click() and
setValue() methods that the test can use. When the test calls them, the WebDriver, together with the browser generate the complete browser native event trail that correspond to the specific request. In practice the application can’t (easily) recognise if an interaction was done by a real user or from test over the WebDriver protocol.
To use native events, the test must resolve the root DOM element from the control proxy and call
click() or
setValue().
var button = browser.asControl({
selector: {
<control selector>
}
});
button.getWebElement().click();
Control events
WDI5 exposes the complete control API and this includes
fireEvent() method, as well as all overrides like
firePress(). So the test can call them and simulate the control firing an custom event. Generally, this should be as good as native events but depending on the control and how it keeps the internal state, there could be some glitches.
var button = browser.asControl({
selector: {
<control selector>
}
});
button.firePress();
Assertions
WDIO comes with a built in assertion library that works on the DOM level. You can use all assertions by resolving the root DOM element of the control using
getWebElement() method of the control proxy.
var button = browser.asControl({
selector:{
<control selector>
}
});
expect(button.getWebElement().isDisplayed()).toBeTruthy();
Alternatively, you can use the control proxy getters and assert on any control property.
var header = browser.asControl({
selector: {
<control selector>
}
});
expect(header.getTitle()).toBe(‘<something>’);
All control properties are available, including aggregations.
var list = browser.asControl({
selector: {
<control selector>
},
});
expect(list.getItems(true).length).toBe(<count>);
Test Recorder
WDI5 declarative locator syntax fully match the OPA control locators, actually under the hood WDI uses the public UI5 APIs so you can utilize the full power of
UI5 Test Recorder. If you haven't used it, under this bold name you can find a snippet generator that can build the best possible control locator by just right-clicking the UI5 control on screen. The test recorder applies a battle-hardened algorithm that traverse the control tree and builds the best possible control locator for the given control. Of course, as will all machine processing, there could be further context that is not considered in the building process but generally the resolved locator is a very good base to start with. Then you can copy it in your test code and edit it manually if necessary.
The test recorder can also encapsulate the generated locator in a skeleton of a PageObject method and so help you structure your test code. Currently only OPA and UIVeri5 dialects formatting is available but hopefully we will see support for WDI5 also.
Tips & Tricks
How to interact with multi-input controls
Unlike UIVeri5 or OPA, the suffix clause in the control locator is not supported (yet) and any interaction will target the root element of the control. Some controls may have have several interaction points like
sap.m.SearchField that accepts both text in the input as well as mouse clicks on search and reset icons. One way to overcome this is to chain a second
$(“<css locator>) that targets the necessary element. Like
$(‘input[type=search]”) for the input field in the
sap.m.SearchField. You can see the respective suffix in the DOM elements tree.
var search = browser.asControl({
selector: {
<control selector>
}
});
search.getWebElement().$('input[type=search]').setValue('<something>');
How to interact with element lists
Element lists (
$$ in WDIO or
element.all() in UIVeri5) need to be handled in code. So you must find the root control using control locator, like the
sap.m.List itself and get its aggregation with
getItems(). Then you can filter the list and work with specific control.
How to recognise the common “Element not found” error
Sometimes it is tricky to recognise that an element is not found with
byControl() call. There is an explicit error message that says it and even mentions the control selector but it is easy to miss it as it is not coloured as error. So typically, the first error you would recognise is
“TypeError: Cannot read property … of null” that happens on the first use of the unresolved WDI5 proxy object. Then just look up the console log and you would see the root cause and the control selector that was used.
Conclusion
WDIO + WDI5 is an excellent choice for E2E testing of UI5 apps. It provides a great TCO both in terms of ease of writing test as well as as reliable execution with minimum flakiness. It also fits nicely in the UI5 ecosystem and so you can benefit from all the innovation that comes with it.
References
Introduction of WDI5 on blogs.sap.com
Introduction of WDI at UI5Con 2020
WDI5 on github.com