Automated tests for ABAP transactional applications
In this blog-post i want to show you some ideas how to automate testing for ABAP transactional applications.
ABAP transactional applications contain a lot of stuff, which is difficult to test automatically:
- form printing
- database updates
When the user interface is highly integrated in the application, a good approach for automated testing is ECATT. If the API is isolated, we can also use ABAP unit.
Forms (SAPScript-Forms, Smartforms) contain often some processing and they are part of the result. So we should test them. In the first test-execution a human could check the form. But in the second and in the third test-execution the machine could compare the created spool-jobs with a snapshot of the spool-job approved by a human in the first test-execution. The spool-API gives us with the function-module
RSPO_RETURN_SPOOLJOB the possibility to access the generated content. So automate testing can be reduced to a comparison of OTF-data (only for SAPScript-Forms or Smartforms). In the repository you can find a realization of this idea.
Whenever a change is made to the affected forms, we can check them manually in the first approach and create a new snapshot, which is later used as expected result for the automated tests.
A note to Adobe PDF forms
Adobe PDF forms are bit trickier to test. OTF is a text format and is human readable at least a little bit :). PDF is a binary format and is definitely not human readable. Of course we can create a snapshot of PDF-data and compare this snapshot, but the diff wouldn’t be very descriptive. So i omit PDF forms in my consideration.
To make testing reproducible it’s necessary to prepare the database or to erase the changes after the test-execution.
We have to differ between custom code and SAP standard-code. In custom code, database updates affect often just a few isolated database tables. Here it’s suitable to prepare the database tables or to use the OpenSQL test-double framework (class
cl_osql_replace), if we can do so. One of my favorite tools in this context is the ABAP DB preparator.
In SAP standard-code database updates affect a lot of different tables, which we don’t know at all and which stand in relationship to other tables. Preparing the well known database-tables or using the OpenSQL test-double framework for them is not good idea, because this approach creates inconsistencies and broken relationships. Just think of goods-movement documents. If you you are going to replace the table
MCHB (batch-stock) by some test-double, you have an inconsistency between the batch stock and the financial valuated stock in table
MBEW. The better approach here is to erase the changes for example by canceling the goods-movement document, which was created in the test.
Transactional applications play a important role in ABAP development. I hope i could show some useful tips how to test them and how to create a scaffolding for refactorings.
Thanks for sharing your knowledge on testing form printing and database updates. I just would like to say, I am not fully agree on your below statement.
Preparing the well known database-tables or using the OpenSQL test-double framework for them is not good idea, because this approach creates inconsistencies and broken relationships.
Actually, using OpenSQL test-double framework is very helpful. You don't need to insert the mock data in a real meaning. You may use 'cl_osql_test_environment=>create' to add your tables to your mock environment and then after use the method 'insert_test_data' to add your mock data to those tables mentioned with the create method. NONE of them effects the database in the real meaning INSTEAD they would treat as in that way, like they were really in the database. With that approach, you wouldn't be risking anything (such as updating the table and forgetting to revoke them).
One colleague recently share this quite simple blog about mocking db with OpenSQL.
you can use the OpenSQL test-double framework, if you know every database table, which could be updated. But in transactional applications we often use BAPIs like BAPI_GOOSMVT_CREATE etc. The BAPIs are not our code, so we don't know every database table touched by these BAPIs. Some tables are just touched for certain conditions. When mocking the database tables MSEG and MKPF a lot of tables like MCHB, MBEW or MBEWH involved in the update will be not mocked and therefore updated, but no entry will created in table MSEG and MKPF.
Now we have an inconsistency. The stock in table MCHB doesn't match with the quantities of the created goods movements.
For this reason i prefer mocking database tables just for my own code, where i know every involved database table. For BAPIs i prefer canceling the changes with a corresponding BAPI.