Konzept: Stubs
Diese Richtlinie beschreibt, wie Sie einen Stub erstellen, der als Platzhalter für Komponenten verwendet werden kann, die noch entwickelt werden müssen. Ein Stub ist eine Komponente, die im Prinzip nicht anderes tun muss, als sich selbst und die akzeptierten Parameter zu deklarieren. Der Stub enthält gerade so viel Code, dass er kompiliert und mit den restlichen Komponenten verlinkt werden kann.
Beziehungen
Zugehörige Elemente
Hauptbeschreibung

Einführung

Eine Komponente wird getestet, indem Eingaben an ihre Schnittstelle gesendet werden. Dann wird gewartet, dass die Komponente die Eingaben verarbeitet, und anschließend werden die Ergebnisse geprüft. Im Verlauf der Verarbeitung verwendet eine Komponente in der Regel andere Komponenten, indem sie Eingaben an diese sendet und die zurückgegebenen Ergebnisse verwendet:

Im Begleittext beschriebene Abbildung

Abb1: Implementierte Komponente testen

Diese anderen Komponenten können aus den folgenden Gründen Probleme beim Testen verursachen:

  1. Sie sind möglicherweise noch nicht implementiert.
  2. Sie weisen unter Umständen Mängel auf, die die Durchführung Ihrer Tests behindern oder dafür verantwortlich sind, dass Sie viel Zeit damit verbringen herauszufinden, dass der Testfehler nicht von Ihrer Testkomponente verursacht wurde.
  3. Sie können die Ausführung von Tests erschweren. Wenn eine Komponente eine kommerzielle Datenbank ist, hat Ihr Unternehmen möglicherweise nicht genügend Floating-Lizenzen für jedermann. Oder eine Komponente könnte Hardware sein, die nur zu bestimmten Zeiten in einem separaten Labor verfügbar ist.
  4. Sie können die Tests so verlangsamen, dass die Tests nicht häufig genug ausgeführt werden. Das Initialisieren der Datenbank kann beispielsweise fünf Minuten pro Test dauern.
  5. Es kann schwierig sein, die Komponenten dazu zu bringen, bestimmte Ergebnisse zu erzeugen. Beispiel: Sie möchten, dass jede Ihrer Methoden, die auf die Platte schreibt, Fehler des Typs "Platte voll" behandelt. Wie stellen Sie sicher, dass die Platte gerade zu dem Zeitpunkt voll ist, wenn eine dieser Methoden aufgerufen wird?

Solche Probleme können Sie mit Stub-Komponenten (oder Attrappenobjekten) vermeiden. Stub-Komponenten verhalten sich wie die echten Komponenten, zumindest was die Werte anbelangt, die Ihre Komponente an diese Komponenten sendet, während sie auf ihre Tests reagiert. Sie können sogar noch mehr als das: Sie können vielseitig einsetzbare Emulatoren sein, die versuchen, das meiste oder das gesamte Verhalten der Komponente zu simulieren. Häufig empfiehlt es sich beispielsweise, Softwareemulatoren für Hardware zu erstellen. Sie verhalten sich wie die Hardware, nur langsamer. Sie sind hilfreich, weil sie ein besseres Debugging ermöglichen, weil mehr Exemplare von ihnen verfügbar sind und weil sie verwendet werden können, bevor die Hardware zusammengestellt ist.

Im Begleittext beschriebene Abbildung

Abb2: Implementierte Komponente durch Darstellung einer abhängigen Komponente als Stub testen

Stubs haben zwei Nachteile.

  1. Die Kosten für ihre Erstellung können hoch sein. (Dies gilt insbesondere für Emulatoren.) Da sie selbst Software sind, müssen sie auch gepflegt werden.
  2. Sie verdecken Fehler. Angenommen, Ihre Komponente verwendet trigonometrische Funktionen, aber es ist noch keine Bibliothek verfügbar. Ihre drei Testfälle fragen den Sinus von drei Winkeln ab: 10 Grad, 45 Grad und 90 Grad. Sie verwenden Ihren Taschenrechner, um die richtigen Werte zu berechnen und erstellen dann einen Sinus-Stub, der die Werte 0,173648178, 0,707106781 und 1,0 zurückgibt. Alles ist in Ordnung, bis Sie Ihre Komponente mit der echten trigonometrischen Bibliothek integrieren, deren Sinusfunktion Argumente in Radianten erwartet und deshalb -0,544021111, 0,850903525 bzw. 0,893996664 zurückgibt. Dies ist ein Mangel in Ihrem Code, der erst später, möglicherweise später als Ihnen lieb ist, erkannt wird.

Stubs und Verfahren für Softwaredesign

Sofern die Stubs nicht erstellt wurden, weil die echte Komponente noch nicht verfügbar ist, sollten Sie damit rechnen, dass die Stubs auch nach dem Deployment beibehalten werden. Die Tests, die sie unterstützen, sind wahrscheinlich für die Produktpflege sehr wichtig. Bei der Codierung von Stubs muss deshalb ein höherer Standard angesetzt werden als bei "Wegwerfcode". Obwohl sie nicht dem Standard von Produktcode entsprechen müssen (beispielsweise benötigen die meisten keine eigene Testsuite), müssen die Entwickler sie später als Komponenten der Produktänderung verwalten. Wenn diese Verwaltung zu streng ist, werden die Stubs verworfen, und die Investition gehen damit verloren.

Wenn Stubs beibehalten werden sollen, haben sie Einfluss auf das Komponentendesign. Angenommen, Ihre Komponente verwendet eine Datenbank, um Schlüssel/Wert-Paare persistent zu speichern. Schauen Sie sich die folgenden beiden Designszenarios an:

Szenario 1: Die Datenbank wird für Tests und für den normalen Betrieb verwendet. Die Existenz der Datenbank muss vor der Komponente nicht verdeckt werden. Sie können sie mit dem Namen der Datenbank initialisieren:

 public Component(

String DatenbankURL) { try {     databaseConnection =         DriverManager.getConnection(DatenbankURL);     ... } catch (SQLException e) {...}     }

Obwohl Sie sicherlich nicht möchten, dass jede Position, die einen Wert liest oder schreibt, eine SQL-Anweisung erstellt, so haben Sie doch einige Methoden, die SQL enthalten. Der Komponentencode, der einen Wert benötigt, könnte beispielsweise die folgende Komponentenmethode aufrufen:
 public String get(String key) { try {     Statement stmt =       databaseConnection.createStatement();     ResultSet rs = stmt.executeQuery(       

"SELECT value FROM Table1 WHERE key=" + key);     ... } catch (SQLException e) {...}     }

Szenario 2: Für die Tests wird die Datenbank durch einen Stub ersetzt. Der Komponentencode sollte bei der Verwendung eines Stub genauso aussehen wie bei der Verwendung einer echten Datenbank. Deshalb muss er so codiert werden, dass Methoden einer abstrakten Schnittstelle verwendet werden:
 

interface SchluesselWertPaare { String 

get(String Schluessel); void 

put(String Schluessel, String Wert);     }

Tests implementieren SchluesselWertPaare mit etwas Einfachem wie einer Hash-Tabelle:
 

class FakeDatabase implements SchluesselWertPaare  { Hashtable table = new Hashtable(); public String 

get(String Schluessel) {     return (String) table.get(Schluessel); } public void 

put(String Schluessel, String Wert) {     table.put(key, Wert); }     }
Wenn die Komponente nicht in einem Test verwendet wird, verwendet sie ein Adapterobjekt, das Aufrufe an die Schnittstelle SchluesselWertPaare in SQL-Anforderungen konvertiert:
 

class DatabaseAdapter implements SchluesselWertPaare { private Connection databaseConnection; public DatabaseAdapter(String DatenbankURL) {     try {         databaseConnection =             DriverManager.getConnection(DatenbankURL);         ...     } catch (SQLException e) {...} } public String 

get(String Schluessel) {     try {         Statement stmt =            databaseConnection.createStatement();         ResultSet rs = stmt.executeQuery(           "SELECT value FROM Table1 WHERE Schluessel=" + Schluessel);         ...     } catch (SQLException e) {...} } public void 

put(String Schluessel, String Wert) {     ... }     }

Ihre Komponente kann einen einfachen Konstruktor für Tests und andere Clients haben. Dieser Konstruktor erwartet ein Objekt, das SchluesselWertPaare implementiert. Er könnte diese Schnittstelle aber auch nur Tests bereitstellen und voraussetzen, das gewöhnliche Clients der Komponente den Namen einer Datenbank übergeben:
 class Component { 

public Component(String DatenbankURL) {     this.valueStash = new DatabaseAdapter(DatenbankURL); } // Für Tests.

Geschützt Component(SchluesselWertPaare valueStash) {     this.valueStash = valueStash; }     }

Vom Standpunkt des Clientprogrammierers aus wird in beiden Szenarios dieselbe API verwendet, aber eine ist schneller testfähig. (Beachten Sie, dass einige Tests die echte Datenbank verwenden können und andere die Stub-Datenbank.)

Weitere Informationen


Weitere Informationen zu Stubs finden Sie in den folgenden Veröffentlichungen: