Nunit框架与SpecFlow框架

本文关键字:框架 SpecFlow Nunit | 更新日期: 2023-09-27 18:24:14

我是NUnit的新手,对SpecFlow测试框架和NUnit测试框架感到困惑。

现有项目使用NUnit,如下所示。所有具有[Test]属性的方法都显示在NUnit GUI中(如果我从方法中删除[Test],则测试用例不会显示在NUnitGUI中):

[TestFixture]
public class AccountTest
{
  [Test]
  public void TransferFunds()
  {
    Account source = new Account();
    source.Deposit(200m);
  }
  [Test]
  public void TransferWithInsufficientFunds()
  {
  }
}

当我在同一个项目中使用SpecFlow进行编码时,SpecFlow框架是不同的,从[Given]、[When]、[Then]开始。每个SpecFlow场景都显示在Nunit GUI上。

我正在做的是用一个SpecFlow方法替换每个[Test]方法。例如:

[Test]
public void TransferFunds()
{
  Account source = new Account();
  source.Deposit(200m);
}

转向

[Then(@"I Transfer Funds")]
public void ITransferFunds()
{
  Account source = new Account();
  source.Deposit(200m);
}

这是我的问题:

  1. 看起来SpecFlow无法识别NUnit属性[Test]或[Setup]。要用SpecFlow做这个项目,我需要去掉所有的NUnit框架,用SpecFlow的框架代替吗?

  2. 我可以看到很多文章都在谈论"SpecFlow+NUnit",但它们要么是SpecFlow[Given],[When],[Then],要么是NUnit[Test],[TestCase]。如何使两者在一个项目中发挥作用,还是我对NUnit的理解完全错误?

我的问题可能很初级,谢谢你的回答!

Nunit框架与SpecFlow框架

我需要去掉所有的NUnit框架,用SpecFlow的框架代替吗?

我想你需要理解的第一件事是NUnitSpecFlow并不互斥。

SpecFlow作为一个整体有很多组件,但您现在需要了解的是,SpecFlow用于将用Gherkin编写的功能文件绑定到可以由测试运行程序运行的C#代码。C#代码有两部分,一部分是自动生成的,另一部分是您和您的团队编写的。


您编写的部分是那些具有属性GivenWhenThen的方法。它们是步骤定义(在此处阅读更多信息)。这些绑定需要遵循以下规则:

  • 必须在公共类中,用[Binding]属性标记
  • 必须是公共方法
  • 可以是静态方法,也可以是实例方法。如果它是一个实例方法,则包含>*的类将为每个场景实例化一次
  • 不能有out或ref参数
  • 不能有返回类型

自动生成的部分生成使用NUnitMSTestxUnit以及其他可用的单元测试提供程序编写的测试方法。正如你所看到的,使用相同的小黄瓜(这里和这里),你最终会得到不同的自动生成文件(这里和那里)


让我们来看看一个特定的场景(来源)

Scenario: One single spare
    Given a new bowling game
    When I roll the following series:   3,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
    Then my total score should be 29

如果单元测试提供程序是NUnit,则该步骤将生成以下测试方法(来源):

[NUnit.Framework.TestAttribute()]
[NUnit.Framework.DescriptionAttribute("One single spare")]
public virtual void OneSingleSpare()
{
    TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("One single spare", ((string[])(null)));
#line 7
    this.ScenarioSetup(scenarioInfo);
#line 8
    testRunner.Given("a new bowling game");
#line 9
    testRunner.When("I roll the following series:'t3,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1");
#line 10
    testRunner.Then("my total score should be 29");
#line hidden
    testRunner.CollectScenarioErrors();
}

如果单元测试提供程序是xUnit,则该步骤将生成以下测试方法(来源):

[Xunit.FactAttribute()]
[Xunit.TraitAttribute("FeatureTitle", "Score Calculation (alternative forms)")]
[Xunit.TraitAttribute("Description", "One single spare")]
public virtual void OneSingleSpare()
{
    TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("One single spare", ((string[])(null)));
#line 7
    this.ScenarioSetup(scenarioInfo);
#line 8
    testRunner.Given("a new bowling game");
#line 9
    testRunner.When("I roll the following series:'t3,7,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1");
#line 10
    testRunner.Then("my total score should be 29");
#line hidden
    testRunner.CollectScenarioErrors();
}

无论您使用的是什么单元测试提供程序,您的步骤定义方法看起来几乎都是一样的(正如您在这里看到的NUnitxUnit)。

您可以使用几种不同的步骤定义样式。此处对它们进行了描述

*唯一的区别可能是你的断言。

您需要了解的是,Specflow是一个单元测试生成框架。您使用小黄瓜语法编写特性文件,然后创建[Given], [When] and [Then]的绑定方法,然后specflow使用这些方法在您想要使用的任何类型的单元测试框架(NUnit、MSTest、XUnit等)中生成单元测试

一旦开始使用specflow,就不应该将其与"原始"NUnit属性混合使用,这只会导致混乱和难以调试的问题。对Specflow进行更改,并让它管理测试的生成