Mittwoch, 11. Juli 2007

Anwendungstests mit eCATT

Modultests sind ein grossartiges Hilfsmittel bei der Softwareentwicklung. Aber Modultests sind nur dafür gedacht, isolierten Code zu testen. Sie unterdrücken die Abhängigkeiten von Datenbank, Benutzerschnittstellen und verwendeten API's. Das ist für Entwicklungen in einem SAP-System, in dem alles irgendwie mit allem zusammenhängt, eine harte Übung. Wie schon an früherer Stelle beschrieben, müssen sämtliche API-Aufrufe, Datenbankselektionen, Sperraufrufe, Updates für die Testausführung maskiert werden, ohne dass der produktive Code den Testmodus speziell berücksichtigt. Das ist auf jeden Fall zunächst mal viel Schreibarbeit und geht nur mit den Stub-Techniken, die Frank Westphal in seinem Buch über testgetriebene Entwicklung beschreibt. Einiges lässt sich durch geschickten Einsatz von Macros einsparen. Aber der Aufwand bleibt relativ zum Ertrag häufig zu hoch.

Wir Entwickler sollten uns nicht nur um Modul-, sondern auch um Anwendungstests bemühen (von manchen auch Funktionstests genannt). Das können wir nämlich auch selbst, und mit dem Programmieren von automatisierten Tests sind die (nicht entwickelnden) Prozessberater häufig überfordert. Aber gerade auf die automatische Abspielbarkeit kommt es an. Eine regelmässig eingeplante Suite von Anwendungstests mit email-Benachrichtigung im Fehlerfall (und bitte nur im Fehlerfall!) ergänzt die Modultests in idealer Weise. Die Anwendungstests werden in Programmteilen, die sehr viele Wechselwirkungen mit der Datenbank und API's aufweisen, den Schwerpunkt ausmachen. Denn mit einem geeigneten Tool sind Anwendungstests schneller zu erfassen, als das Programm zuerst mit diversen Stub-Objekten für Modultests flottzumachen.

Um Anwendungstests zu schreiben, bin ich als ABAP-Entwickler mit dem integrierten Testtool eCATT schneller als ich es mit einem externen Tool (wie Mercury) je sein könnte. Die Recorderfunktion zur Aufnahme von Transaktionen, kombiniert mit dem ABAP Inline Scripting, ergibt mächtige Gestaltungsmöglichkeiten für Testfälle.

Weiterer grosser Vorteil: Testfälle lassen sich auch mit dem Funktionsbaustein ECATT_EXECUTE aufrufen. So kann man in eigenen Testklassen bei Bedarf ein eCATT aufrufen, um zunächst eine Belegkette aufzubauen, auf der das neue Programmteil aufsetzen soll. eCATTs lassen sich ebenso problemlos im Hintergrund aufrufen. So kann man im SAP-Entwicklungssystem tägliche Jobs einplanen, die mit Anwendungstests bereits bestehende und ausgelieferte Funktionen zusichern.

Unten folgt zur Illustration ein Beispiel für ein eCATT-Testscript, das eine typische Retail-Belegkette beginnend mit der Umlagerbestellung aufbaut. Ich brauche das Script, um eine Fixture für ein Programmteil aufzubauen, das auf bestimmte Weise Wareneingänge buchen soll.

Schön ist die Möglichkeit, beliebigen ABAP-Code in das Script zu integrieren. Wenn es zuviel Code werden sollte, lagert man ihn besser in eine Methode aus. Auch kann man natürlich kleine Hilfsreports oder -transaktionen ins Script einbinden, die bestimmte Zwischenschritte in der Belegkette ausführen. Die Parametrisierung der Transaktionen durch Bearbeitung der mit dem Recorder aufgenommenen BDC-Transaktionsdaten ist etwas gewöhnungsbedürftig. Natürlich bin auch ich in die Falle gegangen und habe versucht, die ausgehenden Messagevariablen in den Transaktionsdaten abzugreifen, natürlich erfolglos. Schade ist auch, dass es keine ASSERT-Anweisung gibt. Das sollte für ein Test-Tool eigentlich zum Standardrepertoire gehören. Ich musste mir behelfen, indem ich eine bedingte Meldung vom Fehlertyp 'E' ausgebe. Das führt zum Abbruch des Testfalls mit einer entsprechenden Meldung im Protokoll. (Es scheint mir übrigens sinnvoll, für Nachrichten in Tests eine eigene Nachrichtenklasse zu verwenden.)
* UB anlegen, Daten aus Referenzbestellung REF_BESTELLUNG.
* Angelegte EBELN im Parameter EBELN merken.

TCD ( ME21 , ME21_3 ).
* Letzte Meldung enthält die UB-Nummer.
EBELN = ME21_3-MSG[&MSX]-MSGV2.
* Es muss eine Bestellung generiert worden sein.
IF ( EBELN <> ' ' ) .
* VL10B im Hintergrund starten.
TCD ( SE38 , SE38_2 ).
ABAP.
* Angelegte Lieferung aus Bestellentwicklung entnehmen
SELECT SINGLE BELNR INTO VBELN
FROM EKBE
WHERE EBELN = EBELN
AND BEWTP = 'L'.
ENDABAP.
IF ( VBELN <> ' ' ) .
LOG ( VBELN ).
* Auslieferung anlegen.
TCD ( ZMB03 , ZMB03_1 ).
* Letzte Meldung enthält die UB-Nummer.
IDOCNUM = ZMB03_1-MSG[&MSX]-MSGV2.
LOG ( IDOCNUM ).
* IDoc verbuchen.
TCD ( SE38 , SE38_1 ).
* Kontrollieren, ob WA angelegt
ABAP.
* SD-Belegfluss zur Lieferung
select single vbeln from vbfa into mblnr
where vbelv = vbeln
and vbtyp_n = 'R'.
ENDABAP.
IF ( MBLNR = ' ' ) .
* Fehler: Kein WA-Beleg angelegt
LOGMSG( LOGMSG_3 ).
ELSE.
LOG( MBLNR ).
* Alles korrekt durchgelaufen: Exportparameter füllen
EBELN_E = EBELN.
VBELN_E = VBELN.
MBLNR_E = MBLNR.
ENDIF.
ELSE.
* Fehler: Keine Lieferung angelegt
LOGMSG ( LOGMSG_2 ).
ENDIF.
ELSE.
* Fehler: Keine Bestellung angelegt.
LOGMSG ( LOGMSG_1 ).
ENDIF.

Kommentare :

Daniel Enderli hat gesagt…

Danke Rüdiger, ich greife oft zurück auf diesen Blogeintrag. Denn aktuell setze ich ebenfalls eCatt ein. Schau dir mal das SAP CBTA an, das ist ein guter Nachfolger von eCatt. Gruss Dani Enderli

Rüdiger Plantiko hat gesagt…

Hallo Dani,

danke für Dein Feedback. CBTA werde ich mir bei Gelegenheit mal anschauen.

Im Schwerpunkt steht bei uns, wie Du Dich noch erinnerst, das HP UFT. Dazu kommen auf Modultestseite meist noch qUnit-Tests bzw. ABAP Unit Tests.

Schöne Grüsse!
Rüdiger