Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nunit Framework vs SpecFlow Framework

Tags:

c#

nunit

specflow

I am new to NUnit and confused with the SpecFlow Testing Framework and NUnit Testing Framework.

The existing project uses NUnit, something like this below. All the methods with [Test] attribute are displayed in the NUnit GUI (if I remove [Test] from the method, the test case is not display in NUnit GUI):

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

  [Test]
  public void TransferWithInsufficientFunds()
  {
  }
}

When I code with SpecFlow in the same project, the SpecFlow framework is different, starting with [Given], [When], [Then]. And each SpecFlow scenario is displayed at the Nunit GUI.

What I am doing is replacing each [Test] method with one SpecFlow method. E.g.:

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

Turns to

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

Here is my question:

  1. It looks like SpecFlow does not recognize the NUnit attributes [Test] or [Setup]. To do the project with SpecFlow, do I need to get rid of all NUnit framework and replace with SpecFlow's framework?

  2. I can see there is many articles talking about "SpecFlow + NUnit", but they are either with SpecFlow [Given], [When], [Then] or NUnit [Test], [TestCase]. How to make both work in one project or is my understanding of NUnit is totally wrong?

My question might be very entry level, thanks for the answers!

like image 692
Yan Avatar asked Nov 25 '15 13:11

Yan


2 Answers

Do I need to get rid of all NUnit framework and replace with SpecFlow's framework?

The first thing I think you need to understand is that NUnit and SpecFlow are not mutually exclusive.

SpecFlow as a whole has a lot of components, but what you need to understand now is that SpecFlow is used to bind feature files written in Gherkin to C# code that can be run by a test runner. That C# code has two parts, the auto-generated one, and the one written by you and your team.


The part written by you are those methods with the attributes Given, When, and Then. They are the step definitions (read more here). These bindings need to follow these rules:

  • Must be in a public class, marked with the [Binding] attribute.
  • Must be a public method.
  • Can be either a static or an instance method. If it is an instance method, the >* containing class will be instantiated once for every scenario.
  • Cannot have out or ref parameters.
  • Cannot have a return type.

The auto-generated part generates tests methods written using NUnit, MSTest, xUnit among other available unit test providers. As you can see, with the same Gherkin (here and here) you end up with different auto-generated files (here and here)


Let's take a look at a specific scenario (source)

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

If the Unit Test Provider is NUnit that step will generate the following test method (source):

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

If the Unit Test Provider is xUnit that step will generate the following test method (source):

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

No matter what Unit Test Provider you're using, your step definitions methods will look almost* the same (as you can see here for NUnit and here for xUnit).

There are a few different step definition styles you can use. They are described here

*The only difference might be your assertions.

like image 173
Maximo Dominguez Avatar answered Nov 15 '22 20:11

Maximo Dominguez


The thing you need to understand is that Specflow is a unit test generation framework. You write your feature files with your gherkin syntax and then create the binding methods attributed with the [Given], [When] and [Then] and then specflow uses these to generate the unit tests in whichever flavour of unit testing framework you want to use (NUnit, MSTest, XUnit etc etc)

Once you start using specflow you should not mix it with 'raw' NUnit attributes, this will just lead to confusion and difficult to debug issues. Make the change to Specflow and let it manage the generation of the tests

like image 22
Sam Holder Avatar answered Nov 15 '22 20:11

Sam Holder