Show TOC

Step 29: Integration Test with OPALocate this document in the navigation structure

If we want to test interaction patterns or more visual features of our app, we can also write an integration test. We haven’t thought about testing our interaction with the app yet, so in this step we will check if the dialog actually opens when we click the “Say Hello with Dialog” button. We can easily do this with OPA5, a feature of SAPUI5 that is easy to set up and is based on JavaScript and QUnit. Using integration and unit tests and running them consistently in a continuous integration (CI) environment, we can make sure that we don’t accidentally break our app or introduce logical errors in existing code.

Preview
Figure 1: An OPA test opens the "Hello" dialog from step 16
Coding

You can view and download all files in the Explored app in the Demo Kit under Walkthrough - Step 29.

Figure 2: Folder Structure for this Step

We add a new folder integration below the test folder, where we put our new test cases. Page objects that help structuring such integration tests are put in the pages subfolder that we also create now.

webapp/test/integration/navigationJourney.js (New)
sap.ui.require([
	"sap/ui/test/opaQunit"
], function () {
	"use strict";
	QUnit.module("Navigation");
	opaTest("Should open the hello dialog", function (Given, When, Then) {
		// Arrangements
		Given.iStartMyAppInAFrame(jQuery.sap.getResourcePath("sap/ui/demo/src/test", ".html"));
		//Actions
		When.onTheAppPage.iPressTheSayHelloWithDialogButton();
		// Assertions
		Then.onTheAppPage.iShouldSeeTheHelloDialog().
			and.iTeardownMyAppFrame();
	});
});

Let’s start with the journey first. A journey consists of a series of integration tests that belong to the same context such as navigating through the app. Similar to the QUnit test implementation, OPA5 uses QUnit, that's why we first set up a QUnit module Navigation that will be displayed on our result page.

The function opaTest is the main aspect for defining integration tests with OPA. Its parameters define a test name and a callback function that gets executed with the following OPA5 helper objects to write meaningful tests that read like a user story.
  • Given

    On the given object we can call arrangement functions like iStartMyAppInAFrame to load our app in a separate iFrame for integration testing.

  • When

    Contains custom actions that we can execute to get the application in a state where we can test the expected behavior.

  • Then

    Contains custom assertions that check a specific constellation in the application and the teardown function that removes our iFrame again.

In our test, we create a very simple test that starts the test page in an iFrame. In the app, we trigger a click a button and expect that the dialog is opened afterwards. Finally, we remove the iFrame again from our test page.

As you can see, the test case reads like a user story, we actually do not need the implementation of the methods yet to understand the meaning of the test case. This approach is called "Behavior Driven Development" or simply BDD and is popular in "Agile Software Development".

webapp/test/integration/pages/App.js (New)
sap.ui.require([
	"sap/ui/test/Opa5"
],
function (Opa5) {
	"use strict";
	Opa5.createPageObjects({
		onTheAppPage: {
			actions: {
				iPressTheSayHelloWithDialogButton: function () {
					return this.waitFor({
						controlType: "sap.m.Button",
						success: function (aButtons) {
							aButtons[0].$().trigger("tap");
						},
						errorMessage: "Did not find the helloDialogButton button on the app page"
					});
				}
			},
			assertions: {
				iShouldSeeTheHelloDialog: function () {
					return this.waitFor({
						controlType: "sap.m.Dialog",
						success: function () {
							// we set the view busy, so we need to query the parent of the app
							Opa5.assert.ok(true, "The dialog is open");
						},
						errorMessage: "Did not find the dialog control"
					});
				}
			}
		}
	});
});

The implementation of the page object holds the helper functions we just called in our journey. We require OPA5 from the sap.ui.test namespace and define a page object with the helper function createPageObjects. We pass in an object with the key of our page onTheAppPage and two sections: actions and assertions.

In the actions section of the page object we define a function to click the "Hello" dialog button. This is done in OPA5 with a waitFor statement, it is basically a loop that checks for the conditions defined as parameters. If the conditions are met, the success callback is executed, if the test fails because the conditions have not been met, the text in the errorMessage property is displayed on the result page.

We define a waitFor statement that checks for controls of type sap.m.Button. As soon as a button is found on the app page the success handler is executed and we use jQuery to trigger a tap event on the first button that we found. This should open the HelloDialog similar to clicking on the button manually.

In the assertions section we define another waitFor statement that checks if a sap.m.Dialog control is existing in the DOM of the app. When the dialog has been found, the test is successful and we can immediately confirm by calling an ok statement with a meaningful message.

webapp/test/integration/opaTests.qunit.html (New)
<!DOCTYPE html>
<html>
<head>
	<title>OPA tests for Walkthrough</title>
	<meta http-equiv='X-UA-Compatible' content='IE=edge'>
	<meta charset="utf-8">
	<script id="sap-ui-bootstrap"
			src="/resources/sap-ui-core.js"
			data-sap-ui-resourceroots='{
			"sap.ui.demo.wt.test.integration": "./",
			"sap.ui.demo.src.test" : "../../test/mockServer"
		}'>
	</script>
	<script>
		jQuery.sap.require("sap.ui.qunit.qunit-css");
		jQuery.sap.require("sap.ui.thirdparty.qunit");
		jQuery.sap.require("sap.ui.qunit.qunit-junit");
		jQuery.sap.require("sap.ui.test.opaQunit");
		jQuery.sap.require("sap.ui.test.Opa5");
		// pages
		jQuery.sap.require("sap.ui.demo.wt.test.integration.pages.App");
		// journeys
		jQuery.sap.require("sap.ui.demo.wt.test.integration.navigationJourney");
	</script>
</head>
<body>
<div id="content"></div>
<div id="qunit"></div>
<div id="qunit-fixture"></div>
</body>
</html>

This file contains our test suite for all OPA tests of the app. We define a namespace to the current folder for our integration tests and to the mockServer page so that we can easily start the app by this namespace instead of giving the file name directly in each test.

Then we load the basic QUnit and OPA functionality from SAPUI5 and our custom page object so that we can execute the test journey. The navigationJourney we defined above is also loaded and the test functions inside are immediately executed.

When you call the webapp/test/integration/opaTests.qunit.html page of your project on the server, you should see the QUnit layout and a test “Should see the hello dialog” is executed immediately. It will load the app in a small iFrame in the lower right of the page. There you can see what operations the test is performing on the app, if everything works correctly the button click is triggered, then a dialog is shown and the test case is green.

Conventions
  • OPA tests are located in the webapp/test/integration folder of the application.

  • Use page objects and journeys for structuring OPA tests.