Software-Test / Testautomatisierung

SAP Testautomatisierung – plattformübergreifender Test mit JCo 1/2

SAP bietet einige Tools zur Testautomatisierung an (eCATT, CBTA). Diese Tools sind nahtlos in die SAP GUI integriert und können vom Testmanagement Werkzeug SAP Test Workbench verwendet werden.
Die Grenzen der SAP-Welt werden jedoch schnell überschritten: sei es, weil Ihr Produkt neben SAP weitere Technologien wie Web oder .NET nutzt und diese gemeinsam getestet werden müssen oder weil Ihre Organisation die Nutzung bestimmter Testmanagementwerkzeuge einfach vorgibt, und sie müssen sich mit diesen Rahmenbedingungen arrangieren.

 

Mal angenommen…

Im Artikel Test Automation Practices: Keywords, Page Objects und Clients in Java stellte Stefan Gwihs eine Automatisierungsarchitektur mit einem Java Framework und Selenium vor. Als Beispiel verwendete er eine Bestellung in einem Webshop. Ich führe das Beispiel in diesem Artikel weiter.
Angenommen ein Webshop erweitert sein Angebot um Geschenkgutscheine, mit denen im Shop verbilligt eingekauft werden kann. Ein Kunde gibt bei seiner Bestellung den Gutschein-Code ein und erhält eine Ermäßigung zwischen 10 und 1000 Euro, je nach Gutschein.

 

Der neu entwickelte Geschenkgutschein für einen Webshop soll getestet werden

Der neu entwickelte Geschenkgutschein für einen Webshop soll getestet werden

 

Als Tester bzw. Testautomatisierer müssen Sie nun diese Rabatte testen. Dazu benötigen Sie natürlich funktionierende Gutscheine. Die einfachste Lösung ist es, sich vor dem Test einen Stapel Gutscheine zu besorgen welche nun kontinuierlich von Testfällen verwendet und somit verbraucht werden können. Nach Murphy’s Law wird aber genau dann wenn es wichtig ist kein Gutschein mehr übrig sein. Alternativ könnten Sie auch vor jedem Test zuerst im Webshop einen Geschenkgutschein kaufen, den Gutschein-Code auslesen und diesen dann im eigentlichen Test verwenden. Diese Lösung ist sicherer, aber deutlich aufwändiger, fragiler und erhöht die Durchlaufzeit eines Testfalls dramatisch; zudem wird so neben dem Rabatt an sich auch die Gutschein-Bestellung über den Webshop getestet, eine Funktionalität, die besser in einem separaten Testfall aufgehoben wäre. In diesem fiktiven Fall wäre es daher am besten, direkt vor dem Test über das Support-Backend einen Gutschein zu erstellen und diesen zu verwenden. Das ist minimalinvasiv, schnell und deutlich stabiler als die Bestellung über das Frontend. Das Problem dabei ist allerdings, dass dieses Backend unserem Webshop eine SAP-Transaktion ist…

 

Ausgangslage

Das Runde muss in das Eckige; der Java-Testfall muss auf SAP zugreifen können

Das Runde muss in das Eckige; der Java-Testfall muss auf SAP zugreifen können

 

Solche und ähnliche Szenarien unterstreichen den Nutzen, den eine plattformübergreifende SAP Testautomatisierung mit sich bringt. Und in der Tat werben viele Anbieter kommerzieller Automatisierungstools damit, dass sie SAP, Web, Windows und weitere Technologien mit einem einzigen Tool integriert testen können. Die Nutzung dieser Tools birgt aber häufig Probleme:

  • Sie sind eben kommerziell; die Anbieter lassen sich die Möglichkeiten durchaus teuer bezahlen.
  • Plattformübergreifende Tools sind keine Spezialisten in dem jeweiligen Gebiet, sondern Generalisten. Manche Dinge lassen sich mit ihnen nur unvollständig oder kompliziert testen.
  • In vielen Tools ist es mitunter schwierig den Testfall von der Technologie zu trennen. Dadurch werden Testfälle kompliziert zu lesen (für den Fachbereich) und bei Änderungen schwer zu warten (für den Testautomatisierer).

Ein alternativer Ansatz ist die modulare Vorgehensweise mit fachlichen Keywords und technischen Abstraktionsschichten. Ein Testfall könnte dann in unserem Beispiel folgendes fachliches Keyword enthalten:

order().useVoucher(50);

 

Dieses Keyword nutzt für die Bestellung einen Gutschein in Höhe von 50 Euro. Wo und wie dieser Gutschein im Bestellvorgang genau angegeben werden muss ist zum Verständnis des Testfalls nicht wichtig. Dass der Gutschein vor der Verwendung im Keyword über SAP und eCATT erstellt wurde, muss der Fachbereich gar nicht im Detail wissen. Das muss nur der Testautomatisierer, der sich um die Anbindung an die SAP-Transaktion zur Erstellung der Gutscheine kümmert.

Nehmen wir weiter an, der Testautomatisierer war fleißig und hat in eCATT bereits das Skript Z_TS_ERSTELLE_GUTSCHEIN geschrieben, das den gewünschten Betrag als Import Parameter erhält, in der SAP GUI in der passenden Transaktion einen neuen Gutschein erstellt und den Gutschein-Code als Export Parameter zurückgibt. Sehr gut, jetzt müssen wir nur noch das eCATT Testskript mit dem Java-Keyword verheiraten. Und wie machen wir das?

 

SAP Java Connector (JCo)

Auch hierfür bietet SAP ein geeignetes kostenloses Tool an: die Middleware SAP Java Connector (JCo), welche von http://service.sap.com/connectors heruntergeladen werden kann. Man benötigt hierfür lediglich einen SAP Service Marketplace Login mit entsprechenden Downloadrechten.

JCo ermöglicht es aus Java heraus SAP RFCs (Remote Function Calls) ausführen. Von diesen gibt es auf einem SAP-System jede Menge: Zugriff auf BAPIs (Business Application Programming Interface), auf fachliche und administrative Transaktionen etc. (der Autor hat auf dem Testsystem eines Kunden über achtzehntausend RFCs gezählt). Für die SAP Testautomatisierung ist vor allem ein RFC interessant: mit ECATT_EXECUTE lassen sich eCATT-Skripte ausführen.

Sobald man JCo heruntergeladen und die JAR Bibliothek in Java eingebunden hat, kann man den Connector nutzen:

import com.sap.conn.jco.*;

 

Destination

Das erste JCo-Objekt, mit dem man sich befassen sollte, ist die Destination. Diese ermöglicht den Zugriff auf ein bestimmtes SAP-System:

JCoDestination destination = JCoDestinationManager.getDestination("MyDestinationFile");

 

MyDestinationFile.jcoDestination (die Dateiendung ist obligatorisch) ist letztendlich eine Textdatei, die die Verbindungsdaten zum gewünschten SAP-System enthält. User und Passwort sind die Zugangsdaten, mit denen man sich selbst als Tester im SAP Login auf das System einwählen würde. Die anderen Werte kann man sich im SAP Login oder rechts unten in der SAP GUI abschauen. Für eCATT ist es noch wichtig, den Parameter use_sapgui=1 zu setzen; erst das erlaubt es JCo, auf eigene Faust die GUI zu öffnen.

# SAP JCo destination file
 jco.client.ashost=sapsystem123
 jco.client.client=880
 jco.client.sysnr=00
 jco.client.lang=de
 jco.client.user=taf-automation
 jco.client.passwd=loremipsum
 jco.client.use_sapgui=1
 jco.destination.peak_limit=10
 jco.destination.pool_capacity=3

 

Der direkte Ansatz: Ausführen von eCATTs

Wir schießen den Ball direkt ins Tor; wir führen eCATT-Skripte direkt aus.

Wir schießen den Ball direkt ins Tor; wir führen eCATT-Skripte direkt aus.

 

Über die Destination lässt sich nun ECATT_EXECUTE verwenden:

JCoFunction ecattExecute = destination.getRepository().getFunction("ECATT_EXECUTE");

 

Vor der Ausführung der JCoFunction ecattExecute muss man diese erst konfigurieren. Und es gibt einiges zu konfigurieren: ein getImportParameterList() liefert eine ganze Reihe Parameter, die teils selbst wiederum Tabellen mit weiteren Parametern sind.

JCoParameterList allImportParameters = ecattExecute.getImportParameterList();

 

Im Netz findet man hierzu nur bruchstückhafte Informationen; es bleibt nichts anderes übrig als per Trial & Error eine Lösung zu finden. Der wichtigste Parameter ist natürlich, welches eCATT-Skript eigentlich ausgeführt werden soll. Diese Information muss in den JCo Import Parameter TO_EXECUTE geschrieben werden, welcher selbst wieder eine Tabelle ist (eine JCoTable). Eine passende Tabelle händisch zu erstellen ist allerdings sehr mühsam; man kann sich diese Arbeit glücklicherweise ersparen, da der JCo Export Parameter EXECUTED eine Tabelle derselben Bauart ist. Bei unserer neu erstellten JCoFunction ist die Tabelle EXECUTED zwar (noch) leer, aber zumindest nicht NULL, so wie es TO_EXECUTE ist. Wir instanziieren diese Tabelle also als Blaupause, befüllen sie mit den passenden Werten und nutzen sie dann als JCo Import Parameter:

JCoTable BLUEPRINT = ecattExecute.getExportParameterList().getTable("EXECUTED");
BLUEPRINT.appendRows(1);
BLUEPRINT.nextRow();
BLUEPRINT.setValue("OBJ_TYPE", "ECSC"); // ECSC = ECatt test SCript
BLUEPRINT.setValue("OBJ_NAME", "Z_TS_ERSTELLE_GUTSCHEIN");
ecattExecute.getImportParameterList().setValue("TO_EXECUTE", BLUEPRINT);

 

Da TO_EXECUTE eine Tabelle ist, kann sie mit mehr als einem Datensatz befüllt werden; so könnte man mehrere eCATT-Skripte auf einmal ausführen. Für unsere Zwecke tut es jedoch ein einzelnes Skript.

Das reicht für den ersten Testlauf, man kann ecattExecute nun das erste Mal ausführen:

ecattExecute.execute(destination);

 

Es wird nun ein SAP GUI Fenster geöffnet und in diesem Z_TS_ERSTELLE_GUTSCHEIN ausgeführt (eCATT muss auf dem System verfügbar sein, das Skript muss lokal existieren). Der Test endet mit der Anzeige des Testprotokolls. Sobald das SAP-Fenster händisch geschlossen wird, läuft der Test weiter. Man kann diesen händischen Eingriff vermeiden, indem man vor dem Aufruf des execute() die Anzeige des Testprotokolls deaktiviert:

ecattExecute.getImportParameterList().setValue("DISPLAY_LOG", "");

 

…und jetzt?

Auf direktem Weg kommen wir nicht mehr ans Ziel; wir müssen Hindernisse durchbrechen

Auf direktem Weg kommen wir nicht mehr ans Ziel; wir müssen Hindernisse durchbrechen

 

Wir können jetzt aus unserem Java-Framework heraus eCATT-Skripte ausführen. Was wir allerdings noch nicht können, ist dem Skript Parameter mitgeben. Woher soll das Skript wissen, welchen Wert der erstellte Gutschein haben soll? Auch das Auslesen des Gutschein-Codes fehlt noch: wie bekommen wir den Code in das Java-Keyword, so dass dieses im Webshop an geeigneter Stelle den Gutschein einlösen kann?

Hier stößt man an die Grenzen von ECATT_EXECUTE, denn der RFC bietet keine Möglichkeit, Parameter direkt in ein eCATT-Skript zu schreiben oder aus ihm zu lesen. Man erhält lediglich die ID des eCATT-Testprotokolls und eine Fehlermeldung, falls das eCATT-Skript fehlgeschlagen ist – aber diese beiden Werte alleine reichen nicht aus.

String errorMessage = 
ecattExecute.getExportParameterList().getTable("EXECUTED").getValue("ERR_MSG").toString();
String metaScriptProtokollId = 
ecattExecute.getExportParameterList().getStructure("LOGID").getValue("LOGID").toString();

 

Um mit einem eCATT-Skript wirklich interagieren zu können, muss man sich noch einiger Kniffe bedienen. Wie diese genau aussehen, wird im zweiten Teil dieses Artikels beleuchtet.

 

(The Incredible Machine: https://de.wikipedia.org/wiki/The_Incredible_Machine)

 

Passende Artikel

Kommentare gesperrt.