2015-03-17 12 views
10

TL; DR; Wie kann ich einen Specflow-Test erstellen, der einen anderen Test als ersten Schritt aufruft?Kann ich in Specflow einen Test als Schritt eines anderen ausführen?

Given I already have one specflow test 
And I want to run another test that goes deeper than the first test 
Then I create a second test that runs the first test as its first step 
And I add additional steps to test the deeper functionality 

Sorry, wenig specflow es Humor.

zB Ich habe einen Test, der bereits einen Verkauf erstellt:

Given I want to create a sales order 
And I open the sales order page 
And I click the add new order button 
Then a new sales order is created 

Und ich möchte einen weiteren Test haben, die eine Vertriebslinie

Und einen weiteren Test Tests hinzufügen, die den Verkauf Tests abgeschlossen

Und ein weiterer Test, der den Verkauf

Und .. so weiter

annulliert

Alle diese Tests würden mit den gleichen ersten vier Schritten wie der einfache Test beginnen, der das DRY-Prinzip durchbricht. Also wie kann ich es so machen, dass der erste Schritt des 2. Tests nur den ersten Test durchführt? zB so etwas wie:

Given I have run the create sales order test // right here it just runs the first test 
And I add a sales order line 
Then the order total is updated 

Wenn jeder Test mit den gleichen ersten vier Zeilen beginnt und später merke ich, dass ich brauche die einfache Erstellen Verkauf Test ändern, dann werde ich auch gehen müssen und finden und repariere überall sonst diese vier Zeilen.

BEARBEITEN: Beachten Sie, dass dies auch funktionsübergreifend möglich sein sollte. Beispiel: Der obige einfache Test wird in der Verkaufsfunktion definiert. Aber ich hätte auch Kredite verfügen, und das würde erfordern einen Verkauf jedes Mal um die Schaffung der Lage sein, es kreditieren:

Given I want to credit a sale 
And I run the create sales order test 
And I complete the the sale 
And I click the credit button 
Then the sale is credited 
+0

Ihren 'schaffen I habe den Kundenauftrag test' Schritt erstellen laufen, die die drei vorherige' Given' ausführt Schritte Methoden nicht funktioniert? Oder willst du einen anderen Weg? Ich bezweifle, dass Sie den Assert-Teil in Ihren folgenden Tests wiederholen möchten. –

+0

Es macht mir nichts aus, dass es die Behauptungen wiederholen muss, die im ersten Test existieren werden. Ich möchte es ausführen können, ohne die gleichen 4 Schritte in viele verschiedene Tests schreiben zu müssen. –

+0

ja, aber warum erstellst du nicht den neuen 'Given' wie deinen 'something like' Teil, der die drei vorherigen' Given' manuell aufruft? Passt auch zu dem Szenario in Ihrer Bearbeitung, da Sie Ihren 'Ich habe den Schritt zum Erstellen eines Kundenauftrags-Tests ausführen können, wo Sie möchten, wiederverwenden können. Du warst zu 99% in deiner Frage. –

Antwort

12

Wie bereits erwähnt können Sie Verwenden Sie dafür einen Hintergrund (und das ist wahrscheinlich die beste Option in den meisten Situationen), aber Sie können auch einen Schritt erstellen, der die anderen Schritte aufruft.

[Binding] 
public class MySteps: Steps //Inheriting this base class is vital or the methods used below won't be available 
{ 
    [Given("I have created an order")] 
    public void CreateOrder() 
    { 
     Given("I want to create a sales order"); 
     Given("I open the sales order page"); 
     Given("I click the add new order button"); 
     Then("a new sales order is created"); 
    } 
} 

die Sie dann in Ihrem Szenario verwenden:

Scenario: I add another sale 
    Given I have created an order 
    When I add a sales order line 
    Then the order total is updated 

Dies hat den Vorteil, dass dieser Verbund Schritt überall in dem Szenario verwendet werden kann, und zwar nicht nur als Ausgangspunkt. Dieser Schritt kann dann für mehrere Funktionen erneut verwendet werden, wenn Sie

+0

Danke, das ist eigentlich ziemlich nah. Trotzdem möchte ich, dass der erste Test die Schritte tatsächlich in der Feature-Datei enthält, so dass es immer noch einige Duplikate geben wird (aber nur 2x statt n-mal). –

+0

Das ist in Ordnung. Sie können die Schritte verwenden, wenn Sie möchten, oder Sie können sie zusammen mit einem zusammengesetzten Schritt von Ihnen gruppieren. Es gibt das Beste aus beiden Werken –

+0

Ein paar Dinge zu beachten: 1. Sie müssen die richtige Gegebene verwenden (...) Wann (...) Dann (...) oder Und (...) 2. Wenn Sie nach dem Schritt ein "Und" verwenden, wird es "erben", je nachdem, was Sie zuletzt im Code verwendet haben und nicht mehr, was Sie zuletzt in der Feature-Datei verwendet haben. – Steve

5

Hintergrund verwenden:

Background: 
    Given I want to create a sales order 
    And I open the sales order page 
    And I click the add new order button 
    Then a new sales order is created 

Scenario: I add another sale 
    When I add a sales order line 
    Then the order total is updated 

Scenario: I add cancel a sale 
    When I cancel a sale 
    Then the order total is updated to 0 

etc. 
+0

Das sieht gut aus, würde aber nur innerhalb einer einzigen Funktion funktionieren, oder? Gibt es eine Möglichkeit, den Test für mehrere Funktionen erneut zu verwenden? Ich werde die Frage aktualisieren. –

+0

Sie können '[BeforeTestRun]' oder '[BeforeScenario]' verwenden, aber es gilt dann für jedes Szenario. Ich bin mir nicht sicher, ob du das willst. – RagtimeWilly

+0

Nein, es wäre nur für bestimmte verwandte Tests. Tests, die auf die gleiche Weise beginnen, aber dann weitermachen, um etwas weiter zu testen. –

2

benötigen. Sie müssen keine tatsächlichen Schritte zum Erstellen eines Kundenauftrags ausführen. Implementieren Sie einfach eine Schrittdefinition, die dies für Sie als Einzeiler erledigt.

Zuerst wird die fiktive SalesOrder Klasse:

public class SalesOrder 
{ 
    public double Amount { get; set; } 
    public string Description { get; set; } 
} 

Dann werden die Schritt Definitionen

using TechTalk.SpecFlow; 
using TechTalk.SpecFlow.Assist; 

[Binding] 
public class SalesOrderSteps 
{ 
    [Given("I have already created a Sales Order")] 
    public void GivenIHaveAlreadyCreatedASalesOrder() 
    { 
     var order = new SalesOrder() 
     { 
      // .. set default properties 
     }; 

     // Save to scenario context so subsequent steps can access it 
     ScenarioContext.Current.Set<SalesOrder>(order); 

     using (var db = new DatabaseContext()) 
     { 
      db.SalesOrders.Add(order); 
      db.SaveChanges(); 
     } 
    } 

    [Given("I have already created a Sales Order with the following attributes:")] 
    public void GivenIHaveAlreadyCreatedASalesOrderWithTheFollowingAttributes(Table table) 
    { 
     var order = table.CreateInstance<SalesOrder>(); 

     // Save to scenario context so subsequent steps can access it 
     ScenarioContext.Current.Set<SalesOrder>(order); 

     using (var db = new DatabaseContext()) 
     { 
      db.SalesOrders.Add(order); 
      db.SaveChanges(); 
     } 
    } 
} 

Jetzt können Sie Kundenaufträge als Einzeiler erstellen und gegebenenfalls einige benutzerdefinierte umfassen Attribute:

Scenario: Something 
    Given I have already created a Sales Order 

Scenario: Something else 
    Given I have already created a Sales Order with the following attributes: 
     | Field  | Value    | 
     | Amount  | 25.99    | 
     | Description | Just a test order | 

Wenn Sie auf diese SalesOrder zugreifen müssen Objekt in anderen Schrittdefinitionen ohne Abfrage in der Datenbank verwenden Sie ScenarioContext.Current.Get<SalesOrder>(), um dieses Objekt aus dem Szenariokontext abzurufen.

-1

Wenn ich die Frage richtig verstanden habe, möchten Sie andere Szenarien über verschiedene Feature-Dateien aufrufen.

  1. Sie können dies umgehen, indem ein Schritt zu schaffen, die die Schritte in das Szenario nennen würde (im Grunde Schritte wie die akzeptierte Antwort verschachtelt oben).
  2. In dem erstellten Schritt auf den Hintergrund

oder

  1. Erstellen Sie eine Funktion, die die Schritte im Szenario nennen würde.
  2. Fügen Sie den Szenarios, die einen Verkaufsauftrag als Vorbedingung benötigen, ein Tag @create_sale_order hinzu.
  3. Implementieren einen vor Szenario Haken für den Tag @create_sale_order und rufen Sie die Funktion in Schritt 1 erstellt