Technical Articles
Automated Performance Testing of SAP Public OData APIs Part-II
Hello Knowledge Enthusiasts,
Welcome back to Part -II , in Part -I , we saw the details on API HUB and its features
In this section I’ll walk you through the solution and implementation details
Solution
Let’s look at a simplified and unified solution approach (complete details) and possibly address our problem statement
Challenges on our way to reach the solution:
- Constructing URL
- Asynchronous execution of selected API and collating the results.
The source of extraction of these APIs becomes the key , once we have identified that then we can download the entities(as shown below)
After having done this we would be able to allow the user to select a single / multiple entities per the need and allow it to be run on a specified target system with specified iterations
To develop business logic and user interface , we’ll first break it down into pieces and logically structure them(shown below)
Additional information:
Implementation
Having researched and thought about all the aspects lets look into the core development itself:
The approach follows the design pattern given below:
- Single User
- Single Task
- Maximum of Three Steps to accomplish the task
Programming logic
Promise provides a simple alternative to execute, manage asynchronous operations compared to traditional callback-based approaches.
var promise = new Promise((resolve, reject) => {
//asynchronous code goes here
});
new Promise( /* executor */ function(resolve, reject) { ... } );
The constructor accepts a function called executor.This executor function accepts 2 parameters resolve and reject which are also functions.
The initiation of these asynchronous operations happens within the executor function.
If the asynchronous operations are successful, then the expected result is returned by calling the resolve function by the creator of the promise.
Similarly, if there was some unexpected error the reasons are passed on by calling the reject function.
Note that a promise can have three states:
- pending (not fulfilled or rejected)
- fulfilled
- rejected
- Pending – the promise’s outcome is not yet determined, because the asynchronous operation that will produce its result hasn’t completed yet.
- Fulfilled – the asynchronous operation succeeded and has a value.
- Rejected – the asynchronous operation failed, and the promise will never be fulfilled. In the rejected state, a promise has a reason that indicates why it failed.
When a promise is pending, it can transition to the fulfilled or rejected state.
Once a promise is fulfilled or rejected, however, it will never transition to any other state, and its value or failure reason will not change.
Sample Promise
var promisesArray = [];
promisesArray.push(promise1);
promisesArray.push(promise2);
promisesArray.push(promise3);
Promise.all(promisesArray).then(function(values) {
console.timeEnd(“Promise.All”);
console.log(“All the promises are resolved”, values);
}).catch(function(reason) {
console.log(“One of the promises failed with the following reason”, reason);
});
Like the above, nested promises can also be used.
Basic Rules for using Promises
- Use promises when async or blocking code is used
- resolve maps to then and reject maps to catch for all practical purposes.
- Ensure to write both .catch and .then methods for all the promises.
- If something needs to be done in both the cases use .finally
- We only get one shot at mutating each promise.
- We can add multiple handlers to a single promise.
- The return type of all the methods in Promise object whether they are static methods or prototype methods is again a Promise
- For Promise.all the order of the promises is maintained in values variable irrespective of which promise was first resolved.
Additional information
The main runs selected were 3(for example) , since buffered runs are implicitly handled (always = 3 : shown in orange) , total of 6 calls , the performance measurements are only accounted for the last 3(shown in green) see below details from Network :
Since this is with Parameter an additional call will be made , the main runs selected were 3 , since buffered runs are implicitly handled(always = 3) similar to the previous one, shown below:
Shows the response time(ms) from Gateway and after computation its then displayed in the UI
URI of the above ( Screenshot : 12)
Execute Without Params (Need basis only)
User can select to retrieve only the top 10 / top 100 / Full set , performance behavior becomes even more transparent
No of items for the above execution was 5671 which is shown in the excel below :
User can select the Target system and the API’s as well
Debugging as to why it displayed as NA
because the result set is empty as shown below
User has an advantage to copy the complete URI and try it in a browser unlike the URI shown in Screenshot 12
In contrast it was executed in ER9 where it was successful
My Favorite Feature(1) is the following :
If the user selects all for a given API(as shown below for the first API) and clicks on any execute it intelligently will execute only the entities that meet the criteria (w.r.t with param and without param)
Similarly for execute without parameter , default is Top10
My Favorite Feature(2) is the following ,
AUTO -> Once the User clicks this button it automatically executes all the steps for custom criteria
Conclusion
We have successfully created an Automated Performance test for OData services of the S/4 HANA Cloud via a simple UI.
Benefits of this approach are listed below:
- Easy to use UI , Better understanding of executions trends and system behavior
- User can select API’s/ Runs/Target System( With & Without Params)
- Mass execution are possible
- No maintenance required , buffered runs are implicitly handled
- Complete E2E Automation
- Extremely Transparent at all levels
- Debugging made easy
- Efficient execution outcomes
Thanks,
Dilip Mamidela
SAP Labs India