Skip to Content
Technical Articles
Author's profile photo Maxim Naidenov

Use WDIO and WDI5 for testing UI5 apps

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

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michaela Churenska
      Michaela Churenska

      What is the pros/cons compared to the ui-verifi5 ? If you are starting open ui5 project today, what will be the 2e testing framework that you will choose ?

      🙂

      Author's profile photo Jannik Adam
      Jannik Adam

      Looks like "UIVeri5 is deprecated and won’t be developed any further"

      https://github.com/SAP/ui5-uiveri5

      Author's profile photo Volker Buzek
      Volker Buzek

      if you want to give wdi5 a shot (which you should 😁), please be aware that since the publication of this blog post, we've switched to async notation style:

      const control = await browser.asControl(selector)

      Newly introduced with the async notation style was the fluent async api:

      const listItemTitle = await browser.asControl(selector).getItems(5).getTitle()

      it allows chaining multiple calls on the retrieved control, similar to the old sync style notation.

      more details: https://github.com/js-soft/wdi5#fluent-async-api

      Author's profile photo Maxim Naidenov
      Maxim Naidenov
      Blog Post Author

      Hi Volker,

      actually my article and the show syntax is STILL correct as you have not published the 0.8.2 release on npmjs. Once you do it, I will be glad to fix the code snippets.

       

      Author's profile photo Volker Buzek
      Volker Buzek

      online since 3 days.

      but the async style notation support incl fluent async api was already there since 0.8.0, published Jan 17th.

      $> npm info wdio-ui5-service                                                                                       
      
      wdio-ui5-service@0.8.2 | (DERIVED BEER-WARE OR Apache-2.0) | deps: none | versions: 23
      WebdriverIO plugin for testing UI5 browser-based apps
      https://github.com/js-soft/wdi5/blob/main/wdio-ui5-service/README.md
      
      keywords: webdriver, wdio, wdio-service, ui5, openui5
      
      dist
      .tarball: https://registry.npmjs.org/wdio-ui5-service/-/wdio-ui5-service-0.8.2.tgz
      .shasum: 9d5b2ee9cd1ccda7a431ef12d2e52113e1364309
      .integrity: sha512-TjWarHkUnbRosr49sXKa607G0bzbBI4i5Me9lffc4iijXE4tmO6ESCCu/WZM90hwgyP8yREhuliMFzrYiUqWdw==
      .unpackedSize: 141.4 kB
      Author's profile photo Maxim Naidenov
      Maxim Naidenov
      Blog Post Author

      Ahh, this wdi5 vs wdio-ui5-service mess, the wdi5 package is still on 0.7 in npmjs and made me think you did not release yet.

      Author's profile photo Volker Buzek
      Volker Buzek

      will, it's not a mess, since they are 2 different packages:
      wdi5 → hybrid app testing, wdio-ui5-service → browser-scope testing.

      still might be confusing at first look.

      but this will end soon™ 😁