SAP Transaktion ME21N

Ranorex Testautomatisierung mit SAP Funktionsbausteinen

Ranorex ist primär ein Werkzeug für den Test auf Ebene von User Interfaces (UI). SAP lässt sich mit Ranorex analog zu Web und Windows Anwendungen auf dieser Ebene testen. Eine bessere Alternative zum Test auf UI-Ebene ist der Test auf Serviceebene gemäß der Test Pyramide. Vorteile sind die bessere Wartbarkeit der Testfälle sowie die schnellere Ausführung. Im SAP wird die Serviceebene häufig durch Funktionsbausteine implementiert. In diesem Beitrag beschreibe ich die Ranorex Testautomatisierung mit SAP Funktionsbausteinen.

Services im SAP

Im SAP wird die Serviceebene häufig durch Funktionsbausteine implementiert. Z.B. implementiert der Funktionsbaustein BAPI_PO_CREATE1 das Anlegen einer Bestellung. Der Funktionsbaustein ist das Pendant auf Service Ebene zur SAP-Transaktion ME21N, über welche eine Bestellung auf UI-Ebene angelegt wird. Eine Automatisierung der SAP-Transaktion ME21N ist aufwendig und fehleranfällig, weil sie sehr verschachtelt ist und viele Tabellen benutzt, in denen die UI-Objektadressierung schwierig ist.

SAP Transaktion ME21N

Die folgende Abbildung zeigt die Schnittstelle des Funktionsbaustein BAPI_PO_CREATE1. Die Schnittstelle besteht aus Vielzahl von Struktur- und Tabellenparametern. Bevor man den Baustein via Ranorex automatisiert aufruft, sollte man zunächst die richtige Parametrisierung ermitteln, da dies in vielen Fällen komplex ist. Deshalb ist es sinnvoll, den Funktionsbaustein zunächst im SAP via ABAP Unit Tests zu testen.

Funktionsbaustein BAPI_PO_CREATE1

Ranorex Testautomatisierung mit SAP Funktionsbausteinen

Damit Ranorex auf SAP-Funktionsbausteine zugreifen kann, muss der kostenlose SAP Connector for Microsoft .NET in die Ranorex Solution eingebunden werden. Der Connector stellt eine API zur Verfügung, die in einem Ranorex Coding Module verwendet werden kann.

Voraussetzung für den Zugriff auf einen Funktionsbaustein ist dessen Remote-Fähigkeit (RFC). Für einen eigenentwickelten Funktionsbaustein ist dies durch ein simples Aktivieren dieser Eigenschaft bei der Definition des Funktionsbausteins zu erreichen. Bei einem durch SAP entwickelten Baustein ist dies unter Umständen nicht der Fall. Hier muss der aufzurufende SAP-Funktionsbaustein durch einen eigenentwickelten RFC-Funktionsbaustein umhüllt werden. Für eine Vielzahl von Testszenarien existieren aber bereits RFC-Funktionsbausteine von SAP selber.

Einbinden des SAP Connectors in die Ranorex Solution

Der Connector besteht aus 4 DLLs. In die Ranorex Solution sind sapnco.dll und sapnco_utils.dll als References aufzunehmen.

Solution Reference SAP .Net Connector

Implementierung des Testfalls als Ranorex Coding Module

Der Aufruf des SAP Funktionsbausteins wird in Ranorex als Coding Module implementiert.

Die Connector-API ist im Namespace SAP.Middleware.Connector implementiert. Deshalb wird dieser zunächst mit der using-Direktive bekannt gemacht.

Über den RfcDestinationManager werden die Verbindungsinformationen zum SAP gelesen. Wie diese konfiguriert werden, wird weiter unten erläutert.

Ein SAP-Funktionsbaustein wird im Connector als IRfcFunction verfügbar gemacht. In diesem Fall ist zu beachten, dass neben dem Funktionsbaustein BAPI_PO_CREATE1 auch der Funktionsbaustein BAPI_TRANSACTION_COMMIT benötigt. Der Hintergrund ist, dass der Funktionsbaustein BAPI_PO_CREATE1 kein Commit der übergebenen Daten auf der SAP-Datenbank durchführt. Dies muss durch einen expliziten Aufruf von BAPI_TRANSACTION_COMMIT durchgeführt werden.  Über den RfcSessionManager wird dem Connector mitgeteilt, dass beide Aufrufe auf der gleichen SAP-Verbindung ausführen soll.

Auf die Parameter des Funktionsbausteins wird über IrRfcStructure und IrfcTable zugegriffen. In diesem Beispiel sind die folgenden Parameter zu füllen. Die Füllung der Parameter ist abhängig vom Testfall und den Einstellungen des SAP-Systems.

  • POHEADER: Kopfdaten der Bestellung wie Lieferant, Buchungskreis etc.
  • POHEADERX: Flags, welche Kopfdaten gefüllt wurden
  • POITEM: Positionsdaten der Bestellung wie Material, Menge und Werk
  • POITEMX: Flags, welche Positionsdaten gefüllt wurden

Die im Code sichtbaren Variablen wie DocType, CompCode etc. sind Modulvariablen, damit das Code Module über eine Data Source parametrisiert werden kann.

private void bapiPurchaseOrderCreate()
        {
        	const string TRUE = "X";
            RfcDestination destination = RfcDestinationManager.GetDestination("NCO_TESTS");
            IRfcFunction bapiPoCreate = destination.Repository.CreateFunction("BAPI_PO_CREATE1");
            IRfcFunction bapiTransCommit = destination.Repository.CreateFunction("BAPI_TRANSACTION_COMMIT");
            
            RfcSessionManager.BeginContext(destination);
            
            try {
                IRfcStructure poHeader = bapiPoCreate.GetStructure("POHEADER");
                poHeader.SetValue("DOC_TYPE", DocType);
                poHeader.SetValue("COMP_CODE", CompCode);
                poHeader.SetValue("PURCH_ORG", PurchOrg);
                poHeader.SetValue("PUR_GROUP", PurGroup);
                poHeader.SetValue("VENDOR", Vendor);
                
                IRfcStructure poHeaderX = bapiPoCreate.GetStructure("POHEADERX");
                poHeaderX.SetValue("DOC_TYPE", TRUE);
                poHeaderX.SetValue("PURCH_ORG", TRUE);
                poHeaderX.SetValue("COMP_CODE", TRUE);
                poHeaderX.SetValue("PURCH_ORG", TRUE);
                poHeaderX.SetValue("PUR_GROUP", TRUE);
                poHeaderX.SetValue("VENDOR", TRUE);
                
                IRfcTable poItems = bapiPoCreate.GetTable("POITEM");
                poItems.Append();
                poItems.SetValue("PO_ITEM", PoItem1);
                poItems.SetValue("MATERIAL", Material1);
                poItems.SetValue("PLANT", Plant1);
                poItems.SetValue("QUANTITY", Quantity1);
                
                IRfcTable poItemsX = bapiPoCreate.GetTable("POITEMX");
                poItemsX.Append();
                poItemsX.SetValue("PO_ITEM", "00001");
                poItemsX.SetValue("MATERIAL", TRUE);
                poItemsX.SetValue("PLANT", TRUE);
                poItemsX.SetValue("QUANTITY", TRUE);
                
                bapiPoCreate.Invoke(destination);
                
                IRfcTable bapiReturnTab = bapiPoCreate.GetTable("RETURN");
                checkReturn( bapiReturnTab );
                
                string poNumber = bapiPoCreate.GetString("EXPPURCHASEORDER");
                Ranorex.Report.Success("PoNumber:" + poNumber);
                
                bapiTransCommit.Invoke(destination);
            }    
            finally
            {
                RfcSessionManager.EndContext(destination);
            }
        }

Durch den Aufruf der Invoke-Methode auf dem IRfcFunction-Objekt wird der Aufruf durchgeführt. Die Nummer der Bestellung wird über den Parameter EXPPURCHASEORDER zurückgegeben und als Success-Meldung in das Ranorex Log ausgegeben.

Als letzter Schritt wird über RfcSessionManager.EndContext die SAP-Verbindung ordnungsgemäß abgebaut.

Die Ermittlung, ob der Aufruf erfolgreich war, ist in Methode checkReturn implementiert. SAP RFC-Funktionsbausteine melden üblicherweise über einen RETURN-Parameter zurück, ob der Aufruf erfolgreich war. Der RETURN-Parameter bildet eine Meldung ab. Eine Fehlermeldung wird mit dem TYPE = E signalisiert. Die Methode checkReturn iteriert über die Tabelleneinträge und prüft das Feld TYPE einer Tabellenzeile. Ist die Meldung ein Fehler, wird eine Ausnahme mit dem Meldungstext geworfen. In allen anderen Fällen wird die Meldung in das Ranorex Log ausgegeben. Über den RETURN-Parameter wird auch die Erfolgsmeldung (hier: „Normalbestellung unter der Nummer 4500017782 angelegt“) zurückgeliefert.

private static void checkReturn(IRfcTable bapiReturnTab) {
			for (int i=0; i<bapiReturnTab.Count; ++i) {
				bapiReturnTab.CurrentIndex = i;
				string msg = bapiReturnTab.GetString("MESSAGE");
                Ranorex.Report.Info(msg);
                string msgType = bapiReturnTab.GetString("TYPE");
                
                if (msgType == "E") {
                    throw new System.Exception(msg);
                }
			}
        }

Die folgende Abbildung zeigt den Aufbau des RETURN-Parameters.

SAP Return Parameter

Konfiguration der SAP-Verbindung

Die Konfiguration der SAP-Verbindungsparameter (Hostname, Benutzer, Kennwort…) erfolgt über die app.config-Datei in der Ranorex Solution, welche beim Build der Solution in die Datei bin\Debug\<RanorexSolution>.exe.config kopiert wird.

Die ConfigSections aus diesem Beispiel können ohne Anpassung übernommen werden. Die Verbindung zum SAP wird in einem destinations-XML-Element definiert. In der Abbildung sind 3 verschiedene Destinations sichtbar, die sich in ihrer Parametrisierung unterscheiden. Durch den Code benutzt wird lediglich die Destination NCO_TESTS. Hier sind neben den SAP-Systeminformationen ASHOST und und SYSNR auch die Benutzerinformationen USER, PASSWD, CLIENT und LANG einzugeben. Die Destination NCO_LB_TESTS ist ein Beispiel, wenn der SAP-Zugriff über den SAP Message Server erfolgen soll.

Jede Ranorex Solution besitzt eine Standard app.config, welche nur das XML-Element startup enthält. Die Reihenfolge, wie die für den Connector erforderlichen XML-Elemente in die app.config eingefügt werden, ist relevant.

app.configfür Connector

Fazit

Das war es schon! Die Ausführung des Testfalls sollte das Ergebnis so aussehen wie in der folgenden Abbildung. Wir haben gesehen, dass Ranorex nicht nur für das UI Testing, sondern auch für die Testautomatisierung auf Service Ebene geeignet ist. Im Unterschied zum UI Testing braucht man hierfür jedoch Entwicklerkenntnisse in .Net.

SAP Service Test Ausführung

 

 

Veröffentlicht in ABAP

Über den Autor

Rüdiger Lühr

Kommentar verfassen