Technical Articles
UI5’s unified test tech stack
Since many moons, karma
was the go-to testrunner for executing Unit- and Integration-tests of UI5 applications. For end-to-end tests, wdi5
has become the default tool.
With karma
being deprecated, a void opened for a successor for running QUnit- and OPA-tests within the existing UI5 test tech stack – until wdio-qunit-service
arrived, allowing you to run Unit-, Integration- and end-to-end tests on the same stack.
π₯Β clone yourself this sample repo https://github.com/vobu/ui5-unified-test-stack, npm i && npm run test
and see for yourself βοΈ
“QUnit service” replaces karma
wdio-qunit-service
is the awesome work by longtime community member Mauricio Lauffer. As Mauricio puts it himself in the README
, “QUnit Service is a drop-in replacement for those using Karma JS to run their QUnit tests”.
It is the same way a Webdriver.IO-extension as wdi5
, following the respective naming convention:
wdio-qunit-service
β human readable “QUnit Service”wdio-ui5-service
β human readable “wdi5”
Both “services” extend Webdriver.IO with UI5-specific functionality – “QUnit Service” for running Unit- and Integration-tests, wdi5
for running end-to-end tests.
Don’t be fooled by neither the technical service name wdio-qunit-service
, nor by “QUnit service” – the Webdriver.IO-extension is perfectly capable of running OPA tests as well, as they are based on QUnit!
With both services using Webdriver.IO, the UI5 test tech stack gets harmonised by eliminating the karma
dependency and using the same test runner for executing all Unit-, Integration- and end-to-end tests.
By the way: migration from karma
to “Qunit Service” is as easy declaring qunit
as a required service in the config file and putting a 7 (!) lines of JS code in a .test.(j|t)s
file.
No believe?
Either look at the sample repo source (config file, test file) or follow along here, as we embark on a journey of creating
- a UI5 app from scratch
- installing
wdi5
and “QUnit Service” - migrating the Unit- and Integration-Tests
…all in under 15 minutes.
Even if you’re a slow typer, promised.
Challenge: UI5 app and unified test stack in less than 15 minutes
Let’s go πππ!
Open a terminal:
$> yo easy-ui5 app
and answer to the prompts.
(yes, I’ll wait)
…
Done? Good.
Install wdi5
in the directory your app was created in:
$> cd <your app dir>
$> npm init wdi5@latest
(yes, I’ll wait again)
This creates a wdi5
config for you at webapp/test/e2e/wdio.conf.js
– which in turn is a Webdriver.IO-config file that can be re-used for executing the QUnit- and OPA-tests via wdio-qunit-service
!
Copy webapp/test/e2e/wdio.conf.js
to the unit test folder webapp/test/unit/
.
Add qunit
to the services
array in ~line 134: services: ["ui5", "qunit"]
of webapp/test/unit/wdio.conf.js
.
exports.config = {
// ...
services: ["ui5", "qunit"],
// ...
}
Create a new file webapp/test/unit/unitTests.test.js
with this content:
describe("QUnit test page", () => {
it("should pass QUnit tests", async () => {
await browser.url("http://localhost:8080/test/unit/unitTests.qunit.html");
const qunitResults = await browser.getQUnitResults();
expect(qunitResults).toBeTruthy();
});
});
(Excerpt: what does this do? It is taken straight from the QUnit Service documentation. And it starts the browser configured in webapp/test/unit/wdio.conf.js
(here: Chrome), opens the URL http://localhost:8080/test/unit/unitTests.qunit.html, and waits for the Unit Tests to run and finish via await browser.getQUnitResults()
)
You end up with this dir/file structure:
.
βββ webapp
βββ test
βββ e2e
β βββ sample.test.js
β βββ wdio.conf.js
βββ unit
βββ unitTests.test.js
βββ wdio.conf.js
Now, head back to the terminal.
Run $> npm start
for starting the UI5 app.
Open a second terminal, run $> npx wdio run ./webapp/test/unit/wdio.conf.js
…
…and marvel at UI5’s QUnit tests running with Webdriver.IO.
With the help of “Qunit Service”, on the same tech base as wdi5
.
And with the same configuration file.
Webdriver.IO and wdio-qunit-service running Unit tests
π£
Clean up + porting integration test runner
We could end here. But now that we’ve seen that the same config file can be re-used for Unit-, Integration- and end-to-end tests, let’s exactly do this:
Copy webapp/test/unit/wdio.conf.js
into webapp/test/
and name it wdio.conf.shared.js
.
Then put a dedicated wdio.conf.{e2e,integration,unit}.js
into each respective folder.
With the contents of each being the same:
const { config } = require("../wdio.conf.shared");
exports.config = config;
This requires the shared file, would allow for on-the-fly config changes, and exports it again.
So the directory/file structure now looks like:
.
βββ webapp
βββ test
βββ e2e
β βββ wdio.conf.e2e.js
βββ integration
β βββ wdio.conf.integration.js
βββ unit
β βββ wdio.conf.unit.js
βββ wdio.conf.shared.js
Create a file for running the OPA integration tests with wdio-qunit-service
/ wdio
the same way as it is for the QUnit unit tests:
webapp/test/integration/integrationTests.test.js
:
describe("QUnit test page", () => {
it("should pass QUnit tests", async () => {
await browser.url(
"http://localhost:8080/test/integration/opaTests.qunit.html"
);
const qunitResults = await browser.getQUnitResults();
expect(qunitResults).toBeTruthy();
});
});
So our test- and config-file tree looks like:
.
βββ webapp
βββ test
β βββ e2e
β β βββ sample.test.js
β β βββ wdio.conf.e2e.js
β βββ integration
β β βββ integrationTests.test.
β β βββ wdio.conf.integration.js
β βββ unit
β β βββ unitTests.test.js
β β βββ wdio.conf.unit.js
β βββ wdio.conf.shared.js
βββ view
Spice up package.json
with npm
scripts for running each test scope:
{
//...
"scripts": {
//...
"test:unit": "wdio run ./webapp/test/unit/wdio.conf.unit.js",
"test:integration": "wdio run ./webapp/test/integration/wdio.conf.integration.js",
"test:e2e": "npm run wdi5",
"wdi5": "wdio run ./webapp/test/e2e/wdio.conf.e2e.js"
}
//...
}
Now you have
- Unit tests (QUnit)
- Integration tests (OPA)
- end-to-end tests (wdi5)
all running on the same tech stack (Webdriver.IO)!
Thanks to Mauricio’s awesome work on wdio-qunit-service
!
Is this the official UI5 approach for running tests on a unified test stack?
No. Not yet π.
From an architectural point of view, it makes a lot of sense – single test runner, fewer module dependencies, reduced technical debt.
From a business perspective, it makes a lot of sense – Webdriver.IO is community-owned and will not go away by the decision of a single company. Both wdio-qunit-service
and wdi5
are Open Source and permit commercial use with their Apache 2.0 license.
From a developer perspective, it makes a lot of sense – keep on writing QUnit- and OPA-tests as it always was, re-use the same test-runner as for wdi5
-tests.
From the SAP perspective, it makes a lot of sense – as it once again proves that a cooperation with the community enables quicker innovation.
Everybody wins. Heck yeah πΎΒ πͺ
That's awesome! I loved it so much that I had to create a PR to make the config even simpler:
test: Single wdio config file
cool! merged!
using suites instead of different config files β only one
wdio.config.js
to run all tests πReally interesting Blog Post thanks a lot for this Volker Buzek
The question that I had was if we could extend this to also use TypeScript and which adjustments needed to be done.
Thanks in advance.
CC: Calin Lazuran
well,
yo easy-ui5 ts-app && npm init wdi5@latest -- --ts
Β allows for a quick start similar to the JS-approach in the blog post.Do you want to give it a shot? I'd be happy to collaborate on both code and writing π
Thanks for the quick response, Volker.
We already have a project where we use UI5 with ts and also added wdi5 there for e2e tests, we will most likely also try it out there soon to add unit testing and give some feedback.
My question was more in the direction of the test files themselves: if something needs to be done, because of the imports on the functions from controllers for example.