ABAP Unit - TDF (CDS Double)
In diesem Artikel geht es um den Test von Core Data Services und wie die du die Test Doubles mit Hilfe des TDF ausschalten kannst.
Inhaltsverzeichnis
Das Test Double Framework (kurz TDF) stellt Werkzeuge zur Verfügung um für die Objekte Klasse, Tabelle und Core Data Service (CDS) zur Testlaufzeit sogenannte Doubles zu erzeugen und gegen sie zu Testen. Diese Technik soll Abhängigkeiten zu schwer testbaren Objekten reduzieren und sich auf den Test der eigentlichen Komponente (Klasse) fokussieren.
Allgemein
Beim CDS Double verhält es sich so ähnlich wie bei dem SQL Double, wir tauschen die Daten zur Testlaufzeit in den entsprechenden Tabellen oder Entitäten aus, um unseren Test durchführen zu können. Dazu als Beispiel einmal eine Hierarchie von Views und Tabellen.
Um die oberste View und die Views darunter zu testen, stehen uns zwei verschiedene Testvarianten zur Verfügung:
- Test des CDS Views (2) - Wir tauschen die direkten Zugriffe zum CDS View aus, egal ob Tabelle oder anderer CDS View und testen die Funktionalität der View für sich. Funktionieren alle Aggregationen und Calculated Fields, werden die Daten korrekt zugeordnet.
- Hierarchie Test (3) - Wir tauschen Tabellen und andere CDS Views an beliebigen Stellen der Hierarchie aus und testen die Datenverarbeitung innerhalb der View Hierarchie, sowie die Verarbeitung der Daten bis hin zum Testview. Je nach Breite der Hierarchie kann das entsprechend aufwändig sein.
Beispiel
Als Beispiel haben wir auf die Tabelle mit den Werkzeugen und Texten jeweils einen CDS View als Interface gesetzt und diese als Consumption View mit etwas Zusatz-Logik publiziert. Hier einmal die Definition der finalen View.
Dabei sieht die Hierarchie der Views und Tabellen wie folgt über den SQL Dependency Graph aus (an oberster Stelle der Consumption View, in der Mitte die Interface-Views und unten die beiden Datenbanktabellen):
Das Ergebnis anhand der vorhandenen Daten in der Datenbank sehen wie folgt aus. Zu beachten ist, dass die Feldnamen für die Ausgabe normalisiert wurden.
Da wir für den CDS View keine verarbeitende Klasse haben, legen wir eine globale Klasse an, die wir als FOR TESTING kennzeichnen. Damit ist die Klasse nicht verwendbar, enthält aber unsere gesamten Testfälle für den 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.
Dazu nun die entsprechende Testklasse mit der Implementierung von drei Testmethoden zur Prüfung von:
- Ermittlung des Gesamtwerts
- Vollständigkeit der Testdaten
- Leerer Text bei fehlender Sprache
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.
Aufbau der Testdaten geht in einem Schritt für einen CDS View und für eine Datenbanktabelle, was den Austausch innerhalb einer ganzen Hierarchie vereinfacht. Die Trennung zu den echten Daten kann auf verschiedenen Ebenen erfolgen, je nachdem was man testen möchte.
Ablauf
Der Ablauf der Tests gestaltet sich wie beim SQL Double und sieht deshalb die folgenden Schritte vor:
- Vorbereitung der Testdaten in der Methode CLASS_SETUP
- Übergabe der Testdaten an das Environment
- Durchführung der Testfälle
- Abbau des Environment in der Methode CLASS_TEARDOWN
Anlage Eclipse
In Eclipse gibt es für die Anlage einer Testklasse für Core Data Services einen Wizard der zur Verfügung gestellt wird. Dieser Wizard legt eine globale Testklasse an und erzeugt Beispiel Zugriffe auf die Daten und stellt ein Environment mit Testdaten zur Verfügung. Dazu legen wir für unseren Consumption View eine Testklasse an.
Dazu im Navigationsbaum auf den CDS View Rechtsklick und Auswahl des Kontextmenü-Eintrags für eine neue ABAP Testklasse.
Im nächsten Schritt legst du den Namen der globalen Testklasse und die Bezeichnung fest. Gegebenenfalls kannst du auch noch das Paket ändern, wenn die Testklasse in einem anderen Paket untergebracht werden soll.
Als Nächstes musst du die Art des Tests auswählen, hier hast du die Möglichkeit eines einfachen Unit Tests des CDS Views oder einem Hierarchie Test.
Als Nächstes folgen die entsprechenden Testdaten, die man bereits hier vorbelegen kann. Für jede Entität, die man austauscht, kann man entsprechende Datensätze vorbelegen.
Nach Befüllung der Daten und einem Klick auf “Finish” wird die entsprechend gewählte Testklasse angelegt, die erste Testmethode implementiert und die Befüllung der Daten übernommen. Ab hier kannst du weitere Methoden oder Daten hinterlegen.
Fazit
Um COre Data Services testen zu können, musst du im ersten Schritt eine globale Testklasse für die Objekte anlegen und kannst dann deine Testfälle implementieren. Der Test mit Daten funktioniert ähnlich wie beim SQL Double.