ABAP Unit - TDF (CDS Double)
This article is about the test of Core Data Services and how you can switch off the test doubles with the help of the TDF.
The Test Double Framework (for short TDF) provides tools to generate so-called doubles for the objects class, table and core data service (CDS) during the test period and to test them against them. This technique is intended to reduce dependencies on objects that are difficult to test and focus on testing the actual component (class).
The CDS double behaves in a similar way to the SQL double, we exchange the data at the test runtime in the corresponding tables or entities in order to be able to perform our test. As an example, here is a hierarchy of views and tables.
To test the top view and the views below it, we have two different test variants:
- Test of the CDS view (2) - We exchange the direct accesses to the CDS view, regardless of whether it is a table or another CDS view and test the functionality of the view for itself. If all aggregations and calculated fields work, the data will be assigned correctly.
- Hierarchy test (3) - We exchange tables and other CDS views at any point in the hierarchy and test the data processing within the view hierarchy as well as the processing of the data up to the test view. Depending on the breadth of the hierarchy, this can be correspondingly time-consuming.
As an example, we have set a CDS view as an interface on the table with the tools and texts and published this as a consumption view with some additional logic. Here is the definition of the final view.
The hierarchy of the views and tables looks as follows via the SQL dependency graph (at the top the consumption view, in the middle the interface views and below the two database tables):
The result based on the existing data in the database is as follows. Note that the field names have been normalized for output.
Since we do not have a processing class for the CDS view, we create a global class that we identify as FOR TESTING. This means that the class cannot be used, but it contains all of our test cases for the Core Data Service.
CLASS zcl_bs_demo_double_cds DEFINITION PUBLIC FINAL CREATE PUBLIC FOR TESTING. PUBLIC SECTION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_bs_demo_double_cds IMPLEMENTATION. ENDCLASS.
Now the corresponding test class with the implementation of three test methods for testing:
- Determination of the total value
- Completeness of the test data
- Empty text if there is no language
CLASS ltc_cds_access DEFINITION FINAL FOR TESTING DURATION SHORT RISK LEVEL HARMLESS. PRIVATE SECTION. CLASS-DATA: go_environment TYPE REF TO if_cds_test_environment. CLASS-METHODS: class_setup RAISING cx_static_check, class_teardown. METHODS: totalvalue_calculation FOR TESTING, missing_text FOR TESTING, dataset_count FOR TESTING. ENDCLASS. CLASS ltc_cds_access IMPLEMENTATION. METHOD class_setup. DATA: lt_table_tools TYPE STANDARD TABLE OF zbs_dy_tools WITH EMPTY KEY, lt_cds_texts TYPE STANDARD TABLE OF zbs_i_tooltexts WITH EMPTY KEY. go_environment = cl_cds_test_environment=>create( i_for_entity = 'ZBS_C_COMPLETETOOLS' i_dependency_list = VALUE #( ( name = 'zbs_dy_tools' type ='TABLE' ) ( name = 'zbs_i_tooltexts' type ='CDS_VIEW' ) ) ). lt_table_tools = VALUE #( ( short_name = 'NAILS' stock_quantity = 2 price = '15.00' ) ( short_name = 'WRENCH' stock_quantity = 10 price = '17.99' ) ). go_environment->insert_test_data( i_data = lt_table_tools ). lt_cds_texts = VALUE #( ( ShortName = 'NAILS' Language = 'E' Description = 'Example text' ) ( ShortName = 'WRENCH' Language = 'D' Description = 'No text' ) ). go_environment->insert_test_data( i_data = lt_cds_texts ). ENDMETHOD. METHOD class_teardown. go_environment->destroy( ). ENDMETHOD. METHOD totalvalue_calculation. SELECT SINGLE * FROM zbs_c_completetools WHERE ShortName = 'NAILS' INTO @DATA(ls_result). cl_abap_unit_assert=>assert_equals( act = ls_result-TotalValue exp = '30.00' ). ENDMETHOD. METHOD missing_text. SELECT SINGLE * FROM zbs_c_completetools WHERE ShortName = 'WRENCH' INTO @DATA(ls_result). cl_abap_unit_assert=>assert_initial( ls_result-Description ). ENDMETHOD. METHOD dataset_count. SELECT * FROM zbs_c_completetools INTO TABLE @DATA(lt_result). cl_abap_unit_assert=>assert_equals( act = lines( lt_result ) exp = 2 ). ENDMETHOD. ENDCLASS.
The test data is set up in one step for a CDS view and for a database table, which simplifies the exchange within an entire hierarchy. The separation from the real data can be done on different levels, depending on what you want to test.
The test sequence is the same as for the SQL Double and therefore includes the following steps:
- Preparation of the test data in the CLASS_SETUP method
- Transfer of the test data to the environment
- Execution of the test cases
- Reduction of the environment in the CLASS_TEARDOWN method
Creation in Eclipse
In Eclipse there is a wizard that is made available for creating a test class for Core Data Services. This wizard creates a global test class and generates sample accesses to the data and provides an environment with test data. To do this, we create a test class for our consumption view.
To do this, right-click on the CDS view in the navigation tree and select the context menu entry for a new ABAP test class.
In the next step you define the name of the global test class and the designation. If necessary, you can also change the package if the test class should be placed in a different package.
Next you have to select the type of test, here you have the option of a simple unit test of the CDS view or a hierarchy test.
The next step is the corresponding test data, which can already be pre-assigned here. Corresponding data records can be pre-assigned for each entity that is exchanged.
After filling the data and clicking on “Finish”, the selected test class is created, the first test method is implemented and the data is filled. From here you can store further methods or data.
In order to be able to test Core Data Services, you first have to create a global test class for the objects and then you can implement your test cases. The test with data works similarly to the SQL Double.