ABAP Unit - TDF (Test Double)
In diesem Artikel geht es um das Ausschalten von Dependend-On Component und wie man solche Komponenten ganz leicht testen kann.
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
Ein Test-Double soll abhängige Komponenten in einem Testfall deaktivieren, um so einen kontrollierten Test der Logik zu ermöglichen und so nicht abhängig von anderen Objekten und ihrem Zustand zu sein. Da ein Unit-Test nur die aktuelle Komponente (Klasse) testet, sind abhängige Komponenten (DOC - Dependend-On Component), wenn möglich, zu deaktivieren bzw. zu kontrollieren.
Im Beispiel (1) siehst du die Komponente, die von unserer zu testenden Klasse verwendet wird. Bei der Vorbereitung des Tests (2) tauschst du dann einfach die Komponente mit einem Test Double aus und verringerst so Abhängigkeiten zu deinen Testfällen.
Hinweis: Für die Erzeugung eines Test Doubles wird immer ein globales Interface benötigt und wird zwingend vorausgesetzt.
Begriffe
Immer wieder werden dir bei der Verwendung von Test Doubles auch verschiedene Begriffe über den Weg laufen, die den Test Double nur in seiner Funktion beschreiben. An dieser Stelle einmal eine Auflistung der Namen und Funktionen:
- Test Double - allgemeiner Begriff für alle Arten von Doubles
- Stub - stellt indirekten Input zur Verfügung
- Spy - loggt indirekten Output
- Fake - einfachste Implementierung eines Test Double
- Mock - Erweiterung für Stub, Spy und Fake der indirekten In-/Output validiert
- Dummy - Keine Logik, nur zur Einhaltung der Syntax
Beispiel
Im folgenden Beispiel besitzt die zu testende Klasse eine abhängige Komponente die eine Ausgabe als ALV triggert. Diese Ausgabe würde unseren Test verhindern und einen Abbruch auslösen, da in Unit Tests keine GUI Komponenten funktionieren. Aus diesem Grund benötigen wir einen Test Double, um unsere Klasse sauber testen zu können und um möglichst wenig Coding anpassen zu müssen.
Die Klasse, die wir testen wollen, sieht wie folgt aus, dabei haben wir zur Vereinfachung die abhängige Komponente in den PUBLIC Bereich übernommen.
CLASS zcl_bs_demo_double_class DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
DATA:
mo_uicomponent TYPE REF TO zif_test_display.
METHODS:
constructor,
select_and_show_data
IMPORTING
id_short_name TYPE zbs_dy_tools-short_name
RETURNING VALUE(rd_displayed) TYPE abap_bool.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
CLASS zcl_bs_demo_double_class IMPLEMENTATION.
METHOD constructor.
mo_uicomponent = NEW zcl_test_display( ).
ENDMETHOD.
METHOD select_and_show_data.
SELECT *
FROM zbs_dy_tools
WHERE short_name = @id_short_name
INTO TABLE @DATA(lt_found_tools).
rd_displayed = mo_uicomponent->display_generic_data( lt_found_tools ).
ENDMETHOD.
ENDCLASS.
Dazu legen wir die folgende Testklasse an, die unsere Klasse nun automatisch testen soll:
CLASS ltc_double_access DEFINITION FINAL FOR TESTING
DURATION SHORT
RISK LEVEL HARMLESS.
PRIVATE SECTION.
METHODS:
selection_without_ui FOR TESTING.
ENDCLASS.
CLASS ltc_double_access IMPLEMENTATION.
METHOD selection_without_ui.
DATA:
lt_dummy_data TYPE STANDARD TABLE OF zbs_dy_tools.
DATA(lo_cut) = NEW zcl_bs_demo_double_class( ).
" Step 1
lo_cut->mo_uicomponent = CAST #( cl_abap_testdouble=>create( 'zif_test_display' ) ).
" Step 2
cl_abap_testdouble=>configure_call( lo_cut->mo_uicomponent )->ignore_parameter( 'IT_DATA' )->returning( abap_true ).
" Step 3
lo_cut->mo_uicomponent->display_generic_data( lt_dummy_data ).
DATA(ld_result) = lo_cut->select_and_show_data( 'SCREWDRIVER' ).
cl_abap_unit_assert=>assert_true( ld_result ).
ENDMETHOD.
ENDCLASS.
In der Testmethode erzeugen wir uns das CUT Objekt und bereiten den Test-Double vor. Hierfür werden einige Schritte durchgeführt. Im Anschluss rufen wir wieder die zu testende Methode auf.
Ablauf
Der Ablauf beim Verwenden eines Test-Doubles muss dringend eingehalten werden, ansonsten funktioniert das Double nicht korrekt:
- Erzeugung des Doubles über das globale Interface (Schritt 1)
- Konfiguration des Doubles und der zu erwartenden Parameter (Schritt 2)
- Aufruf der abhängigen Methode vorm eigentlichen Aufruf der Testmethode zur Übergabe der Importparameter (Schritt 3)
Hinweis: Diese Schritte müssen zwingend eingehalten werden, damit das Double sauber arbeitet und der Testfall funktioniert.
Fazit
Der Test Double ist die älteste Methode um DOCs zu Testen und existiert bereits auf älteren Releases, weit vor S/4 HANA und dem Modernen ABAP. Wenn du die Methodik zur Einrichtung und den Aufruf verstanden hast, sollte es kein Problem mehr sein, diesen auch einzusetzen.