web-dev-qa-db-ja.com

Specflowで、あるテストを別のステップとして実行できますか?

TL; DR;最初のステップとして別のテストを呼び出すspecflowテストを作成するにはどうすればよいですか?

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

申し訳ありませんが、スペックフローのユーモアが少しあります。

たとえば、すでに販売を作成するテストがあります。

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

そして、販売ラインの追加をテストする別のテストが必要です

そして、販売の完了をテストする別のテスト

そして、販売をキャンセルする別のテスト

等々

これらのテストはすべて、単純なテストと同じ最初の4つのステップで開始されます。これは、DRYの原則に違反します。では、2番目の最初のステップを実行するにはどうすればよいですか。 testは最初のテストを実行するだけですか?例:

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

すべてのテストが同じ最初の4行で始まり、後で単純な販売作成テストを変更する必要があることに気付いた場合は、それらの4行を繰り返す他のすべての場所を見つけて修正する必要もあります。

編集:これは機能間でも機能するはずであることに注意してください。たとえば、上記の簡単なテストは販売機能で定義されています。ただし、クレジット機能もあります。クレジット機能を使用するには、毎回セールを作成する必要があります。

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
15
JK.

すでに述べたように、これには背景を使用できます(そして、ほとんどの状況でおそらくこれが最良のオプションです)が、他のステップを呼び出すステップを作成することもできます。

[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");
    }
}

その後、シナリオで使用できます。

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

これには、この複合ステップを開始点としてだけでなく、シナリオのどこでも使用できるという利点があります。このステップは、必要に応じて複数の機能で再利用できます

16
Sam Holder

背景を使用する:

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.
6
RagtimeWilly

受注を作成するために実際のステップを実行する必要はありません。ワンライナーとしてこれを行うステップ定義を実装するだけです。

まず、架空のSalesOrderクラス:

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

次に、ステップの定義

_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();
        }
    }
}
_

これで、販売注文をワンライナーとして作成し、オプションでいくつかのカスタム属性を含めることができます。

_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 |
_

データベースでクエリを実行せずに、他のステップ定義でそのSalesOrderオブジェクトにアクセスする必要がある場合は、ScenarioContext.Current.Get<SalesOrder>()を使用してシナリオコンテキストからそのオブジェクトを取得します。

4
Greg Burghardt