Now that we have a test folder in the app, we can start to increase our test coverage.
Actually, every feature that we added to the app so far, would require a separate test case. We have totally neglected this so far, so let’s add a simple unit test for our custom formatter function from Step 23. We will test if the long text for our status is correct by comparing it with the texts from our resource bundle.
📝 Note:
In this tutorial, we focus on a simple use case for the test implementation. If you want to learn more about QUnit tests, have a look at the Testing Tutorial tutorial, especially Step 2: A First Unit Test.
A unit test for our formatters is now available
You can access the live preview by clicking on this link: 🔗 Live Preview of Step 27.
To download the solution for this step as a zip file, just choose the link here: 📥 Download Solution for Step 27.
We add a new folder unit
under the test
folder and a model
subfolder where we will place our formatter unit test. The folder structure matches the app structure to easily find the corresponding unit tests.
Folder Structure for this Step
We create a new formatter.ts
file under webapp/test/unit/model
where the unit test for the custom formatter is implemented. The formatter function that we want to test is from the formatter.ts
file located in the webapp/model
folder.
The new formatter file just contains one QUnit module for our formatter function and one unit test for the formatter function. In the implementation of the statusText
function that we created in Step 23, we use the translated texts when calling the formatter. As we do not want to test the SAPUI5 binding functionality, we just use text in the test instead of a ResourceBundle
.
Finally, we perform our assertions. We check each branch of the formatter logic by invoking the isolated formatter function with the values that we expect in the data model (A
, B
, C
, and everything else). We strictly compare the result of the formatter function with the hard-coded strings that we expect from the resource bundle and give a meaningful error message if the test should fail.
import ResourceModel from "sap/ui/model/resource/ResourceModel";
import Controller from "sap/ui/core/mvc/Controller";
import formatter from "../../../model/formatter";
QUnit.module("Formatting function", {});
QUnit.test("Should return the translated texts", (assert) => {
const resourceModel = new ResourceModel({
bundleUrl: sap.ui.require.toUrl("ui5/walkthrough/i18n/i18n.properties"),
supportedLocales: [
""
],
fallbackLocale: ""
});
const controllerMock = {
getOwnerComponent() {
return {
getModel() {
return resourceModel;
}
};
}
} as any as Controller;
// System under test
const fnIsolatedFormatter = formatter.statusText.bind(controllerMock);
// Assert
assert.strictEqual(fnIsolatedFormatter("A"), "New", "The long text for status A is correct");
assert.strictEqual(fnIsolatedFormatter("B"), "In Progress", "The long text for status B is correct");
assert.strictEqual(fnIsolatedFormatter("C"), "Done", "The long text for status C is correct");
assert.strictEqual(fnIsolatedFormatter("Foo"), "Foo", "The long text for status Foo is correct");
});
We create a new unitTests.qunit.ts
file under webapp/test/unit/
.
This script loads and executes our formatter.
/* @sapUiRequire */
QUnit.config.autostart = false;
// import all your QUnit tests here
void Promise.all([
import("ui5/walkthrough/test/unit/model/formatter")
]).then(() => {
QUnit.start();
});
📝 Note:
The annotation@sapUiRequire
instructs the UI5 TypeScript transpilation process (executed byui5-tooling-transpile
) to usesap.ui.require
instead ofsap.ui.define
for the transpiled module. This allows to load the module via a<script>
tag. This is important for test suites to guarantee that theQUnit.config.autostart
is set tofalse
directly after QUnit has been loaded to avoid that QUnit immediately starts the test execution before the QUnit tests have been imported. Once the QUnit tests have been imported the tests will be executed after callingQUnit.start()
.
Finally we create a new unitTests.qunit.html
page under webapp/test/unit
.
Since we are now in the webapp/test/unit
folder, we actually need to go up two levels to get the webapp
folder again. This namespace can be used inside the tests to load and trigger application functionality.
First, we load some basic QUnit functionality via script tags. The QUnit test suite must be included at the end via a script tag which loads unitTests.qunit.js
. The file extension .js
must be used since this loads the transpiled version of unitTests.qunit.ts
.
<!DOCTYPE html>
<html>
<head>
<title>UI5 TypeScript Walkthrough - Unit Tests</title>
<meta charset="utf-8">
<script
id="sap-ui-bootstrap"
src="../../resources/sap-ui-core.js"
data-sap-ui-resourceroots='{
"ui5.walkthrough": "../../"
}'
data-sap-ui-async="true">
</script>
<link rel="stylesheet" type="text/css" href="../../resources/sap/ui/thirdparty/qunit-2.css">
<script src="../../resources/sap/ui/thirdparty/qunit-2.js"></script>
<script src="../../resources/sap/ui/qunit/qunit-junit.js"></script>
<script src="./unitTests.qunit.js"></script>
</head>
<body>
<div id="qunit"/>
<div id="qunit-fixture"/>
</body>
</html>
The so-called QUnit test suite is an HTML page that triggers all QUnit tests for the application. Most of it is generating the layout of the result page that you can see in the preview and we won’t further explain these parts.
If we now open the webapp/test/unit/unitTests.qunit.html
file in the browser, we should see our test running and verifying the formatter logic.
-
All unit tests are placed in the webapp/test/unit folder of the app.
-
Files in the test suite end with
*.qunit.html
. -
The
unitTests.qunit.html
file triggers all unit tests of the app. -
A unit test should be written for formatters, controller logic, and other individual functionality.
-
All dependencies are replaced by stubs to test only the functionality in scope.
Next: Step 28: Integration Test with OPA
Previous: Step 26: Mock Server Configuration
Related Information