
BTP - ABAP Unit Runner
How can you regularly run your ABAP unit tests on the ABAP environment and have the results sent to you? There is currently no standard for this.
Table of contents
In this article, we set up the infrastructure for the ABAP Unit Runner and show you how you can consume the standard API from SAP. At the end, we can have our unit tests checked regularly on the system without having to start everything manually. The implementation was inspired by a query from Frank Engert.
Introduction
Last year, we looked at the topic of test automation in operations and how you can run your unit tests regularly with the right infrastructure. In the ABAP environment, the RS_AUCV_RUNNER report is not available to us as customers, even though it is available on the system. Currently, it is possible to automate the tests in the system using Jenkins Pipeline. However, it is not so easy for companies with ABAP development to provide a pipeline if they have not already dealt with the topic. That is why we are looking at an alternative in this article.
Architecture
So what do we want to do? In the following graphic you will find the planned architecture. We would like to provide a destination that points to the current system in order to be able to consume the service. Since there is no released API for this in the system, we use the external service SAP_COM_0735, which is also used for connecting pipelines.
Interface
For communication, we need a technical user with the appropriate authorizations for the interface and a destination in the destination service of the subaccount.
Communication Arrangement
In the first step, we have to make the interface available and set it up. To do this, we create a communication arrangement for SAP_COM_0735.
You can find the basic configuration for the communication system and the user in this article. We then need the access data for our destination in the same subaccount on the BTP. The communication arrangement could ultimately look like this, with the paths to the endpoint now available to us.
Destination
In the subaccount we create a connection that points to the ABAP environment and enter the user and password. This establishes the connection to the service.
Service
We can now begin with the actual connection. In the SAP documentation (linked below) we can find further information on how we need to prepare the HTTP call to create the first run. Here is an example from the project.
Creation
We create a client via the destination and prepare the HTTP call. We pass some parameters and the payload to this. Using the SET_CSRF_TOKEN method we get a simple method to get a token from the endpoint and put it in our request. To do this we need to have set the endpoint beforehand. We need the token because we need to send a POST to the interface to start our ABAP unit run.
DATA(destination) = cl_http_destination_provider=>create_by_cloud_destination(
i_name = run_setting-cloud_destination
i_authn_mode = if_a4c_cp_service=>service_specific ).
DATA(client) = cl_web_http_client_manager=>create_by_http_destination( destination ).
DATA(request) = client->get_http_request( ).
request->set_uri_path( zif_aur_runner=>endpoints-runs ).
request->set_content_type( zif_aur_runner=>content_type-start ).
request->set_text( get_request_payload( ) ).
client->set_csrf_token( ).
DATA(response) = client->execute( i_method = if_web_http_client=>post ).
IF response->get_status( )-code = 201.
RETURN response->get_header_field( `location` ).
ENDIF.
The payload is an XML object that we must prepare beforehand. You can find more information and an example in the documentation. The "LOCATION" header gives us the URL where we can query the status.
Status
To query the status, we only need to request the URL (location) using a GET request. We no longer need a CSRF token here. If our request was successfully executed, we receive an XML in response, which we then have to read in again. In the XML we find information about the run, the status of the execution and a URL for retrieving the results.
<?xml version="1.0" encoding="utf-8"?>
<aunit:run title="Testrun This" context="AIE Integration Test" xmlns:aunit="http://www.sap.com/adt/api/aunit">
<aunit:progress status="FINISHED" percentage="100"/>
<aunit:executedBy user="CC0000000000"/>
<aunit:time started="2025-02-06T19:37:22Z" ended="2025-02-06T19:37:38Z"/>
<atom:link href="/sap/bc/adt/api/abapunit/results/02E4C8A8EDEA1EDFB998391DAA3B1664" rel="http://www.sap.com/adt/relations/api/abapunit/run-result" type="application/vnd.sap.adt.api.junit.run-result.v1+xml" title="Run Result (JUnit Format)" xmlns:atom="http://www.w3.org/2005/Atom"/>
<atom:link href="/sap/bc/adt/api/abapunit/results/02E4C8A8EDEA1EDFB998391DAA3B1664" rel="http://www.sap.com/adt/relations/api/abapunit/run-result" type="application/vnd.sap.adt.api.abapunit.run-result.v1+xml" title="Run Result (ABAP Unit Format)" xmlns:atom="http://www.w3.org/2005/Atom"/>
</aunit:run>
Results
Finally, we can now retrieve the results, also as XML. Using the URL from the previous step, we can access the results of the run and parse them for evaluation or sending.
Encapsulation
We encapsulate the logic for the individual components and distribute them to the corresponding components. We need a core component for scheduling and retrieving the ABAP unit run, a component for parsing the XML file and a component for sending the email.
To decouple the logic and make it testable, we create two factories that generate instances for the runner, parser and email and use these in our code. This allows us to easily build unit tests for the logic in the next step. The current version does not contain any unit tests, but with the next release Joule will also be available for ABAP developers, so we can test this part at the same time.
The classes have also been given a corresponding interface so that we can provide a clean interface to the outside world. The constant and type definitions are in the interfaces, so we keep the class a bit cleaner, especially since we use a lot of internal data types for mapping and data passing.
We use our own structure for the settings, as we only want to transport the data through the interfaces, but also want to react flexibly to extensions. In principle, we could have used a configuration object, but since we didn't need any logic in this case, we decided to use a structure.
Usage
So that we can now schedule the test run in the ABAP environment, we create an Application Job with the appropriate input so that we can schedule our job regularly. The job catalog would look like this in this project.
After we have created a template and have the first initial values on the mask, the job in the "Application Jobs" app (F1240) would look like this.
If email sending is activated, we will receive the results by email either in the event of an error or after the ABAP Unit run has been completed. The various values were formatted in the email and individual cells were highlighted in color for quicker orientation.
The email class is responsible for preparing the email, which creates an HTML document using a few reusable blocks. The data is included in the email as individual tables and headings. In principle, the design of the email content can also be adjusted using the GET_CSS method.
Open Source
You can find the project as open source in our GitHub repository and can use it freely. Changes to the project will take place directly in the repository in the future. The target platform is the ABAP environment, theoretically also the public cloud, in order to provide the missing function of regular tests in the system.
Conclusion
Although there is no internal API for starting the ABAP unit tests for various objects, the external API provided by SAP works very well. Unfortunately, parsing the XML data was a bit complicated; we would have preferred a JSON interface here. There is also an article in the SAP Community.