In Specflow can I run one test as a step of another?

扶醉桌前 提交于 2019-11-27 22:55:50

As noted already you can use a background for this (and that's probably the best option in most situations), but you can also create a step which calls the other steps.

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

which you can then use in your scenario:

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

This has the advantage that this composite step can be used anywhere in the scenario and not just as a starting point. This step can then be reused across multiple features if you need

Use a Background:

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.

You don't need to run actual steps to create a sales order. Just implement a step definition that does this for you as a one-liner.

First, the fictional SalesOrder class:

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

Then the step definitions

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

Now you can create Sales orders as a one-liner and optionally include some custom attributes:

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 |

If you need to access that SalesOrder object in other step definitions without querying for it in the database, use ScenarioContext.Current.Get<SalesOrder>() to retrieve that object from the scenario context.

If I understand the question correctly, you want to call other scenarios across different feature files.

  1. You can handle this by creating a step which would call the steps in the scenario (basically nested steps like the accepted answer above).
  2. Add the created step to the Background

or

  1. Create a function which would call the steps in the scenario.
  2. Add a tag @create_sale_order to the scenarios that needs a sale order as precondition.
  3. Implement a before scenario hook for the tag @create_sale_order and call the function created at step 1.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!