9

OPA5 Test library for Fiori Elements V4 Applications

 1 year ago
source link: https://blogs.sap.com/2022/10/03/opa5-test-library-for-fiori-elements-v4-applications/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
October 3, 2022 6 minute read

OPA5 Test library for Fiori Elements V4 Applications

Hi testing enthusiasts,

in this blog post I want to show you a not pretty new but still quite unknown tool, that eases the process of writing good and stable OPA5 tests dramatically. The Fiori Elements Test Library V4.

The idea behind the test library was to reduce the efforts of writing and maintaining your OPA5 tests. As Fiori Elements applications are mostly generated and follow specific patterns in their control structure, a test library was developed to localize these patterns and cover the most common user interactions and assertions.

With that we can simplify our journeys, make them more readable, reduce the chance of code repetition and use the same actions and assertions across multiple applications. Another big benefit of this library is that it is kept up to date when framework changes happen. Maybe the internal structure of a control changes and the pattern for identifying your control changes as well, the tests with the library still run successfully.

Naming of test functions

The test library has the following predefined test functions:

  • Base arrangements that control the general lifecycle of the app
  • Base actions and assertions that can be used across the whole app, e.g. for Dialogs
  • Actions and Assertions for the ListReport, ObjectPage and Shell

These test functions have a consistent naming pattern which they follow to also improve the readability of the tests.

  • Actions: i<DoSth><WithSth>
  • Assertions: i<ExpectSth>
  • Consistent parameter signature
    • String for identifying UI elements via label on UI element, e.g. iExecuteAction("myAction")
    • Current state of UI elements, e.g. iCheckEdit({visible: true})
  • Supports chaining of functions on the same hierarchy, e.g. onFilterBar()
    • i<DoSth><WithSth>.and.i<DoSth><WithSth>
    • i<ExpectSth>.and.i<ExpectSth>

Integration

The general folder structure of the OPA5 tests stays almost the same:

test
│
├───integration                # By convention OPA tests are added to the test folder inside a UI5 app.
│   ├───pages                  # The pages folder contains the page objects for the different   
│   │   ├───MainListReport.js    # Fiori Elements templates. 
│   │   └───MainObjectPage.js    # Can be extended with own actions & assertions. 
│   ├───Opa.qunit.js             # Launch URL, pages and configuration settings can be set here.  
│   │                            # Uses JourneyRunner to call journeys.   
│   ├───OpaJourney.js            # A journey contains the actual tests which consists of steps 
│   │                            # constructed from the page objects.
│   └───opaTests.qunit.html      # Sets up the UI5 environment to start the OPA5 tests.            
│
├───flpSandbox.html              # Starts the app with mock data.
├───testsuite.qunit.html         # Testsuite that contains all unit and integration tests.
└───testsuite.qunit.js      
  • The opaTests.qunit.html is the file you execute to run your tests. Inside the .html file, the JavaScript file Opa.qunit.js is referenced.
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>{{appTitle}}</title>
    <meta charset="UTF-8">

    <script id="sap-ui-bootstrap"
        src="../../resources/sap-ui-core.js"
        data-sap-ui-theme='sap_fiori_3'
        data-sap-ui-resourceroots='{
          "sap.fe.demo.app": "../../"
        }'
        data-sap-ui-animation="false"
        data-sap-ui-compatVersion="edge"
        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="Opa.qunit.js"></script>
  </head>

  <body>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
  </body>
</html>
  • In the Opa.qunit.js file we reference the so called JourneyRunner to which we can pass the test configuration, the journeys that should be executed, and the page objects for the ListReport and ObjectPage which will provide the exact test functions of the test library. The Journey Runner will then run our OPA tests.
sap.ui.require([
    "sap/fe/test/JourneyRunner",
    "sap/fe/test/Shell",
    "sap/fe/demo/app/test/integration/pages/MainListReport",
    "sap/fe/demo/app/test/integration/pages/MainObjectPage",
    "sap/fe/demo/app/test/integration/OpaJourney"
],
    function (JourneyRunner, Shell, MainListReport, MainObjectPage, Journey) {
        'use strict';
        var JourneyRunner = new JourneyRunner({
            // start flpSandbox.html in test folder
            launchUrl: sap.ui.require.toUrl('incidents') + '/test/flpSandbox.html',
            opaConfig: { timeout: 30 }
        });
        JourneyRunner.run(
            {
                pages: { onTheMainPage: MainListReport, onTheDetailPage: MainObjectPage }
            },
            Journey.run,
        );
    }
)
  • In our page objects we include and configure the actual library. sap.fe.test.ListReport for the list report and sap.fe.test.ObjectPage for the object page. The relevant information can be found in the manifest.json. If there are user interactions or assertions that can not be covered by the available standard functions e.g. you have some custom coding, you can still write your own functions here.
sap.ui.define(['sap/fe/test/ListReport', "sap/ui/test/Opa5"], function (ListReport, Opa5) {
    'use strict';

    var AdditionalCustomListReportDefinition = {
      // custom actions and assertions can be defined here
      actions: {},
      assertions: {
        iShouldSeeMyCustomActionEnabled: function () {
          return this.waitFor({
            id: "myCustomSection"
            properties: {
              enabled: true
            },
            success: function () {
              Opa5.assert.ok(true, "The custom section is visible and enabled")
            },
            errorMessage: "The custom section could not be found or is not enabled!"
          })
        }
      }
    };

    return new ListReport(
        {
            appId: 'sap.fe.demo.app', // Compare sap.app.id in manifest.json
            componentId: 'AppList', // Compare sap.ui5.routing.targets.<ListReport|ObjectPage>.id in manifest.json
            entitySet: 'EntitySet' // Compare sap.ui5.routing.targets.<ListReport|ObjectPage>.options.settings.entitySet in manifest.json
        },
        AdditionalCustomListReportDefinition
    );
});

Usage

To use now the test library we can write normal Journeys that live, by convention, in a run function. In the API documentation you can have a look which generic actions and assertions are available for each individual page. Especially at the beginning, it can be a little cumbersome to navigate through the API, find the correct actions/assertions and the arguments you can pass to them.

A common scenario you can cover with the library could be to search for some specific entry in the table of the list report. To identify the correct functions in the documentation you can follow the following pattern/questions:

Do I want to execute/assert something on the ListReport, ObjectPage or Shell?

ListReport

Bildschirmfoto-2022-09-26-um-16.17.14-2.png

Do I want to execute an action(When.***) or assertion(Then***) on something?

Actions

Bildschirmfoto-2022-09-26-um-16.21.43.png

Which method in the actions could match the part of the view I want to interact with?

FilterBarWe have to click on the link that is provided in the Description Column

Bildschirmfoto-2022-09-22-um-16.26.52-9.png

Which actions can fulfill my scenario?

iChangeSearchField and iExecuteSearch

Bildschirmfoto-2022-09-26-um-16.23.59.png

After identifying the relevant functions, we can now write our journey file the same way we identified the relevant functions in the API

sap.ui.define(['sap/ui/test/opaQunit'], function (opaTest) {
  'use strict';

  var Journey = {
    run: function () {
        QUnit.module('Sample journey');

        opaTest('#0: Start', function (Given, When, Then) {
            Given.iResetTestData().and.iStartMyApp("incidents-tile");
            Then.onTheMainPage.iSeeThisPage();
        });

        opaTest('#1: ListReport: Check List Report Page loads', function (Given, When, Then) {
            When.onTheMainPage.onFilterBar().iChangeSearchField("incident_001");
            When.onTheMainPage.onFilterBar().iExecuteSearch();

            // we can also chain multiple functions on the same hierarchy
            // When.onTheMainPage.onFilterBar().iChangeSearchField("incident_001).and.iExecuteSearch()

            // assert that there should be only 4 rows displayed
            Then.onTheMainPage.onTable().iCheckRows(4);

            // custom assertion
            Then.onTheMainPage.iShouldSeeMyCustomActionEnabled()
        });
      
        opaTest('#999: Tear down', function (Given, When, Then) {
            Given.iTearDownMyApp();
        });
    }
  };

  return Journey;
});   

wdi5 integration

With the help of some colleagues from SAP (thanks Nicolas LUNET for the implementation and Georg Bischoff for the documentation!) we also have an integration of the test library in wdi5 as well! You can have a look at the detailed documentation how you can integrate the library in wdi5. With that achieved we can more or less just copy & paste the same code you used in your Integration test for your E2E test! Isn’t that nice?!

//... wdi5
it("I search product 'Office Plant'", async () => {
  await FioriElementsFacade.execute((Given, When, Then) => {
    // use the same code in the "Facade" as in your OPA5 tests
    When.onTheMainPage.onFilterBar().iChangeSearchField("Office Plant").and.iExecuteSearch()
    Then.onTheMainPage.onTable().iCheckRows(3)
  })
})

Conclusion

The Fiori Elements Test Library V4 is a useful tool, that eases the process of writing and maintaining your test code. If you want to learn more about the test library itself, it’s usage or just want to try it out yourself have a look at the already existing tutorial for the test library. If you’re already using the test library, let me know in the comments what your experiences with the library have been so far.

Cheers


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK