Software-Engineering/Funktionstests für den App-Server

Geschäftsobjekte auf dem Prüfstand

09.03.2001
Die Drei-Stufen-Architektur zur Implementierung verteilter Applikationen hat weit reichende Auswirkungen auf das Testen der Software. Funktionstests auf Middle-Tier-Servern leisten einen wichtigen Beitrag zum Testen verteilter Objekte. Von Todd Scallan und Thomas Kern*

Einwandfreies Testen einer Software ist unerlässlich, wenn man die Zuverlässigkeit einer Applikation sicherstellen will. Die beiden Testmethoden, die hierzu grundsätzlich in Frage kommen, sind funktionales und strukturelles Testen. Funktionstests kontrollieren das "externe" Verhalten einer Software und verwenden hierbei die als "Black-Box"-Testen bekannte Methode. Ziel ist es - allgemein gesagt- zu überprüfen, ob ein Softwareprogramm seinen Spezifikationen und/oder den zuvor definierten Anforderungen entspricht. Hierzu müssen vor den Prüfungen zunächst die Spezifikationsdokumente gelesen sowie Testpläne und -daten erstellt werden.

Anders bei Strukturtests: Dort stehen die internen Abläufe einer Software im Mittelpunkt. Sie basieren auf der Methode des "White-Box"-Testen und nutzen für das Erstellen von Testfällen den Sourcecode eines Softwareprogramms. Dabei soll beispielsweise sichergestellt werden, dass alle logischen Schritte im Programmcode wenigstens einmal ausgeführt werden. Durch Einblick in den Sourcecode können Abhängigkeiten zu anderen Komponenten ermittelt und entsprechende Eingabedaten gewählt werden.

Iteratives Testen

Nicht nur für das Testen, sondern auch für die Entwicklung der Software gibt es zwei Ansätze. Heute wird statt des traditionellen Wasserfall-Modells immer öfter der objektorientierte Ansatz gewählt. Da dieser einen konsequent iterativen und schrittweisen Entwicklungsprozess mit sich bringt, kommen auch für Tests verschiedene Zeitpunkte in Frage. So sind in den Phasen Entwicklung und Wartung an den kritischen Punkten der Software verschiedene Arten des Testens möglich, wobei grundsätzlich im Verlauf des Projektes die Zahl und Bedeutung funktionaler Tests zu- und die der Strukturtests abnehmen.

Tests einzelner Komponenten

Strukturtests sind vor allem während der Entwicklung einer Softwarekomponente wichtig; während der Integration jedoch verlagert sich der Schwerpunkt vom Sourcecode der Komponente auf die Schnittstellen und die Interaktionen zwischen Komponenten. Bei Projekten, die auf Softwarebausteinen von Drittanbietern basieren, ist der Sourcecode außerdem gewöhnlich nicht einmal verfügbar, und Strukturtestläufe sind nicht möglich. Wenn ein Projekt schließlich in die Regressionstestphase eintritt, wird der Sourcecode nicht mehr berücksichtigt. Strukturtests beschränken sich zudem auf den Softwareentwickler, der Tests für eine bestimmte Komponente definiert und durchführt. Weitaus wichtiger für die Zuverlässigkeit einer Applikation sind aber die Zusammenarbeit der Komponenten und die Anpassungsfähigkeit, mit der diese auf Änderungen reagieren, also Funktionstests.

Tests der Interaktionen

Funktionale Tests erlauben eine Überprüfung auf der Ebene des User Interface (UI) und des Application Programming Interface (API). Auf UI-Ebene simuliert der Tester dabei den Benutzer und versucht, die Applikation zu überfordern. Sind Werkzeuge für das Automatisieren von Tests im Einsatz, lassen sich Interaktionen des Anwenders mit dem UI aufzeichnen und wiedergeben. Diese Testmethode findet sich in vielen Qualitätssicherungsabteilungen. Sie stellt aber eine vollständige Black-Box dar, so dass die Fehlerursache gewöhnlich unbekannt bleibt. Auf der API-Ebene muss der Entwickler spezielle Testtreiber schreiben und die Objekte oder Module, die über das API getestet werden, mit den Treibern verbinden. Dieser Ansatz kommt vor allem dann zum Einsatz, wenn die Schnittstellen von Objekten oder Modulen nicht dokumentiert sind.

Verteilte Applikationen werden heute meist in einer Drei-Ebenen-Architektur implementiert. Sie weisen eine Präsentations- und Interaktionsschicht, wie zum Beispiel einen Web-Browser, die eigentliche, komponentenbasierende Applikationslogik sowie eine Datenzugriffsschicht auf. Die Business Objects der Anwendungsschicht sind dabei der dominierende Teil einer dreistufigen Architektur und besitzen einige sehr nützliche Eigenschaften:

- Objekte können irgendwo innerhalb des Netzwerks platziert sein - ein notwendiges Attribut für verteilte Applikationen

- Ein transparenter Zugriff ermöglicht es den Clients, mit Servern ungeachtet ihres physikalischen Standorts zu interagieren. Die zugrunde liegende Infrastruktur kümmert sich um das Auffinden jeder Server-Quelle. Transparenz ist auch sehr wichtig für die Applikationsentwickler, weil sie ihnen ermöglicht, Applikationskomponenten zu entwickeln, ohne sich um Networking- oder Kommunikationsdetails kümmern zu müssen.

- Jedes Objekt kann in die Programmiersprache implementiert werden, die sich für die gerade aktive Aufgabe eignet, und auf jeder Plattform residieren. Beispielsweise kann ein Java-Objekt, das auf einer Windows-Plattform läuft, ein C++-Objekt auf einer Unix-Plattform aufrufen. Der Java-Client bemerkt nicht, dass der Server in C++ implementiert ist, weil er mit dem Server über native Java-Konstrukte kommuniziert.

- Schließlich bieten Business-Objekte die Basis für den Aufbau und die Entwicklung von Applikationen, die auf Komponenten beruhen.

Für Funktionstests derartiger Anwendungen ist eine beträchtliche Menge an API-Level-Tests erforderlich. Diese sind um einiges komplexer als das Testen nichtverteilter Applikationen über ein UI, da eine verteilte Applikation aus vielen verschiedenen Systemkomponenten, darunter verschiede Betriebssysteme, Applikationsmodule und Netzwerkverbindungen, besteht. Zudem erhöht sich der Koordinationsaufwand zwischen den Projektbeteiligten, es gilt verschiedenste Datenquellen zu integrieren, Applikationen verändern sich im Internet-Zeitalter mit zunehmender Geschwindigkeit, und ein neues Release einer Komponente muss meist im laufenden Betrieb eingespielt werden.

Technisch hilft hier der Einsatz von Komponententechnologie wie etwa Corba-Implementierungen als Kommunikations-Backplane oder Enterprise Javabeans (EJB) als Standard für Applikationskomponenten, die Business-Objekte auf dem Middle-Tier (Server) zu verwalten und zu steuern. Die mittlere Schicht spielt dadurch bei der Zuverlässigkeit von Applikationen eine lebenswichtige Rolle, denn die Integrationspunkte der verschiedenen Komponenten stellen potenzielle Ausfallpunkte des Systems dar. Umso problematischer scheint es daher zunächst, dass für funktionale Tests an Objekten keine Benutzerschnittstelle der Anwendung zur Verfügung steht.

Doch es gibt eine Lösung. Sie besteht im Einsatz eines generisches Test-Tool in der Präsentations- und Interaktionsstufe. Dieses kann direkt mit den Business-Objekten "zusammenarbeiten", dass heißt, es imitiert den erwarteten Server-Aufruf. Das Werkzeug muss hierzu aber eine Reihe von Herausforderungen meistern können (siehe Kasten "Anforderungen"). Zudem sollte ein gutes Test-Tool für Funktionstests von Middle-Tier-Servern nicht den Aufbau spezifischer Testprogramme und das manuelle Erzeugen von Regressions-Testfällen erfordern. Ebenso wäre es wünschenswert, wenn die Werkzeuge und Verfahren zum Schutz der eigenen Investitionen auf offenen Industriestandards aufbauen. Des Weiteren ist es empfehlenswert, dass zur Verbesserung der Produktivität die Testverfahren klar und intuitiv sowie die Tools leicht zu bedienen sind. Und schließlich sollten alle Server-Komponenten innerhalb verteilter Systeme gründlich getestet werden, da hierdurch das Vertrauen steigt, dass die Applikation in der Produktion zuverlässig arbeitet.

*Todd Scallan ist Vice President Development Lab., Thomas Kern ist Development Manager bei Segue Software in San Franzisko

Anforderungen

Um funktionale Tests auf dem Middle-Tier bewekstelligen zu können, muss das Testwerkzeug einige Funktionen bieten können:

1. Informationen über die Objekt-Schnittstellen einholen. Dokumentationen über die Schnittstellen sind durch Mechanismen in Standard-Middleware erhältlich. Beispielsweise nutzt EJB für das Lokalisieren von Objekten und Metadaten-Beschreibungen für lokale und entfernte Schnittstellen, Bean-Type- und Business-Verfahren JNDI das Verfahren NDF. Corba bietet das Schnittstellen-Repository, das Schnittstellen-Beschreibungen enthält, die während des Betriebs zugänglich sind. Ein allgemeines Test-Tool sollte eine User-Schnittstelle haben, durch die Informationen über das Interface eines Business-Object präsentiert werden könnten. Details über eine Schnittstelle beinhalten die verfügbaren Methoden, Verfahrensparameter, Rückmeldungen und mögliche Ausnahmen.

2. Aufruf-Methoden. Bei einem allgemeinen Test-Tool wäre es zu kompliziert, das Kompilieren statischer Objektbeschreibungen im Tool durchführen zu müssen. Stattdessen sollten dynamische Aufrufe verwendet werden, um Methodenanfragen nach dem Bedarf des Testers zu erzeugen. Das Reflection API von Java und das Dynamic Invocation Interface (DII) von Corba unterstützen ein schnelles, dynamisches Erkennen von Schnittstellen und das Erzeugen von Methodenaufrufen. Das Einsatzmodell des Test-Tools muss die Wahl einer Testmethode, die visuelle Erzeugung und das Editieren von Argumenten sowie unmittelbares Sichten der Resultate und Ausnahmen erlauben.

3. Aufnahme und Wiedergabe. Anfragen und Antworten, die durch ein Tool erfolgen, sind sinnvollerweise über passende externe Datendarstellung wie XML zu sichern. Der User sollte entscheiden können, welche Aktionen aufgenommen und für künftigen Gebrauch gespeichert werden. Das Test-Tool würde dann die externen Daten interpretieren, um eine Session wiederzugeben. Die externen Daten könnten auch verwendet werden, um Standalone-Test-Clients zu generieren. Diese Möglichkeiten sind erforderlich, um Regressionstesten zu unterstützen.

Abb: Test eines Business-Objekts

Die Testkonsole holt sich die Informationen über die Schnittstelle, ruft die Methoden auf, bewertet und verwaltet die Ergebnisse. (Quelle: Segue)