我们正在尝试在我们的 specflow 测试中实现全局挂钩,但并不完全确定属性方法是如何工作的 [BeforeScenario]
。[AfterScenario]
就我所见,这些属性总是在一个类中定义,其中包含在一些场景中使用的特定步骤。
他们可以去某个地方,以便适用于所有场景吗?或者是否将方法归因于[BeforeScenario]
并[AfterScenario]
导致它们在所有场景中运行,而不管它们实际放置在哪里?
我们正在尝试在我们的 specflow 测试中实现全局挂钩,但并不完全确定属性方法是如何工作的 [BeforeScenario]
。[AfterScenario]
就我所见,这些属性总是在一个类中定义,其中包含在一些场景中使用的特定步骤。
他们可以去某个地方,以便适用于所有场景吗?或者是否将方法归因于[BeforeScenario]
并[AfterScenario]
导致它们在所有场景中运行,而不管它们实际放置在哪里?
嗯...据我所知,根据文档,这些钩子始终是全局的,即来自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
是在您的场景之前还是之后运行。
这里还有一个很好的例子来说明标记是如何工作的 ->使用 SpecFlow 进行功能范围的步骤定义?
是的,您可以创建全局 BeforeScenario 和 AfterScenario 方法,但在实践中我发现这是不可取的,因为通常相同的前后步骤并不适用于测试项目中的所有步骤。
相反,我为我的步骤定义创建了一个基类,它具有我想应用于所有场景的 BeforeScenario 和 AfterScenarios 方法,例如
public class BaseStepDefinitions
{
[BeforeScenario]
public void BeforeScenario()
{
// BeforeScenario code
}
[AfterScenario]
public void AfterScenario()
{
// AfterScenario code
}
}
请注意,我没有在此类上使用 Binding 属性。如果您确实包含它,那么 BeforeScenario 和 AfterScenario 步骤将是全局的。
然后我从这个基本步骤定义类派生我的步骤定义类,以便它们具有之前和之后的场景方法,例如
[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();
}
}
虽然这种方法不是全局的,但通过使所有 StepDefinition 都派生自 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]
为了控制“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
}
我认为使用标签是保持场景整洁的好方法,并为您提供额外的功能,让您控制每个场景应该做什么。