在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 

我想进行另一项测试,测试添加销售线

另一个测试完成销售的测试

另一项取消销售的测试

等等

所有这些测试都将从与简单测试相同的前四个步骤开始,这将打破DRY原则。 那么我怎么能这样做,以便第二次测试的第一步只运行第一次测试? 例如:

 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 

如果每个测试都以相同的前四行开始,后来我意识到我需要更改简单的创建销售测试,那么我还需要去寻找并修复重复这四行的其他地方。

编辑:请注意,这也应该能够跨function。 例如,上面的简单测试在销售function中定义。 但我也有一个学分function,这需要每次创建一个销售,以便能够归功于它:

 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 

如前所述,您可以使用背景(这可能是大多数情况下的最佳选择),但您也可以创建调用其他步骤的步骤。

 [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 

这具有以下优点:该复合步骤可以在场景中的任何地方使用,而不仅仅作为起点。 如果需要,可以在多个function中重复使用此步骤

使用背景:

 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. 

您无需运行实际步骤来创建销售订单。 只需实现一个步骤定义,为您做一个单行。

首先,虚构的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(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(); // Save to scenario context so subsequent steps can access it ScenarioContext.Current.Set(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()从方案上下文中检索该对象。

如果我正确理解了这个问题,您希望在不同的function文件中调用其他方案。

  1. 您可以通过创建一个调用场景中的步骤(基本上是嵌套的步骤,如上面接受的答案)来处理这个问题。
  2. 将创建的步骤添加到背景中

要么

  1. 创建一个函数,该函数将调用场景中的步骤。
  2. 将标记@create_sale_order添加到需要销售订单作为前提条件的方案中。
  3. 为标记@create_sale_order实现before方案挂钩,并调用在步骤1中创建的函数。