Freigeben über


.NET-Interop

Automatisieren von Akzeptanztests mit IronRuby

Ben Hall

Codedownload verfügbar in der MSDN-Codegalerie
Code online durchsuchen

Themen in diesem Artikel:
  • Was sind Akzeptanztests?
  • Automatisierte Akzeptanztests
  • Implementieren von Akzeptanztests
In diesem Artikel werden folgende Technologien verwendet:
IronRuby

Inhalt

Was sind Akzeptanztests?
Automatisierte Akzeptanztests
Die Vorgaben
Szenarios
Implementieren von Akzeptanztests
Das Ausführungsprogramm des RSpec-Szenarios bei der Interaktion mit C#-Objekten
Akzeptanztests der Benutzeroberfläche
Ausblick

Der Traum fast jedes Entwicklers ist es, dass Kundenanforderungen richtig vermittelt werden können, sodass keine Zeit für das Implementieren unvollständiger oder falscher Funktionen verschwendet werden muss. Wäre es nicht großartig, wenn der Entwickler dem Kunden eine klar verständliche Spezifikation überreichen und ausfindlich machen könnte, ob die Features den Kundenanforderungen entsprechen, und dann genau diese Spezifikation ohne weiteren Aufwand ausführen könnte, um die Implementierung anhand der Anforderungen zu überprüfen?

Diese Ebene der Kommunikation zwischen Kunden und Entwicklern lässt sich mithilfe des Konzepts von Akzeptanztests und ausführbaren Spezifikationen erreichen. Durch Nutzung der verhaltensgesteuerten Entwicklung (Behavior Driven Development, BDD) können Anforderungen effektiver vermittelt werden.

In meinem Artikel in der Ausgabe des MSDN Magazins vom Februar 2009 (Erste Schritte mit IronRuby und RSpec, Teil 1) wurde IronRuby vorgestellt und aufgezeigt, wie Sie damit die dynamische Ruby-Sprache zur Zusammenarbeit mit .NET-kompatiblem Code wie C# verwenden können. Im vorliegenden Artikel geht es um das Konzept von Akzeptanztests. Aufbauend auf den Konzepten aus dem vorhergehenden Artikel wird erläutert, wie Akzeptanztests mithilfe von IronRuby und RSpec automatisiert werden können, um .NET-Anwendungen zu überprüfen und eine ausführbare Spezifikation für das System zu erstellen.

Was sind Akzeptanztests?

Der Begriff „Akzeptanztests“ hat viele verschiedene Definitionen. Für mich geht es bei Akzeptanztests um die Überprüfung, ob das gerade entwickelte System die Anforderungen des Kunden erfüllt, und weniger um das Verringern der Fehleranzahl im Code. Bei Akzeptanztests geht es also nicht um das Testen von Code, sondern darum, das vom Kunden oder Unternehmen gewünschte Produkt zu erstellen. Das scheint einleuchtend, doch ein Mangel an Akzeptanztests und ein ähnlicher Mangel beim Verständnis der Anforderungen sind die Hauptgründe für das Fehlschlagen vieler Projekte.

Akzeptanztests funktionieren nur mit Unterstützung des Kunden oder zumindest eines Vertreters des Kunden, der beim Definieren der Kriterien behilflich ist. Wenn keine Akzeptanzkriterien aufgestellt werden, können Sie nicht überprüfen, ob die Software korrekt und richtig ist. Der Kunde sollte sich mit allen Mitgliedern des Entwicklungsteams zusammensetzen, um das System im Hinblick auf eine Reihe von zu testenden „Szenarios“ zu definieren, die beschreiben, was das System auf welche Weise ausführen soll.

Ein Beispiel: Wenn Sie ein E-Commerce-System entwickeln, könnte ein Akzeptanztest auf der Interaktion mit dem Warenkorb basieren. Ein typisches Szenario sieht z. B. wie folgt aus: „Wenn der Warenkorb leer ist und das Produkt 123 hinzugefügt wird, sollte sich die Artikelzahl um 1 erhöhen, und die Zwischensumme sollte 20 $ betragen.“ Sie erhalten einen Einblick, wie sich der Warenkorb gemäß den Erwartungen des Kunden verhalten sollte, sowie Hinweise auf Schritte zum Überprüfen der Implementierung. Mit zunehmender Größe des Systems ergeben sich weitere Szenarios zum Überprüfen verschiedener Teile des Systems und der Featureliste.

Eine wichtige Überlegung beim Schreiben der Szenarios ist die Sprache, die dazu verwendet wird. Es sollte sprachlich wiedergegeben werden, wie das Unternehmen das Problem versteht und nicht, wie ein Entwickler die Lösung implementieren würde. Wenn die Tests im Hinblick auf die eigentliche Implementierung geschrieben würden („wenn ich auf die Schaltfläche 'Senden' klicke, ändert sich die Beschriftung 'Bestätigen'“), ist dies nur von geringem Nutzen für den Kunden, da es sich auf die eigentliche Systemimplementierung bezieht. Wenn sich die eigentliche Implementierung ändert, aber die Geschäftsanforderungen dieselben bleiben, sind für diese Abhängigkeit zusätzliche Wartungskosten erforderlich, da das Team die entsprechenden Tests aktualisieren muss.

Durch das Erstellen von Tests mit klaren Anforderungen und Kriterien ist es sehr viel wahrscheinlicher, dass die Kundenerwartungen erfüllt werden. Doch dazu muss manuell überprüft werden, ob die Anforderungen erfüllt werden und die Anwendung wie erwartet funktioniert. Hier kommt das Konzept der automatisierten Akzeptanztests ins Spiel. Die Anforderungen befinden sich dabei nicht in einem veralteten Dokument in einer Dateifreigabe, sondern werden als Beispiele und Szenarios definiert, die zusammen mit den Implementierungsartefakten in die Quellcodeverwaltung eingecheckt werden. Sie können dann jederzeit ausgeführt werden, um zu überprüfen, ob eine Anforderung implementiert wird und richtig funktioniert. Sie können beim Schreiben der Tests denselben Ansatz verwenden, doch statt sie in eine Testfallverwaltungssoftware oder eine Tabelle zu schreiben, werden sie direkt in den Code geschrieben.

Automatisierte Akzeptanztests

Akzeptanztests helfen bei der Überprüfung, ob Sie die Anwendung wie vom Kunden gewünscht erstellen, während das Automatisieren dieser Szenarios eine ständige Überprüfung der Implementierung während des Entwicklungsprozesses ermöglicht. Sie können diese Szenarios dann als Teil der Regressionstestsuite verwenden, um sicherzustellen, dass zukünftige Änderungen nicht gegen vorhandene Anforderungen verstoßen.

Doch wenn der Kunde am Schreiben der Tests, insbesondere automatisierter Tests, beteiligt ist, führt dies zu einer Reihe potenzieller Probleme. Kunden sind im Allgemeinen nicht technisch orientiert und scheuen sich vor der eigentlichen Softwareentwicklung. Durch Zusammenarbeit mit dem technischen Team kann der Kunde Ideen und Beispiele bereitstellen, während die Tester oder Entwickler die Szenarios und die ausführbare Spezifikation schnell codieren können. Zudem müssen die Szenarios für alle Mitarbeiter im Unternehmen einleuchtend sein. Mithilfe von IronRuby können Sie die Lesbarkeit von Tests verbessern, doch wie sieht dies in der Praxis aus?

Um zu zeigen, wie dieser Prozess möglicherweise in einem wirklichen Projekt verwendet werden könnte, wird im Folgenden die Implementierung der Benutzervorgaben für ein Preisberechnungssystem vorgestellt. Es ist ein einfaches Beispiel, an dem die entsprechenden Schritte aber gut verdeutlicht werden können. Akzeptanztests bieten einen Rahmen dafür, wie Sie an ein Problem herangehen können, und es gibt viele Varianten und Interpretationen. Dennoch sollten auf diese Weise die Grundkonzepte vermittelt werden, sodass Sie in Zukunft herausfinden können, welche Techniken im Einzelnen die für Sie richtigen sind.

Dieses Beispiel stammt aus der Präsentation „Rot, Grün, Umgestaltung“, die ich kürzlich einer lokalen Benutzergruppe vorgestellt habe. Anschließend bat mich ein Teilnehmer um Rat, wie er bei seiner Anwendung effektiv einen Komponententest durchführen kann, um sicherzustellen, dass alle Preisberechnungen einschließlich verschiedener Optionen und Ergänzungen zu dem Paket richtig berechnet werden. Dieses Beispiel zeigt perfekt, in welchen Fällen Akzeptanztests sehr nützlich sind. Da sich die Vorgaben und das Szenario um Preise und Ihre Erwartungen dreht, können Sie sicher sein, dass das System richtig arbeitet.

Diese Überprüfungen sind außerdem eine nützliche Quelle für die Dokumentation des Entwicklungsteams und des Kunden, um anhand verschiedener Beispiele aufzuzeigen, wie das System funktioniert, und die verschiedenen Ausnahmen vorzustellen. Wenn ein Kunde meint, ein Preis sei falsch, kann das Team auf die vom Kunden genehmigte, ausführbare Spezifikation als Nachweis für die abgeschlossene Arbeit verweisen.

Ohne diese Tests würden die Regeln für Preisangaben wahrscheinlich in riesigen Word-Dokumenten definiert, die zu erklären versuchen, wie das System verschiedene Preisberechnungskonfigurationen behandelt, wobei diese Dokumente vom gerade entwickelten System prinzipiell getrennt sind. Aus diesem Grund vertraue ich auf automatisierte Akzeptanztests.

Die Vorgaben

Beim Entwickeln eines Preisberechnungssystems mit dem Ziel, Akzeptanztests zu verwenden, besteht die erste Phase darin, von allen Versammelten die Vorgaben definieren zu lassen. Die Kunden definieren ihre Wünsche, wobei sie von technischen Mitgliedern des Teams unterstützt werden. Wie im vorhergehenden Artikel erwähnt, sollte beim BDD ein festes Format zum Definieren der Anforderungen verwendet werden, um eine konsistente Sprache zwischen den Teammitgliedern zu fördern und speziell die Dinge zu unterstützen, die vom Kunden verlangt werden. Anhand des folgenden Formats geben Sie die Einzelheiten in Zusammenarbeit mit dem Kunden ein:

Als [Rolle] wünsche ich mir [Feature], damit [Ergebnis].

Ein Fehler gleich zu Anfang besteht oft darin, dass Implementierungsdetails in die Vorgaben aufgenommen werden. Beispiel:

Als Administrator wünsche ich mir, dass Preise in einer Rasteransicht in „default.aspx“ angezeigt werden, damit ich die Kosten angeben kann.

Die Vorgaben dürfen das Problem nur in spezifischen Wirtschaftsbegriffen beschreiben und sollten keine technischen Einzelheiten enthalten. Ein verbessertes Beispiel könnte so aussehen:

Als Vertriebsadministrator wünsche ich mir, dass Preise für einen Kunden identifiziert werden, damit ich ihm die Kosten angeben kann.

Obwohl das Format eingehalten wird, enthält es leider einige sehr undeutliche Informationen und bietet keinen Ausgangspunkt für die Implementierung. Ein noch besseres Beispiel sähe so aus:

Als Vertriebsadministrator wünsche ich mir, dass Preise für Produkt x angezeigt werden, damit ich dem Kunden auf Grundlage seiner Anforderungen genaue Kosten angeben kann.

Diese Vorgaben bieten weitere Einzelheiten und mehr Kontext zu den Erwartungen des Kunden und zu seinen tatsächlichen Wünschen. Daher sind sie für den Entwickler beim Implementieren des Systems von erheblich größerem Nutzen.

Beim Schreiben von Anforderungen und Features muss unbedingt beachtet werden, sich möglichst auf das Wesentliche konzentrieren. Dadurch wird es viel einfacher, Szenarios zu erstellen, Tests zu schreiben und den fertigen Code zu implementieren. In einigen Systemen könnten die Vorgaben auf einem Feature basieren.

Szenarios

Selbst wenn Vorgaben vorhanden sind, benötigen Sie trotzdem noch mehr Informationen dazu, was den Erwartungen zufolge geschehen sollte. Szenarios sind dabei äußerst nützlich. Ein Szenario erklärt einfach, dass in einem bestimmten Kontext bei einem bestimmten Ereignis ein bestimmtes Ergebnis erwartet wird. Ziel ist es, ein konkreteres Beispiel dafür zu bieten, wie sich die Implementierung der Vorgaben in verschiedenen Situationen auswirken sollte. Auf diese Weise werden dem Team Erwartungen vermittelt und Schritte zur Überprüfung bereitgestellt.

Die empfohlene Syntax wird als GWT-Syntax (Given, When, Then – Annahme, wenn, dann) bezeichnet und von Dan Norden befürwortet:

Given [Kontext], When [etwas geschieht], Then [Ergebnis].

Ein Beispielszenario könnte so aussehen:

Szenario: Einzelbenutzerlizenz für Produkt X ohne Unterstützung

Annahme: Produkt X. Wenn der Benutzer eine Einzelbenutzerlizenz wünscht und diese keine Unterstützung umfasst, dann sollte der Preis 250 $ betragen.

„Und“ kann verwendet werden, um mehrere Kontexte oder Ergebnisse zu verbinden, sodass Sie das Szenario sinnvoller gestalten und mehr Informationen zum Geschehen bieten können.

Im Idealfall sollte es möglichst viele Szenarios geben, um Zweideutigkeiten zu beseitigen. Diese Szenarios dienen als ausführbare Spezifikation und bieten genug Informationen, um anfängliche Arbeiten durchzuführen. Es sollte beachtet werden, dass diese Szenarios nicht festgelegt sind. Bei fortschreitender Arbeit und zunehmenden Kenntnissen müssen Sie sich mit Fragen zu vorhandenen Szenarios möglicherweise wieder an den Kunden wenden oder aufgrund gewonnener Erkenntnisse zusätzliche Szenarios erstellen.

Beim Schreiben der Szenarios sollten einige Dinge beachtet werden. Ähnlich wie Anforderungen sollten sich Szenarios auf ein Beispiel konzentrieren. Der Hauptgrund dafür ist die Lesbarkeit. Wenn das Szenario zu umfassend ist, geht die Kernaussage verloren.

Implementieren von Akzeptanztests

Wenn die Vorgaben und die Szenarios in einem klar verständlichen Format vorliegen, besteht die nächste Phase in ihrer Automatisierung. Die Szenarios können dann während der Entwicklung ausgeführt werden, um den Fortschritt zu verfolgen und Regressionsfehler zu finden. Obwohl hier auf RSpec Bezug genommen wird, kann der grundlegende Prozess auf jedes BDD-Framework übertragen werden. Einzelheiten zum Installieren von IronRuby und RSpec sind in meinem bereits erwähnten Artikel enthalten.

Wenn Sie das vorstehende Beispiel beim Schreiben Ihrer Anforderungen verwenden, werden Sie das Ausführungsprogramm für Szenarios in RSpec ganz natürlich einsetzen können. Die Vorgaben und die Szenarios werden einfach im folgenden Format in eine einfache, leere Datei kopiert, die pricing_scenarios_for_product_x heißt:

Story: Pricing for New Product X
  As a sales administrator, I want to be able to view
  prices for product x so that I can provide customers
  with an accurate cost for their requirements. 
Scenario: Single User License for Product X without support
  Given Product X
  When user requests a 1 user license
  And this does not include support
  Then the price should be $250

Dies bildet nun die Grundlage für die Akzeptanzkriterien und wird beim Überprüfen der Anwendung verwendet. Damit die Vorgaben und Szenarios aber als ausführbare Spezifikation dienen können, ist zur Ausführung Ruby-Code erforderlich. IronRuby ist eine einfache Umgebung für das Schreiben und Ausführen von Code. Erstellen Sie einfach eine Datei mit einer .rb-Erweiterung, und Sie können sofort mit dem Schreiben von RSpec-Tests anfangen.

Der erste Schritt besteht darin, auf das RSpec-Framework zu verweisen. Dies geschieht mithilfe von require-Direktiven. Durch Erfassen der folgenden zwei Zeilen können Sie das Ausführungsprogramm für die RSpec-Vorgaben verwenden:

require 'rubygems'
require 'spec/story'

Als Nächstes können Schritte definiert werden. Ein Schritt ist eine Zeile innerhalb des Szenarios, wobei das GWT-Format verwendet wird. Bei RSpec wird ein Schritt einer Methode im Code zugeordnet. Jeder Schritt sollte nur mit jeweils einer Aufgabe verbunden sein. Der Given-Schritt beispielsweise wird zum Einrichten von Objekten verwendet, während im Schritt „Then“ im Allgemeinen die Assertion und Überprüfung stattfindet.

Bei RSpec müssen alle Schritte in einem Block eingeschlossen werden, der „steps_for“ heißt. Innerhalb der Klammern befindet sich ein Bezeichner für diese Schritte:

steps_for(:product_x) do
  #Steps go here
end

Jeder Schritt in den Vorgaben bezieht sich direkt auf eine Zeile im Szenario. Die Zeile „Given Product X“ im RSpec-Code entspricht hier der folgenden Schrittmethode:

Given("Product $productName at $price") do |productName, price|
   pending "Need to complete implementation for accessing C# object"
 end

RSpec führt eine Zeichenfolgenmanipulation durch, die es Ihnen ermöglicht, Platzhalter in Ihrem Schritt zu verwenden, wobei der Platzhalterwert als eine Variable des Schritts festgelegt wird. In diesem Fall werden „ProductName“ und „Price“ in der Variablen gespeichert, sodass Sie denselben Schritt für mehrere verschiedene Produkte und Grundpreise wiederverwenden können.

Verwenden Sie bei den Schritten „When“ und „Then“ denselben Ansatz:

  When("user requests a $amount user license") do |amount|
    pending "Need to complete implementation for accessing C# object"
  end
  When("this does not include support") do
    pending "Need to complete implementation for accessing C# object"
  end
  Then("the price should be $price") do |price|
    pending "Need to complete implementation for accessing C# object"
  End

Für den zweiten Schritt benötigen Sie keinen Platzhalter, da es sich immer um dieselbe Aktion handelt. Der Block hat daher keinen Parameter. Wenn Sie die Tests ausführen, ruft RSpec die richtigen Methoden in der richtigen Reihenfolge basierend auf dem Szenario auf und ersetzt die Werte laut Definition.

Schließlich müssen Sie den Pfad zu der Datei mit den Vorgaben bereitstellen, die Sie zuerst erstellt haben. Dies ist ein weiterer Block mit der Bezeichnung „with_steps_for“, der den beim Definieren der Schritte verwendeten Bezeichner bereitstellt. Der Text ruft die Run-Methode mit dem Pfad und dem Namen der Datei auf, in der die Szenarios gespeichert werden:

with_steps_for(:product_x) do
  run File.dirname(__FILE__) + "/pricing_scenarios_for_product_x"
end

Zum Ausführen der Tests führen Sie das IronRuby-Befehlszeilentool (ir) aus, wobei die Ruby-Datei als Parameter übergeben wird:

>ir pricing_scenarios_for_product_x_story.rb

Beim Schreiben der Schritte werden Sie feststellen, dass hier die pending-Methode aufgerufen wurde. Damit wird angezeigt, dass noch Arbeit zum Abschließen der Funktion erforderlich ist. Wenn Sie die Tests ausführen, werden daher alle ausstehenden Aufgaben in der Ausgabe angegeben (siehe Abbildung 1). Dies ist hervorragend für die Lesbarkeit und das Verständnis dessen, was geschieht. Wirklich unerwünscht ist nämlich, dass der Schritt übergeben wird, weil keine Implementierung vorhanden ist.

Abbildung 1 Anzeige der pending-Methoden

Running 1 scenarios
Story: Pricing for New Product X
 As a sales administrator, I want to be able to view prices for product x, 
 so that I can provide customers with an accurate cost for their requirements.
 Scenario: Single User License for Product X without support
  Given Product X at 250 (PENDING)
  When user orders a 1 user license (PENDING)
  And this does not include support (PENDING)
  Then the price should be 250 (PENDING)
1 scenarios: 0 succeeded, 0 failed, 1 pending
Pending Steps:
1. Pricing for New Product X (Single User License for Product X without support): Product $productName at $price
2. Pricing for New Product X (Single User License for Product X without support): user orders a $amount user license
3. Pricing for New Product X (Single User License for Product X without support): this does not include support
4. Pricing for New Product X (Single User License for Product X without support): the price should be $price

Das Ausführungsprogramm des RSpec-Szenarios bei der Interaktion mit C#-Objekten

Die Vorgaben, Szenarios und Schritte sind nun vorhanden. Sie haben jedoch noch keinen Code implementiert, der mit dem System interagiert. Im vorhergehenden Artikel ging es um die Verwendung des RSpec-Spezifikationsframeworks zum Bereitstellen von Beispielen dafür, wie die erstellten C#-Objekte arbeiten und ihre Implementierung als isolierte Einheit überprüft wird. In diesem Artikel geht es darum, wie Sie das Ausführungsprogramm für die RSpec-Vorgaben für Akzeptanztests verwenden können, wobei das Überprüfen des vollständigen Anwendungsstapels anstelle isolierter Blöcke im Mittelpunkt steht.

Die erste Aufgabe besteht darin, auf die C#-Assembly zu verweisen. IronRuby befolgt die Ruby-Sprachkonstrukte und verweist daher auf C#-Bibliotheken genauso wie auf Ruby-Bibliotheken:

require File.dirname(__FILE__) + 
  '/CSharpAssembly/CSharpAssembly/bin/Debug/CSharpAssembly.dll'

Jetzt können Sie mit dem Schreiben von Text für die Szenarios beginnen, die Sie im vorhergehenden Abschnitt definiert haben. Um die Szenarios zu übergeben, müssen Sie die Funktion zum Berechnen des Gesamtpreises einer Bestellung implementieren. Im Given-Block initialisieren Sie die für das Szenario erforderlichen Objekte. Für diese Szenarios ist das einzige Objekt, das an dieser Stelle initialisiert werden muss, das Product-Objekt. Der Konstruktor für das Objekt erfordert den Produktnamen und den Preis. Beide werden aus dem Methodenparameter abgerufen, der wiederum aus dem Szenario selbst abgerufen wird:

  Given("Product $productName at $price") do |productName, price|
    @product = CSharpNamespace::Product.new(productName, price.to_i)
  end

Wenn die anfänglichen Objekte vorhanden sind, müssen Sie den Status der Variablen für die Objekte festlegen, die Gegenstand der Tests sein sollen. Dies geschieht im When-Block. In diesem Szenario erklären Sie, dass ein Benutzer eine bestimmte Anzahl Lizenzen bestellt hat. Der Schritt muss dies widerspiegeln und der Objektzustand dementsprechend festgelegt werden:

  When("user orders a $amount user license") do |amount|
    @order = CSharpNamespace::Order.new(@product)
    @order.NumberOfLicenses = amount.to_i
  end

Schließlich kommen Sie an der Stelle an, an der tatsächlich überprüft wird, ob die vorstehende Aktion richtig funktioniert. Innerhalb des Then-Blocks definieren Sie Ihre Erwartungen und Assertionen.

Hier wird bei der erstellten Bestellung überprüft, ob die Zwischensumme dem Preis entspricht, der in Ihrem Szenario definiert wurde. „Should“ ist eine Erweiterungsmethode, die dynamisch von RSpec für alle Objekte erstellt wird, sodass Sie die Wahrheit der Aussage überprüfen können. Wenn sie nicht wahr ist, wird eine Ausnahme ausgelöst:

  Then("the price should be $price") do |price|
    @order.Subtotal.should == price.to_i
  end

Jetzt können Sie die Vorgaben mithilfe des folgenden Befehls ausführen:

>ir pricing_scenarios_for_product_x_story.rb

Beim Ausführen der einzelnen Szenarios, gibt RSpec die Anforderungen und Szenarios an die Konsole aus. Wenn einer der Schritte fehlschlägt, wird das betreffende Problem hervorgehoben, und die Summe wird am Ende angezeigt:

Running 1 scenarios
Story: Pricing for New Product X
  As a sales administrator, I want to be able to view prices for product x, 
  so that I can provide customers with an accurate cost for their requirements.

  Scenario: Single User License for Product X without support

    Given Product X at 250
    When user orders a 1 user license
    And this does not include support
    Then the price should be 250 (FAILED)

1 scenarios: 0 succeeded, 1 failed, 0 pending

Wenn alles richtig funktioniert, wird Folgendes in der Befehlszeile angezeigt:

Running 1 scenarios
Story: Pricing for New Product X
 As a sales administrator, I want to be able to view prices for product x, 
 so that I can provide customers with an accurate cost for their requirements.
 Scenario: Single User License for Product X without support
  Given Product X at 250
  When user orders a 1 user license
  And this does not include support
  Then the price should be 250
1 scenarios: 1 succeeded, 0 failed, 0 pending

Sie können nun zusätzliche, komplexere Szenarios erstellen, die mehr Geschäftslogik enthalten. Sie könnten beispielsweise einen Preisrabatt aufnehmen, sodass das Szenario folgendermaßen aussieht:

Scenario: Single User License for Product X with 20% discount 
and includes 2 years unlimited premium support.
   Given Product X
   When user requests a 1 user license
   And including 2 years support
   And support length is unlimited
   And support type is premium
   And with 20% discount
   Then the price should be $800

Wie bereits erwähnt, wird in diesen Szenarios Wirtschaftsterminologie verwendet, sodass sie nicht nur für den Kunden, sondern für alle Mitarbeiter im Unternehmen lesbar sind.

Akzeptanztests der Benutzeroberfläche

In den oben genannten Beispielen standen bei den Akzeptanztests die Geschäftslogik und die Domänenobjekte im Mittelpunkt, um zu testen, ob die Logik erfolgreich funktioniert. Doch wie steht es mit der Interaktion des Benutzers mit der Anwendung? Mithilfe dieser Akzeptanztests sollte überprüft werden können, ob die Logik aus der Sicht des Benutzers korrekt ist, und die Sicht des Benutzers ist die Benutzeroberfläche.

Persönlich bin ich überzeugt davon, dass sich Akzeptanztests auf die Anwendungslogik und die wichtigen Abschnitte des Codes konzentrieren sollten, in denen Entscheidungen über Aktionen getroffen werden. Wenn Ihre Anwendung über gute Entkopplung und gute Trennung der Logik vom Benutzeroberflächencode verfügt, dann sollten sich die Tests einfacher implementieren lassen. Wenn Sie auf dieser Ebene testen, wirken sich Änderungen an der Benutzeroberfläche nicht auf die Tests aus.

Obwohl sich die Tests ausschließlich auf die Logik konzentrieren sollten, bedeutet dies nicht, dass keine Akzeptanztests für die Benutzeroberfläche ausgeführt werden sollten. Ich setze gerne einige Feuerproben ein, die auf den hauptsächlichen „geglückten Pfad“ der Benutzeroberfläche abzielen. Sie konzentrieren sich auf die Teile der Anwendung, die von Benutzern am wahrscheinlichsten verwendet werden. Ziel dabei ist, mit der geringsten Anzahl an Tests den höchsten Nutzen zu erzielen. Wenn Sie versuchen, alle möglichen Pfade und Verwendungen der Benutzeroberfläche abzudecken, und die Benutzeroberfläche dann geändert wird (beispielsweise Optionen, die in andere Dialoge verschoben werden), dann müssten Sie alle Tests ändern.

Wenn Sie beispielsweise die Benutzeroberfläche für eine E-Commerce-Website testen, besteht der geglückte Pfad darin, einen Artikel auszuwählen, ihn dem Warenkorb hinzuzufügen, zu bezahlen und sich die Kaufbestätigung anzeigen zu lassen. Wenn dieses Szenario fehlschlägt, möchten Sie dies so früh wie möglich wissen.

Bei bestimmten Anwendungen könnten Sie abhängig von der Komplexität und Lebensdauer eine höhere Anzahl von Akzeptanztests für die Benutzeroberfläche ausführen, um sicherzustellen, dass die UI-Ebene möglichst verlässlich ist. Doch das erfolgreiche Testen der Benutzeroberfläche ist ein komplexes Thema, das den Rahmen dieses Artikels sprengen würde. Ich empfehle Ihnen, meine Blogbeiträge zum „Project White“ zum Testen von WPF und WatiN zum Testen von Webanwendungen zu lesen. Außerdem hat James McCaffrey zum Thema Benutzeroberflächenautomatisierung mit Windows PowerShell in der Ausgabe des MSDN Magazins vom Dezember 2007 einen Artikel verfasst.

Ausblick

Sie sind jetzt in der Lage, IronRuby bei Ihren Akzeptanztests zu verwenden. Die hier vorgestellten Informationen müssten ausreichen, aber Sie sollten einige Dinge bedenken.

Ein mögliches Problem besteht darin, dass IronRuby noch nicht für die Verwendung in der Produktion geeignet ist. Die Software kann bereits verwendet werden, aber IronRuby und RSpec werden zurzeit noch weiterentwickelt und verfeinert. Dazu gehört die Fehlerbehebung, aber auch die Möglichkeit bedeutender Änderungen. Es gibt auch Probleme im Hinblick auf die Ausführungsgeschwindigkeit von RSpec. Eine Bewertung der Frage, ob die Probleme die Vorteile bei der Vereinfachung Ihrer Tests überwiegen, ist aber möglicherweise lohnenswert.

Ein weiteres Problem liegt vielleicht im Kontextwechsel. Im Allgemeinen wird es von Entwicklern bevorzugt, Tests und Produktionscode in derselben Sprache zu schreiben. Dem stimme ich im Prinzip zu. Für Komponententests, bei denen täglich eine große Anzahl von Wechseln durchgeführt wird, werden Sie IronRuby und RSpec möglicherweise nicht verwenden. Doch bei Akzeptanztests ist die Anzahl der erforderlichen Kontextwechsel viel geringer. Daher bin ich der Meinung, dass sich der Kontextwechsel rechtfertigen lässt, um die Lesbarkeit und die natürlichere Art und Weise beim Schreiben von Überprüfungsvorgängen und Szenarios zu nutzen, da sich dem Kunden und dem Entwicklungsteam dadurch enorme Vorteile bieten.

Letztendlich kann das Integrieren von Akzeptanztests in den Entwicklungsprozess einen äußerst positiven Schritt für eine Entwicklungsorganisation darstellen. Mithilfe von Verfahren wie Anforderungen und Szenarios zum Definieren von Funktionen mit kundenorientierten Begriffen, gekoppelt mit lesbaren, aber gleichzeitig automatisierten Akzeptanztests können Sie eine vertrauensvollere Partnerschaft mit Ihrem Kunden aufbauen und zunehmend stabilere und zuverlässige Software liefern.

Ben Hall ist C#-Entwickler und -Tester in Großbritannien. Seine Leidenschaft ist die Softwareentwicklung und das Schreiben von Code. Ben Hall ist bei Red Gate Software als Test Engineer tätig. Sein Aufgabenbereich umfasst die Untersuchung verschiedener Arten von Softwaretests, einschließlich manueller und automatischer Tests, um die besten Möglichkeiten für das Testen verschiedener Anwendungen zu erforschen. Ben Hall ist C#-MVP und führt einen Blog unter Blog.BenHall.me.uk.