全局[BeforeScenario],[AfterScenario]在SpecFlow中执行

时间:2013-10-28 18:36:33

标签: specflow

我们正在尝试在我们的specflow测试中实现全局挂钩,并且不完全确定[BeforeScenario][AfterScenario]归因方法的工作原理。

我看到它完成的方式,这些属性总是在包含几个场景中使用的特定步骤的类中定义。

他们可以去某个地方,以便适用于所有场景吗?或者使用[BeforeScenario][AfterScenario]将方法归因于所有方案都会运行它们,无论它们实际放置在何处?

3 个答案:

答案 0 :(得分:11)

嗯......据我所知,根据文件记载,这些钩子总是全局的,即来自http://www.specflow.org/documentation/hooks/

  

     

钩子(事件绑定)可用于在特定事件上执行其他自动化逻辑,例如在执行场景之前。

     

挂钩是全局的,但可以限制为仅针对具有特定标记的功能或方案运行(参见下文)。同一事件的挂钩执行顺序未定义。

事实上,通过以下

生成一个小型演示项目
[Binding]
public class Unrelated
{
  [BeforeScenario]
  public void WillBeCalledIfGlobal()
  {
    Console.WriteLine("I'm global");
  }
}

[Binding]
public class JustTheTest
{
  [Given("nothing")]
  public void GivenNothing()
  {
     // Don't do anything
  }
}

然后是

的测试规范
As a developer
In order to understand how BeforeSpecifcation works
I want to know what the following does

Scenario: See if BeforeSpecifcation hook gets called
Given nothing

获取输出

I'm global
Given nothing
-> done: JustTheTest.GivenNothing() (0.0s)

所以它确实看起来好像文档是正确的,你应该使用标记来控制BeforeScenario \ AfterScenario是否在你的场景之前或之后运行。

还有一个关于标记如何在这里工作的好例子 - > Feature-scoped step definitions with SpecFlow?

答案 1 :(得分:7)

是的,您可以创建全局的BeforeScenario和AfterScenario方法,但实际上我发现这是不可取的,因为通常相同的前后步骤不适用于测试项目中的所有步骤

相反,我为我的步骤定义创建了一个基类,它将具有我想要应用于所有场景的BeforeScenario和AfterScenarios方法,例如。

public class BaseStepDefinitions
{
    [BeforeScenario]
    public void BeforeScenario()
    {
        // BeforeScenario code
    }

    [AfterScenario]
    public void AfterScenario()
    {
        // AfterScenario code
    }
}

请注意,我没有在此类上使用Binding属性。如果确实包含它,那么BeforeScenario和AfterScenario步骤将是全局的。

然后我从这个基本步骤定义类派生我的步骤定义类,以便它们具有Before和After场景方法,例如。

[Binding]
public class SpecFlowFeature1Steps : BaseStepDefinitions
{
    [Given(@"I have entered (.*) into the calculator")]
    public void GivenIHaveEnteredIntoTheCalculator(int inputValue)
    {
        ScenarioContext.Current.Pending();
    }

    [When(@"I press add")]
    public void WhenIPressAdd()
    {
        ScenarioContext.Current.Pending();
    }

    [Then(@"the result should be (.*) on the screen")]
    public void ThenTheResultShouldBeOnTheScreen(int expectedResult)
    {
        ScenarioContext.Current.Pending();
    }
}

虽然这种方法不是全局的,但通过使所有StepDefinitions派生自BaseStepDefinition类,我们可以获得相同的结果。

它还提供了更多控制,即如果您不想要BeforeScenario或AfterScenario绑定,则不要从基本步骤派生。


抱歉,这不起作用。一旦开始使用多个Binding类,最终会有多个调用。例如,如果我扩展上面的例子将绑定分成三个类,

[Binding]
public class SpecFlowFeature1Steps : BaseStepDefinitions
{
    [Given(@"I have entered (.*) into the calculator")]
    public void GivenIHaveEnteredIntoTheCalculator(int inputValue)
    {
        //ScenarioContext.Current.Pending();
    }
}

[Binding]
public class SpecFlowFeature2Steps : BaseStepDefinitions
{
    [When(@"I press add")]
    public void WhenIPressAdd()
    {
        //ScenarioContext.Current.Pending();
    }
}

[Binding]
public class SpecFlowFeature3Steps : BaseStepDefinitions
{
    [Then(@"the result should be (.*) on the screen")]
    public void ThenTheResultShouldBeOnTheScreen(int expectedResult)
    {
        //ScenarioContext.Current.Pending();
    }
}

public class BaseStepDefinitions
{
    [BeforeScenario]
    public void BeforeScenario()
    {
        // BeforeScenario code
        Console.WriteLine("Before. [Called from "+ this.GetType().Name+"]");
    }

    [AfterScenario]
    public void AfterScenario()
    {
        // AfterScenario code
        Console.WriteLine("After. [Called from " + this.GetType().Name + "]");
    }
}

然后当我运行它时,输出是

Before. [Called from SpecFlowFeature1Steps]
Before. [Called from SpecFlowFeature2Steps]
Before. [Called from SpecFlowFeature3Steps]
Given I have entered 50 into the calculator
-> done: SpecFlowFeature1Steps.GivenIHaveEnteredIntoTheCalculator(50) (0.0s)
And I have entered 70 into the calculator
-> done: SpecFlowFeature1Steps.GivenIHaveEnteredIntoTheCalculator(70) (0.0s)
When I press add
-> done: SpecFlowFeature2Steps.WhenIPressAdd() (0.0s)
Then the result should be 120 on the screen
-> done: SpecFlowFeature3Steps.ThenTheResultShouldBeOnTheScreen(120) (0.0s)
After. [Called from SpecFlowFeature1Steps]
After. [Called from SpecFlowFeature2Steps]
After. [Called from SpecFlowFeature3Steps]

答案 2 :(得分:4)

你可以做些什么来控制'BeforeScenario'和'AfterScenario'是使用标签。这使您可以控制在块之前和之后运行哪个场景。您的方案如下所示:

@GoogleChrome
Scenario: Clicking on a button
    Given the user is on some page
    When the user clicks a button
    Then something should happen

在这里,您可以让'BeforeScenario'为您在Google Chrome中启动浏览器会话,并为不同的浏览器实施类似的标签。你的'BeforeScenario'看起来像这样:

[Binding]
class Browser
{         
    [BeforeScenario("GoogleChrome")]
    public static void BeforeChromeScenario()
    {
        // Start Browser session and do stuff
    }

    [AfterScenario("GoogleChrome")]
    public static void AfterChromeScenario()
    {
        // Close the scenario properly
    } 

我认为使用标签是保持场景清洁的好方法,并为您提供额外的功能,让您控制每个场景应该做的事情。