2016-03-29 14 views
7

Ich versuche, eine neue Reihe von Tests zum Testen einer älteren Website zu erstellen, an der ich gerade arbeite. Die Website verwendet eine Datenbank am Back-End. Ich plane, SpecFlow und Selenium zu verwenden, aber ich bin ein wenig ratlos, was der beste Weg ist, um Daten zu bereinigen.So entfernen Sie ein SpecFlow-Szenario

Derzeit habe ich eine Datenbanksicherung mit einer Reihe von Beispieldaten, die ich vor jedem Testlauf wiederherstellen. Dies ist jedoch umständlich, daher möchte ich dies nur für kritische Testläufe vor einer Veröffentlichung tun und die kontinuierliche Integration läuft auf der gleichen Datenbank dazwischen arbeiten lassen.

Zur Zeit habe ich eine große Anzahl von Tests, die in etwa so gehen:

Secenario: Test Item Creation 
    Given I am logged in 
    When I create an item with a unique name 
    Then an item exists with the unique name 

Die als Schritt verwendet eine GUID der Name ist einzigartig und der dann Schritt Zugriff auf diese über ein Modul Variable hat, um sicherzustellen, überprüfe, ob es existiert.

Wie ich schon sagte, habe ich viele Tests ähnlich und ich führe sie mehrere Male auf der gleichen Datenbank, so dass das Testsystem voll von Elementen gestopft wird, die Suchvorgänge und dergleichen verlangsamt.

Meine Frage ist, was ist der beste Weg, damit umzugehen? Sollte ich einen weiteren Schritt im Test erstellen, die das Element erneut wie folgt gelöscht:

Secenario: Test Item Creation 
    Given I am logged in 
    When I create an item with a unique name 
    Then an item exists with the unique name 
    Then delete the item with the unique name 

Oder sollte mein Test-Framework irgendwie in der Lage sein, damit umzugehen? Wenn ja, was machen die Leute? Angesichts der globalen Natur des SpecFlow-Schritts würde ich mir vorstellen, dass die Teardown-Schritte in der richtigen Reihenfolge ausgeführt werden, wenn mehrere Elemente mit Eltern-Kind-Beziehungen problematisch werden könnten.

Antwort

6

Ein guter Test sollte keine Abhängigkeiten haben, daher ist es eine gute Idee, Testschritte zu erstellen und dann Testdaten "abzureißen".

Ein Ansatz Sie nehmen könnte, ist den eindeutigen Namen von erzeugt wurden, zu speichern:

When I create an item with a unique name 

im ScenarioContext Objekt z.B.

Dadurch können Sie diesen Wert für die Dauer des Szenarios beibehalten.

Sie könnten dann eine SpecFlow hook erstellen, die mit einem bestimmten Tag verknüpft ist, um diese Daten abzureißen, wenn das Szenario abgeschlossen ist, z. Das Szenario wäre (man beachte den Tag):

@deleteTestItem 
Secenario: Test Item Creation 
Given I am logged in 
When I create an item with a unique name 
Then an item has exists with the unique name 

Und den Code zu bereinigen sein würde:

[AfterScenario("deleteTestItem")] 
public void DeleteTestItem() 
{ 
var testItemName = ScenarioContext.Current["testItemName"]; 

// Use testItemName to clean-up your database 
} 

Dieser Code wird dann nur für Szenarien ausgeführt werden, die diesen Tag haben. Beachten Sie, dass Sie, wenn alle Ihre Tests ein Testobjekt erstellen, das Tag auslassen und einfach einen AfterScenario-Hook verwenden können.

Alternativ können Sie alle Testelementnamen im FeatureContext beibehalten und dann diese Elemente in einem AfterFeature-Hook löschen. Dies würde zu weniger Datenbankaufrufen führen (d. H. Sie würden die Datenbank nicht nach jedem Szenario zur Bereinigung aufrufen).

Ich bevorzuge den ScenarioContext-Ansatz, da ich denke, wenn ein Szenario Daten erstellt, dann sollte dieses Szenario für die Bereinigung verantwortlich sein.

+0

Ich würde ein explizites Kontextobjekt bevorzugen, das über den Konstruktor der Step-Klassen per Context-Injection übergeben und dort gefüllt wird, anstatt das 'ScenarioContext.Current' zu verwenden (welches nicht in parallelen Tests in specflow 2.0 verwendet werden kann) , aber das ist im Grunde der richtige Ansatz, den ich fühle. –

+0

@SamHolder ScenarioContext.Current ist ein explizites Kontextobjekt, d. H. Es ist exklusiv für diese Szenarioinstanz. Welche Probleme hat es mit parallelen Tests? –

+0

Ja, ich verstehe, was 'ScenarioContext.Current' ist, ich denke nur, dass es nicht der beste Weg ist, den Status zwischen den Schritten in Specflow zu teilen. Es gibt [im Grunde 3 Wege] (http://stackoverflow.com/a/2963667/97614), und die Verwendung einer expliziten Klasse für einen bestimmten Zustand, anstatt den generischen 'ScenarioContext' zu verwenden, ist IMHO viel vorzuziehen. In dem gegebenen Beispiel würde ich wahrscheinlich eine 'ItemContext' Klasse mit einer Eigenschaft' Name' erstellen, die ich auf Guid setzen würde. Dann können Sie diese Klasse in typsicherer Weise verwenden, anstatt sich auf den string (und casting) basierten Ansatz des 'ScenarioContext.Current' zu verlassen. –