Create Automated System Tests for SAP Cloud Application Programming Model Projects
- How to create system tests with wdi5 for SAP Cloud Application Programming Model projects using the Test Recorder
- How to add system tests as automated steps to your SAP Continuous Integration and Delivery job
Prerequisites
- You use SAPUI5 in version 1.105.0 or higher.
- You have installed and configured a local Git client.
- You have installed Node.js in version 18.x.
- You have installed Visual Studio Code.
- You have installed the
cds
development kit using the commandnpm install -g @sap/cds-dk
. If you encounter any problems when installing thecds
development kit, have a look at this troubleshooting section. - Your Google Chrome version is up to date. See Update Google Chrome.
- You have an SAP Business Technology Platform (BTP) Trial Account with a subaccount hosted in the region US East (VA).
- You have an account on GitHub.
- You have set up SAP Continuous Integration and Delivery (see Initial Setup).
- Step 1
In Visual Studio Code, set up and run your bookshop application.
- Before you start working, fork this repository to your personal GitHub account. See Forking a repository.
- In Visual Studio Code, choose View → Command Palette… → Git:Clone.
-
As Repository URL, enter:
URLCopyhttps://github.com/<your github username>/cap-bookshop-wdi5.git
- Choose Select Repository Location and select a folder into which to clone the test repository.
-
When asked if you want to open the cloned repository, choose Open.
As a result, the
CAP-BOOKSHOP-WDI5
project is loaded into the EXPLORER pane and you can see its resources in the outline: -
In Visual Studio Code, choose Terminal → New Terminal.
-
Execute the following command to install the npm packages:
Shell/BashCopynpm install
-
Execute the following command to start your bookshop application:
Shell/BashCopynpm run start
-
To open a new terminal, choose Terminal → New Terminal.
-
Execute the following command to call the quick start installation of wdi5:
Shell/BashCopynpm init wdi5@latest -- --configPath ./app/admin-books/webapp/test/wdi5/ --specs ./**/wdi5/specs/**.js --baseUrl http://localhost:4004/fiori-apps.html\#Books-manage
The console output should look as follows:
-
In your project in the EXPLORER pane, choose
app
→admin-books
→webapp
→test
→wdi5
.Now you can see all files you need to define system tests with wdi5:
-
The
wdio.conf.js
file:In this file, you’ll define the settings for the wdi5 plugin, for example the browser and reporter, as well as the URL to access the SAP Fiori app under test.
-
The
test.js
file (in this case, it’s calledbookshop.test.js
):In this file, you’ll define your test scenario, which comprises steps that are triggered one after the other. Within the test scenario, you’ll refer to your page objects.
-
Page objects (in this case, you have
pageobjects/manageBooks.page.js
for the list of books that are added and the button to create a new book, andpageobjects/newBook.page.js
to provide the details of the new book):Page objects are design patterns that represent a significant part of an app, for example, a view. They group two kinds of elements:
- Actions, for example, choosing the Create button to create a new book
- Assertions, for example, checking if the newly created book is displayed in the list of books
Page objects reside in the
pageobjects
folder of your project. They use locators to identify specific elements on the screen and thereby, allow test runners to see and do anything a real user would.
-
-
Execute the following command to install the timeline reporter:
Shell/BashCopynpm run install --save-dev wdio-timeline-reporter
The console output should look as follows:
-
In the
wdio.conf.js
file, add the following snippets to configure the timeline reporter and the Chrome browser:JavaScriptCopyconst { TimelineService } = require("wdio-timeline-reporter/timeline-service"); exports.config = { // ...
JavaScriptCopy// ... services: ['chromedriver','ui5', [TimelineService]], // ...
JavaScriptCopy// ... reporters: ['spec',[ "timeline", { outputDir: "target", embedImages: true, screenshotStrategy: "before:click", }, ] ], // ...
JavaScriptCopy// ... capabilities: [{ maxInstances: 5, browserName: 'chrome', acceptInsecureCerts: true, "goog:chromeOptions": { args: ["--no-sandbox", "--disable-dev-shm-usage"] } }], // ...
-
Now, your project setup is ready. Make sure that your code looks as follows and choose File → Save.
- Step 2
Familiarize yourself with your test scenario before starting to code it. Later, you’ll automate the following steps so that they are automatically executed during your system tests.
-
As your bookshop application runs on your local server, use the following URL to access it:
URLCopyhttp://localhost:4004/fiori-apps.html#Books-manage
-
In the bookshop application, choose Create.
-
Enter the title of your new book, for example,
How to Cook Pancakes
. -
From the Genre drop-down menu, choose Fiction.
-
From the Author drop-down menu, choose Emile Bronte.
-
Choose Create.
-
Verify that the Edit button is displayed.
-
Choose Back to return to the list of books.
-
Verify that the new book has been added to the list.
The created book will persist as long as the local server with the application is running. To start with a fresh database, stop the process and restart it with
npm run start
.
-
- Step 3
Create a wdi5 script to test the creation of a new book in your bookshop application.
-
In your project in the EXPLORER pane, choose
fiori
→app
→admin-books
→webapp
→test
→wdi5
→specs/bookshop.test.js
.The
bookshop.test.js
file contains your test scripts, which are divided into two sections:- The describe block, which is like a test suite and holds sets of test cases that are called
it
- The
it
block, which comprises the test cases
You can have multiple
it
blocks in a single spec file.In your
bookshop.test.js
file, you’ll define the steps of your test scenario and within them, refer to your page objects. - The describe block, which is like a test suite and holds sets of test cases that are called
-
Into the
describe
function, implement theit
function by adding the skeleton of thecreate new book
test:JavaScriptCopyit("create a new book", async () => { });
Your code should now look as follows:
-
As a first step to create a new book, you have to choose the Create button. Implement this action as follows in the
it
block:JavaScriptCopyawait ManageBooksPage.iClickOnCreateNewBook();
Here,
iClickOnCreateNewBook()
is a reference to the test function that you’ll define in the following.Your code should now look as follows:
After each step make sure to save your changes by choosing File → Save.
-
From the EXPLORER pane, open
pageobjects
→manageBooks.page.js
.This file represents the page object for your bookshop application. In page objects, you can define actions that are performed during a test and make assertions:
-
In the bookshop application in Google Chrome, press CTRL + SHIFT + ALT + T (if you use a Windows system) or SHIFT + CTRL + OPTION + T (if you use a Mac system) to open the Test Recorder in a new browser window.
-
In your sample application, right-click on the Create Button and choose Press.
As a result, the Test Recorder highlights the entry to indicate its activity:
Now, the Test Recorder provides a code snippet for your test:
Note: Make sure that the dialect
wdi5
is selected. -
Copy the generated code snippet into the
module.exports
section of yourmanageBooks.page.js
and name the functioniClickOnCreateNewBook
.
-
- Step 4
Create a wdi5 script to test the addition of detailed information to your newly created book.
-
From the EXPLORER pane in Visual Studio Code, open
bookshop.test.js
. -
In the describe block, add the following line to declare the variable
bookTitle
and assign the value"How to Cook Pancakes"
to it:JavaScriptCopyconst bookTitle = "How to Cook Pancakes";
-
When adding detailed information to a book in the bookshop application, as a first action, you have to enter the title of the book. Implement this action as follows in the
it
block:JavaScriptCopyawait NewBookPage.iEnterTitle(bookTitle);
The
bookTitle
constant, which you have declared before, is passed as an argument, here.Now, your code should look as follows:
-
From the EXPLORER pane, open
pageobjects
→newBook.page.js
. -
In your bookshop application, right-click the Title input field and choose Enter Text.
As a result, the Test Recorder highlights the input field to indicate its activity:
Now, the Test Recorder provides a code snippet for your test:
Note: Make sure that the dialect
wdi5
is selected. -
Copy this code snippet into the
module.exports
section of yournewBook.page.js
and name the functioniEnterTitle
.Here, pass the
sBook
as an argument in the function name and use it in theenterText()
method. -
In the
it
block of yourbookshop.test.js
, add the following line to choose a value from the Genre drop-down list:JavaScriptCopyawait NewBookPage.iSelectGenre();
-
In your bookshop application, right-click the Genre drop-down menu and choose Press.
As a result, the Test Recorder highlights the drop-down icon to indicate its activity:
Now, the Test Recorder provides a code snippet for your test:
Note: Make sure that the dialect
wdi5
is selected. -
Copy this code snippet into the
module.exports
section of yournewBook.page.js
file and name the functioniSelectGenre
. -
From the Genre pop-up window in your bookshop application, right-click Fiction and choose Press.
-
Again, the Test Recorder provides a code snippet for your test. Copy it into the
module.exports
section of yournewBook.page.js
file under the same function name (iSelectGenre
).Your code should now look as follows:
-
In the
it
block of yourbookshop.test.js
file, add the following line to choose a value from the Author drop-down list:JavaScriptCopyawait NewBookPage.iSelectAuthor();
-
Repeat the procedure for selecting the author (that is, copying the generated code snippets from the Test Recorder for choosing the drop-down menu and Emily Bronte from the pop-up window into your page object). Name the functions
iSelectAuthor
.In the end, the code in your
newBook.page.js
should look as follows: -
In the
it
block of yourbookshop.test.js
, add the following line to select the Create button at the bottom of the application:JavaScriptCopyawait NewBookPage.iPressCreate(); await NewBookPage.iSeeEditButton()
-
Now, at the footer in the bookshop application, right-click the Create button and choose Press.
-
Copy the generated snippet into the
module.exports
section of yournewBook.page.js
file. Name the functionsiPressCreate
and add the expected behavior to yourbookshop.test.js
file. -
To ensure that the saving action was successful, verify that the Edit button is displayed. Add the expected behavior to your
bookshop.test.js
file: -
In the bookshop application, right-click the Edit button and choose Highlight.
-
On the right side of the Test Recorder window, you can find a section with Properties and Bindings. Choose the icon that is located on the left of the property
enabled
. This will addexpect(enabled).toBeTruthy();
to the code snippet. -
Copy the generated code snippet from the Test Recorder into the
module.exports
section in yournewBook.page.js
file and name the functioniSeeEditButton
.It should look as follows:
-
Let’s proceed with our test scenario by implementing another
it
function in thebookshop.test.js
file. To achieve that, we need to add the skeleton of theshould check book is added
test function:JavaScriptCopyit("should check book is added", async () => { });
-
In this
it
function, we need two steps. First an action to navigate back to the list of books and a second step to assert that our newly created book is contained in the list. Implement this as follows in theit
block:JavaScriptCopyawait NewBookPage.iNavigateBack(); await ManageBooksPage.theBookListContains(bookTitle);
Now, your test is complete. Make sure that it looks as follows:
-
To get the code snippet for the implementation of the
NewBookPage.iNavigateBack
action, right-click the < (Go Back) button and choose Press in the bookshop application. -
Again, copy the generated code snippet into the
module.exports
section of yournewBook.page.js
file and name itiNavigateBack
.Your page object should now look as follows:
-
In your bookshop application, choose the < (back) button. As a result, you should see the list of all books including the one you’ve added.
-
In the list of books of your bookshop application, right-click the title of the book you’ve created and choose Highlight.
Note: Make sure that only the specific title of the row is highlighted in blue and not the whole row.
-
On the right side of the Test Recorder window, you can find a section with Properties and Bindings. Choose the icon that is located on the left of the property
visible
in theInherited
section. This will addexpect(visible).toBeTruthy();
to the code snippet. -
Copy the generated code snippet into the
module.exports
section of yourmanageBooks.page.js
file and name the functiontheBookListContains
. Here, pass thesBook
as an argument in the function name and use it in the locator to identify the control by its text.It should look as follows:
-
Choose File → Save.
-
Right-click your
test\wdi5
folder in the EXPLORER pane and choose Open in Integrated Terminal. -
Execute the following command to run your test:
Bash/ShellCopynpm run wdi5
If your test run was successful, your terminal response should look as follows:
You might face a timeout error as shown in the following screenshot:
The timeout property is applicable at each step definition. However, if you want to increase the timeout because your test takes longer than the default value, you need to set it in the mocha framework options. In the
wdio.conf.js
file, set the time as follows:JavaScriptCopy// wdio.conf.js exports.config = { //..... mochaOpts: { ui: 'bdd', timeout: 60000 } //..... }
Another known timeout error is while waiting for the UI5 controller to load as shown in the following screenshot:
If you are getting timeout errors while waiting for an UI5 element to load, consider increasing the maximum waiting time for the availability of UI5 control. In the
wdio.conf.js
file, set the time as follows:JavaScriptCopy/// wdio.conf.js exports.config = { //..... wdi5: { waitForUI5Timeout: 60000, }, //..... }
-
In the EXPLORER pane, right-click the
timeline-report.html
in thetarget
folder and choose Reveal in File Explorer. -
Double-click the
timeline-report
in the file explorer:
-
- Step 5
Create credentials for deploying your application to SAP BTP, Cloud Foundry environment.
-
In the Credentials tab in SAP Continuous Integration and Delivery, choose + (Create Credentials).
-
For Name, enter a freely chosen name for your credentials, which is unique in your SAP BTP subaccount, for example
cfdeploy
. -
As Type, select Basic Authentication.
-
For Username, enter your username for the SAP BTP cockpit.
-
For Password, use your password for the SAP BTP cockpit.
-
Choose Create.
-
- Step 6
Note: If your GitHub repository is not private, you can skip this section.
If your GitHub repository is private, configure credentials for it, so that SAP Continuous Integration and Delivery can connect to it.
-
In the Credentials tab in SAP Continuous Integration and Delivery, choose + (Create Credentials).
-
For Name, enter a freely chosen name for your credential, which is unique in your SAP BTP subaccount, for example
github
. -
As Type, select Basic Authentication.
-
For Username, enter your GitHub username.
-
For Password, use a personal access token.
Note: When creating the token, select repo as scope.
-
Choose Create.
-
- Step 7
Connect SAP Continuous Integration and Delivery to the repository in which your project sources reside.
-
In SAP Continuous Integration and Delivery, choose Repositories → + (Add).
-
In the Add Repository pane, add a name for your repository.
-
In GitHub, copy the HTTPS clone URL of the repository that contains your application.
-
Paste it into the Clone URL field in the Add Repository pane in SAP Continuous Integration and Delivery.
-
(Optional) If your GitHub repository is private, choose the GitHub credentials you’ve created in the previous step from the Credentials drop-down list.
-
Choose Add.
Note: Optionally, you can automate SAP Continuous Integration and Delivery builds through webhooks. Thereby, builds are triggered through creating and committing a code change in your GitHub project. For more information, see Add a Webhook in GitHub.
-
- Step 8
Configure a basic SAP Continuous Integration and Delivery job and automate your system tests by integrating them into it.
-
Execute a Git commit and push the content of your local
CAP-BOOKSHOP-WDI5
project into your GitHub repository. -
In SAP Continuous Integration and Delivery, go to the Jobs tab and choose + (Create job).
-
In the General Information section of the Create Job pane, enter the following values:
- Job Name: Freely choose a unique name for your job, for example,
cap-bookshop-wdi5
. - Repository: From the drop-down list, choose your repository.
- Branch: Enter the branch of your repository for which you want to configure your CI/CD job, for example,
main
. - Pipeline: From the drop-down list, choose SAP Cloud Application Programming Model.
- Version: If you create a new job, the latest version is selected by default.
- State: To enable your job, choose ON.
- Job Name: Freely choose a unique name for your job, for example,
-
In the Build Retention section, keep the default values.
-
In the Stages section, choose Job Editor as Configuration Mode.
-
For the Build stage, keep the default values.
-
For the Acceptance stage, enter the following values for the Deploy to Cloud Foundry Space step:
- Application Name: Enter a unique application name.
- API Endpoint: Enter the URL of your SAP BTP, Cloud Foundry API Endpoint. You can find it in the overview of your subaccount in the SAP BTP cockpit, under the Cloud Foundry Environment: tab.
- Org Name: Enter the name of your Cloud Foundry organization. You can also find it in the overview of your subaccount.
- Space: Enter the name of the Cloud Foundry space in which you want to test your application.
- Credentials: From the drop-down list, choose the SAP BTP credentials you created.
-
Enter the following values for the WebdriverIO Test step:
- npm Script: Use the same script name that is used to execute for local execution of the tests (
wdi5
). - Base URL: Enter the URL of the application against which the tests shall be executed. The application will be available under the following URL:
URLCopy
https://<Org Name>-<Space>-bookshop-srv.cfapps.us10-001.hana.ondemand.com/fiori-apps.html#Books-manage
Note: Depending on your region,
us10-001
could be different. - Space: Enter the name of the Cloud Foundry space in which you want to test your application.
- Credentials: As your test application doesn’t require credentials, leave this field empty.
- npm Script: Use the same script name that is used to execute for local execution of the tests (
-
Switch all other stages off and choose Create.
Note: As this tutorial focuses on how to get started with SAP Continuous Integration and Delivery, we’ve decided to configure only a very basic CI/CD pipeline in it. For how to configure more elaborate ones, see Supported Pipelines.
-
To run your CI/CD pipeline, choose Run.
As a result, a build of the connected job is triggered and a new build tile appears in the Builds section of your job. If you choose it, the Build Stages view opens and you can watch the individual stages of your build run through. The pipeline run might take a few minutes.
You can get an overview of the test results in the detailed log of your build:
-
- Set up and run your sample application
- Walk through the test scenario
- Create a test for adding a new book
- Create a test for adding detailed information to your book
- Configure your SAP BTP credentials in SAP Continuous Integration and Delivery
- (Optional) Configure your GitHub credentials in SAP Continuous Integration and Delivery
- Add your repository to SAP Continuous Integration and Delivery
- Integrate your system tests into your SAP Continuous Integration and Delivery job