Tag Archives: specflow

A Better Table.CreateInstance() for SpecFlow

SpecFlow remains my top choice for automated integration testing. I love writing cute little cukes and putting them together in different ways to create different test scenarios. And one of my favorite cuke tricks is using tables to define an object, which I wrote about some time ago.

The CreateInstance<T> extension method provides an easy way to convert that table data into objects for testing, but I really think there should be a better way to populate child properties of complex objects.

Consider this example:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

It would be nice if you could write a cuke like this:

Given a person
	| field          | value         |
	| firstName      | adam          |
	| lastName       | prescott      |
	| address.street | 123 number ln |
	| address.city   | anytown       |
	| address.state  | ny            |
	| address.zip    | 10000         |

And then convert it to a person like this:

[Given(@"a person")]
public void GivenAPerson(Table table)
{
    var person = table.CreateInstance<Person>();
    ScenarioContext.Current.Set(person);
}

But you can’t. Well, you can, but the address property won’t be populated. I didn’t like that, so I decided to grow my own. It works by identifying the child properties in the table and creating sub-tables, then using reflection to find and set the property on the result object. It works recursively, too, so you could even go n properties deep (i.e., address.state.abbreviation).

At its core, it’s just using CreateInstance<T> so you get all the niceties that go along with that. Note also that it only works with the 2-column, vertical tables with field and value columns. I called my extension method BuildInstance since CreateInstance was already taken. Here it is… Enjoy!

using System;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;

public static class TableExtensions
{
    public static T BuildInstance<T>(this Table table)
    {
        T result = table.CreateInstance<T>();

        // find sub-properties by looking for "."
        var propNames = table.Rows.OfType<TableRow>()
            .Where(x => x[0].Contains("."))
            .Select(x => Regex.Replace(x[0], @"^(.+?)\..+$", "$1"));

        foreach (var propName in propNames)
        {
            // look for matching property in result object
            var prop = typeof(T).GetProperty(
                propName,
                BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

            if (prop != null)
            {
                // create sub-table with relevant rows (field == propName.something)
                var subTable = new Table("field", "value");
                var re = new Regex(string.Format(@"^{0}\.([^\.]*)$", propName), RegexOptions.IgnoreCase);
                table.Rows.OfType<TableRow>().Where(x => re.IsMatch(x[0]))
                    .Select(x => new[] { re.Replace(x[0], "$1"), x[1] })
                    .ToList()
                    .ForEach(x => subTable.AddRow(x));

                // make recursive call to create child object
                var createInstance = typeof(TableExtensions)
                    .GetMethod(
                        "BuildInstance",
                        BindingFlags.Public | BindingFlags.Static,
                        null,
                        CallingConventions.Any,
                        new Type[] { typeof(Table) },
                        null);
                createInstance = createInstance.MakeGenericMethod(prop.PropertyType);
                object propValue = createInstance.Invoke(null, new object[] { subTable });

                // assign child object to result
                prop.SetValue(result, propValue);
            }
        }

        return result;
    }
}
Advertisements

Database SpecFlow Scenarios and TransactionScope

My team has been using SpecFlow to verify that our data access components are working correctly. In an effort to write repeatable tests that won’t pollute the database, we’ve decided to wrap each scenario in a transaction.

Creating and rolling back the transactions is very simple to do with SpecFlow’s BeforeScenario & AfterScenario hooks.

using System.Transactions;

[Binding]
public class TransactionHooks
{
    private TransactionScope _transactionScope;

    [BeforeScenario]
    public void BeforeScenario()
    {
        _transactionScope = new TransactionScope();
    }

    [AfterScenario]
    public void AfterScenario()
    {
        _transactionScope.Dispose();
    }
}

By including these hooks, you’re placing your test scenarios in the loving embrace of a transaction scope. The act of instantiating the TransactionScope will update the ambient transaction that will be used by all subsequent code unless you explicitly tell it to do otherwise.

If you’re testing code that uses TransactionScope itself, using TransactionScopeOption.Required will allow the code to use the ambient transaction if one exists. Note that this is the default value, so it’s what you’re using if you’re not explicitly specifying an option. However, the other TransactionScopeOption values will cause code to execute outside your test scenario’s ambient transaction by either creating a new/different transaction (RequiredNew) or executing outside the transaction (Suppress).

Performance Profiling for Unit Tests

When I first got my hands on Visual Studio 2012, I was trying out every feature I could, new and old alike. I love the new Test Explorer. Code coverage is SO much better than it was before. Code analysis for code clones is a terrific, too. The only thing I wasn’t happy about was performance analysis.

The reason I wasn’t happy with performance analysis is that I couldn’t use it on unit tests. Luckily, Microsoft fixed that with the release of Visual Studio 2012 Update 1. Now you can right-click a test and choose Profile Test to run performance analysis on a single unit test, and it is awesome!

ProfileTest_ContextMenu

When you choose to profile a test, the test runs as usual followed by the analysis. When analysis completes, you’re presented with a summary view that shows you CPU usage over time, the “hot path” call tree—a tree of the most active function calls where most of the work was performed—and a list of functions responsible for doing the most individual work.

ProfileTest_SummaryView

You can find out more and investigate resource spikes by selecting a time range on the graph and filtering. That’s all good and well, but what really blew me away was that you can click on the functions with the most individual work to drill into them. Drill into them? Yea—you’re taken to a view that shows you the selected function, its callers, and the methods it calls. There are percentages that show how much time was taken in each of the three areas (callers, current method, and callees), and you can click into any of the methods displayed to navigate up or down the call stack. The actual code for the current method is also displayed. The only thing that seemed sub-optimal is that I couldn’t edit the code directly; there’s a link to the actual file, though, so you’re only a click away from the editable code file.

ProfileTest_FunctionDetails

There are other, sortable views you can look at, too. You can view a call tree or breakdown by module, and you can get to the same function details view described above from each of those views. It’s a really useful, powerful experience.

Here’s where it gets really nuts, though: add SpecFlow to the mix. SpecFlow lets you write feature-based scenarios that are capable of serving as automated integration tests. The scenarios run like normal unit tests. You can right-click them in the Test Explorer to run performance analysis on them. This means that you can do targeted performance analysis on specific features of your application! To test this out, I sorted my unit tests by execution duration and analyzed the slowest. I was able to find a bottleneck with a caching algorithm used by nearly all of the other modules in the application. Execution time of the 350 unit tests in the project went from 50 seconds to 20. That’s a HUGE improvement from fixing one flaw found from running analysis on one function picked only because it was the most time-consuming in the slowest test.

Good tests are supposed to run quickly, and performance analysis is an invaluable tool to help you triage valuable-but-poor-performing tests. Also, since you’ve got automated tests, you can refactor and optimize the performance of your application with high confidence. If you haven’t used performance analysis before—more specifically, performance analysis for unit tests—give it a shot; I’d be blown away if you didn’t find incredible value.

Learning Cukes

Cucumber

I’ve written [several] [posts] [in] [the] [past] about my team’s adoption of SpecFlow and BDD, and I’m still loving it several months later. The large project that we started with has nearly 10,000 lines of code and 93% code coverage. We’ve gone through several large refactors, and each time we walk away with a high level of confidence that no functionality was lost or affected negatively. It’s been a really great experience.

One of the challenges of adoption was just learning the Cucumber step definition syntax, or rather, how to write cukes. For getting started, I recommend taking a look at this page for a good list of descriptions, scenarios, and examples. If you’re using SpecFlow, you may also want to check out their step definition documentation on GitHub.

Once you’ve got the basic syntax down, the hard part begins. My team hasn’t had much formal discussion about Cucumber best practices, and we’re still learning what works and what doesn’t. If you look around online, you can find a few good articles with helpful suggestions, though.

Here’s a great post that I recommend reading. This article offers advice on just about every aspect of creating and managing your cukes, from feature files to tags to running and refactoring.

I also found this post from EggsOnBread to be very helpful. All of the recommended practices are good. This was one of the first articles I read when I was getting started, and it’s served me well. I’ll be honest, though–many of the points didn’t stick during my initial read. It became much more valuable after spending several months working with Cucumber and then re-reading.

Compare Objects from Tables in SpecFlow

Earlier this week, I wrote about how to create and populate objects from tables created in your SpecFlow scenarios. If the only reason you’re populating an object is to do a comparison, there’s an easier way: the CompareToInstance<T> method.

Similar to the previously discussed method, CreateInstance<T>, an object will be created using the properties contained in a table of values. The object properties will be matched ignoring case and whitespace. CompareToInstance allows you to provide an instance of the same type and does a property-by-property comparison. If any of the property values are different, a TechTalk.SpecFlow.Assist.ComparisonException is thrown with a message containing all differences that were found.

Here’s an example!

Scenario: Update a person name
	Given I have an existing person
	And I change the name to the following
		| first | middle | last  |
		| Ftest | Mtest  | Ltest |
	When I save the person
	And I retrieve person
	Then the name was changed to the following
		| first | middle | last  |
		| Ftest | Mtest  | Ltest |
// don't forget!
// using TechTalk.SpecFlow.Assist;

[Given(@"I change the name to the following")]
public void GivenIChangeTheNameToTheFollowing(Table table)
{
    var p = ScenarioContext.Current.Get<Person>();
    p.Name = table.CreateInstance<NameType>();
}

[Then(@"the name was changed to the following")]
public void ThenTheNameWasChangedToTheFollowing(Table table)
{
    var p = ScenarioContext.Current.Get<Person>();
    table.CompareToInstance<NameType>(p.Name);
}

Calling Steps From Steps in SpecFlow

Steps are the building blocks of SpecFlow. Each Given/When/Then line in a SpecFlow scenario represents a step, and steps should be reused across features and scenarios to test your application from different angles. When you’re building a low-level scenario, you may want to use very specific steps. In a higher-level feature, you may want to perform the same tasks but in a less granular fashion. Wouldn’t it be nice if you could create a “super-step” that just calls the necessary sub-steps?

Well, guess what? You can, and it’s really easy to do. First, let’s build some fake code to work with. I created a simple PersonRepository that lets me add and save Person objects. Here are the classes and my initial SpecFlow test.

Person.cs

using System;

namespace samples.SpecFlowDemo
{
    public class Person
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public DateTime? DateOfBirth { get; set; }
    }
}

PersonRepository.cs

using System;
using System.Collections.Generic;

namespace samples.SpecFlowDemo
{
    public static class PersonRepository
    {
        private static readonly Dictionary<int, Person> Persons;

        static PersonRepository()
        {
            Persons = new Dictionary<int, Person>();
        }

        public static Person Get(int id)
        {
            if (!Persons.ContainsKey(id))
            {
                return null;
            }
            return Persons[id];
        }

        public static bool Save(Person person)
        {
            if (person == null)
            {
                return false;
            }
            if (!Persons.ContainsKey(person.Id))
            {
                Persons.Add(person.Id, person);
            }
            Persons[person.Id] = person;
            return true;
        }
    }
}

Person_Add.feature

Feature: Person_Add
	In order track person records
	As a records manager
	I need to add new persons

Scenario: Add a person
	Given I have a new person record with the following properties
		| id  | name   | date of birth |
		| 100 | Rodney | 2/20/1950     |
	When I save the person
	Then the person is saved successfully
	And I can retrieve the person by ID

Person_AddSteps.cs

using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;

namespace samples.SpecFlowDemo.SpecFlow
{
    [Binding]
    public class Person_AddSteps
    {
        [Given(@"I have a new person record with the following properties")]
        public void GivenIHaveANewPersonRecordWithTheFollowingProperties(Table table)
        {
            ScenarioContext.Current.Set<Person>(
                table.CreateInstance<Person>());
        }
        
        [When(@"I save the person")]
        public void WhenISaveThePerson()
        {
            var r = PersonRepository.Save(
                ScenarioContext.Current.Get<Person>());
            ScenarioContext.Current.Set<bool>(r, "SaveResult");
        }
        
        [Then(@"the person is saved successfully")]
        public void ThenThePersonIsSavedSuccessfully()
        {
            Assert.IsTrue(
                ScenarioContext.Current.Get<bool>("SaveResult"),
                "SaveResult");
        }
        
        [Then(@"I can retrieve the person by ID")]
        public void ThenICanRetrieveThePersonByID()
        {
            var expected = ScenarioContext.Current.Get<Person>();
            var actual = PersonRepository.Get(expected.Id);
            Assert.AreSame(expected, actual);
        }
    }
}

Now let’s say I want to test the PersonRepository’s ability to update records. In order to update a record, the record needs to exist. I could reuse the add feature’s “I have a person” step with a provided table of properties and its “I save the person” step, but it would be nice if I didn’t have to call both of those steps and provide data each time I needed to do something with an existing record.

I can avoid the repetition by calling those steps from within a new step that I’ll create called “I have an existing person record.” Here’s the code for my update feature.

Person_Update.feature

Feature: Person_Update
	In order track person records
	As a records manager
	I need to update existing persons

Scenario: Update a person
	Given I have an existing person record
	When I change the person name to "Rocko"
	And I save the person
	Then the person is saved successfully
	And I can retrieve the person by ID
	And the person name was saved as "Rocko"

Person_UpdateSteps.cs (Note the highlighted lines. The only “gotcha” that I ran into is that the steps class must inherit from SpecFlow’s Steps class in order to access the Given/When/Then functions.)

using Microsoft.VisualStudio.TestTools.UnitTesting;
using TechTalk.SpecFlow;

namespace samples.SpecFlowDemo.SpecFlow
{
    [Binding]
    public class Person_UpdateSteps : Steps
    {
        [Given(@"I have an existing person record")]
        public void GivenIHaveAnExistingPersonRecord()
        {
            var header = new[] { "Field", "Value" };
            var t = new Table(header);
            t.AddRow("id", "100");
            t.AddRow("name", "Fred");
            t.AddRow("date of birth", "12/15/1990");

            Given("I have a new person record with the following properties", t);
            When("I save the person");
        }
        
        [When(@"I change the person name to ""(.*)""")]
        public void WhenIChangeThePersonNameTo(string p0)
        {
            var p = ScenarioContext.Current.Get<Person>();
            p.Name = p0;
        }
                
        [Then(@"the person name was saved as ""(.*)""")]
        public void ThenThePersonNameWasSavedAs(string p0)
        {
            var p = ScenarioContext.Current.Get<Person>();
            Assert.AreEqual(p0, p.Name);
        }
    }
}

You can read more about calling steps from step definitions in the SpecFlow documentation.

You can also download the code for this example from GitHub.

Create and Populate Objects in SpecFlow Scenarios

SpecFlow is definitely my favorite new tool for 2012. If you haven’t checked it out yet, you should. If you’ve checked it out and still don’t get it, come talk to me. I love writing scenarios using business language to help guide my test-driven development. The integration-level tests are proving to be an awesome supplement to more traditional isolated unit tests.

Sometimes it’s hard to come up with a good scenario step because you need to specify several details. Don’t worry, though–SpecFlow’s got ya covered with its Assist Helpers. Let’s say I’m working on some code that has a configuration object that contains my application’s settings. When I’m writing a feature scenario, I might want to provide these settings. I can do just that by putting the details into a table in my scenario.

Configuration.cs

public class Configuration
{
    public string OutputDir { get; set; }
    public bool Enabled { get; set; }
}

Feature1.feature

Scenario: CreateInstance demo
    Given I have the following configuration
        | output dir | enabled |
        | c:\blah    | true    |
    When I do something
    Then what I expected to happen happened

In my step definition, I can import the TechTalk.SpecFlow.Assist namespace to use Assist Helpers like the CreateInstance&lt;T&gt; extension method. When called on a table, CreateInstance will match columns to properties to create and populate an object. Here’s how I use it with the above example:

[Given(@"I have the following configuration")]
public void GivenIHaveTheFollowingConfiguration(Table table)
{
    var config = table.CreateInstance();
}

When creating the object, case-sensitivity and whitespace are ignored, allowing you to create a human-friendly table of your object’s property values. You can also use a vertical table with properties listed as rows. This table will produce the same result as above:

Scenario: CreateInstance demo
    Given I have the following configuration
        | Field      | Value   |
        | output dir | c:\blah |
        | enabled    | true    |
    When I do something
    Then what I expected to happen happened

This technique allows you to create complex objects without having to write any code. You can create highly re-usable steps that rely on the scenario author to provide necessary details in the scenario itself. Simply awesome!

ScenarioContext in SpecFlow

I’ve been using SpecFlow pretty regularly for a few weeks now, and I must say, I’m a fan. I find that it’s a lot easier to do test-first development because I’m writing the test in human-readable, business language.

One of the ideas that I didn’t understand right away was how to re-use generated step definitions across features and scenarios. ScenarioContext and FeatureContext give you great options to handle this, though. Let’s check out an example using a modified version of the default scenario SpecFlow generates with a new feature file:

Scenario: Add two numbers
	Given I enter 50 into the calculator
	And I press plus
	And I enter 70 into the calculator
	When I press enter
	Then the result should be 120 be displayed

When I generate step definitions, I might end up with a class that looks like this:

namespace adamprescott.net.Calculator.SpecFlow
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using TechTalk.SpecFlow;

    [Binding]
    public class Calculator_AddSteps
    {
        Calculator calculator = new Calculator();

        [Given(@"I enter (.*) into the calculator")]
        public void GivenIEnterIntoTheCalculator(int p0)
        {
            calculator.Number(p0);
        }

        [Given(@"I press plus")]
        public void GivenIPressPlus()
        {
            calculator.Plus();
        }

        [When(@"I press enter")]
        public void WhenIPressEnter()
        {
            calculator.Enter();
        }

        [Then(@"the result should be (.*) be displayed")]
        public void ThenTheResultShouldBeBeDisplayed(int p0)
        {
            Assert.AreEqual(Convert.ToString(p0), calculator.Display);
        }
    }
}

Okay, not bad. A logical next feature might be subtraction. Some of the steps, like entering numbers and pressing enter, are shared. It would be nice if we could re-use those, but they’re configured to manipulate private variables in the Calculator_AddSteps class. So let’s do some refactoring! Instead of using a member-level variable, I can store my Calculator object in the ScenarioContext, making it accessible to other steps being executed in the same scenario.

// store to ScenarioContext like this:
ScenarioContext.Current.Set<Calculator>(new Calculator());
ScenarioContext.Current.Set<Calculator>(new Calculator(), "Calc");
ScenarioContext.Current["Calc"] = new Calculator();

// retrieve from ScenarioContext like this:
var c = ScenarioContext.Current.Get<Calculator>();
var c = ScenarioContext.Current.Get<Calculator>("Calc");
var c = ScenarioContext.Current["Calc"] as Calculator;

This is overkill for such a simple example, but I separated my shared steps into a new step definitions file. The final solution has three classes for the step definitions: Calculator_AddSteps, Calculator_SubtractSteps, and Calculator_SharedSteps.

Here’s the final solution, broken up by file:

Calculator_Add.feature

Feature: Calculator_Add
	In order to avoid silly mistakes
	As a math idiot
	I want to be told the sum of two numbers

Background:
	Given I have a calculator

Scenario: Add two numbers
	Given I enter 50 into the calculator
	And I press plus
	And I enter 70 into the calculator
	When I press enter
	Then the result should be 120 be displayed

Calculator_AddSteps.cs

namespace adamprescott.net.Calculator.SpecFlow
{
    using TechTalk.SpecFlow;

    [Binding]
    public class Calculator_AddSteps
    {
        [Given(@"I press plus")]
        public void GivenIPressPlus()
        {
            ScenarioContext.Current.Get<Calculator>().Plus();
        }
    }
}

Calculator_SharedSteps.cs

namespace adamprescott.net.Calculator.SpecFlow
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;
    using TechTalk.SpecFlow;

    [Binding]
    public class Calculator_SharedSteps
    {
        [Given(@"I have a calculator")]
        public void GivenIHaveACalculator()
        {
            ScenarioContext.Current.Set<Calculator>(new Calculator());
        }

        [Given(@"I enter (.*) into the calculator")]
        public void GivenIEnterIntoTheCalculator(int p0)
        {
            ScenarioContext.Current.Get<Calculator>().Number(p0);
        }

        [When(@"I press enter")]
        public void WhenIPressEnter()
        {
            ScenarioContext.Current.Get<Calculator>().Enter();
        }

        [Then(@"the result should be (.*) be displayed")]
        public void ThenTheResultShouldBeBeDisplayed(int p0)
        {
            Assert.AreEqual(Convert.ToString(p0), ScenarioContext.Current.Get<Calculator>().Display);
        }
    }
}

Calculator_Subtract.feature

Feature: Calculator_Subtract
	In order to avoid silly mistakes
	As a math idiot
	I want to be told the difference between two numbers

Background:
	Given I have a calculator

Scenario: Subtract two numbers
	Given I enter 70 into the calculator
	And I press minus
	And I enter 50 into the calculator
	When I press enter
	Then the result should be 20 be displayed

Calculator_SubtractSteps.cs

namespace adamprescott.net.Calculator.SpecFlow
{
    using TechTalk.SpecFlow;

    [Binding]
    public class Calculator_SubtractSteps
    {
        [Given(@"I press minus")]
        public void GivenIPressMinus()
        {
            ScenarioContext.Current.Get<Calculator>().Minus();
        }
    }
}

BDD in .NET with SpecFlow

Yesterday, I was invited to sit in on a demo/discussion about behavior-driven development (BDD) with SpecFlow. As a self-proclaimed unit test enthusiast, I was excited right away.

I’ve been doing my own, made-up version of BDD for a while. For example, I would have a function that calls several sub-methods. I’d mock the sub-methods and write tests to verify that the sub-methods were called. Then I’d move to the next “layer” by implementing the sub-methods in a similar fashion, repeating until I hit the bottom layer, where the actual work happens.

The problem with that approach is that all tested behaviors relate to the code and not business requirements or real-world scenarios. SpecFlow fixes that by using a Gherkin parser, allowing you to write test scenarios using business-readable, domain-specific language instead of code.

Here’s how you can get started with SpecFlow and Visual Studio. This tutorial is basically a modified version of the Project Setup Guide on the SpecFlow site. I ran into a couple issues with their tutorial, though, and their tutorial also doesn’t get much into implementing the application logic to fix unit tests once they’re generated.

Installing SpecFlow

SpecFlow is included in the Visual Studio Extensions Gallery, so installing it is a breeze.

  1. Open Visual Studio, and go to Tools > Extensions and Updates (Extension Manager in VS2010)
  2. Select the Online gallery
  3. Search for “SpecFlow”
  4. Install it!

Nice, now you’re ready to create your first test project.

Creating your first test project

SpecFlow tests are defined as “features” that have multiple scenarios. There is a small amount of project setup that needs to be done, but it’s not too bad and you can be up and running in just a few minutes.

  1. In Visual Studio, create a new Unit Test Project
  2. Install SpecFlow via NuGet
    • PM> Install-Package SpecFlow
    • I had to manually add the unit test provider to my app.config:
      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <configSections>
          <section name="specFlow" type="TechTalk.SpecFlow.Configuration.ConfigurationSectionHandler, TechTalk.SpecFlow" />
        </configSections>
        <specFlow>
          <unitTestProvider name="MsTest" />
        </specFlow>
      </configuration>
      
  3. Add a SpecFlow Feature to your project
  4. Generate Step Definitions by right-clicking in your newly created feature file

  5. Run your scenario by right-clicking in the feature file

    • Right-clicking in the feature and choosing Run SpecFlow Scenarios produced an error for me; I’ll be looking into this
    • I instead ran the unit tests as usual, and that worked fine
  6. Implement your code/step definitions until you have a passing test
    • I added my class-to-be-tested to the same file as my step definitions for brevity
      namespace adamprescott.net.SpecFlow.FirstProject
      {
          using Microsoft.VisualStudio.TestTools.UnitTesting;
          using System.Collections.Generic;
          using System.Linq;
          using TechTalk.SpecFlow;
      
          public class AddingMaching
          {
              private List<int> _numbers = new List<int>();
              private int _sum;
      
              public int Screen
              {
                  get { return _sum; }
              }
      
              public void EnterNumber(int num)
              {
                  _numbers.Add(num);
              }
              public void PressAdd()
              {
                  _sum = _numbers.Sum();
              }
          }
      
          [Binding]
          public class MyFirstFeatureSteps
          {
              private AddingMaching _addingMachine;
      
              public MyFirstFeatureSteps()
              {
                  _addingMachine = new AddingMaching();
              }
      
              [Given(@"I have entered (.*) into the calculator")]
              public void GivenIHaveEnteredIntoTheCalculator(int p0)
              {
                  _addingMachine.EnterNumber(p0);
              }
      
              [When(@"I press add")]
              public void WhenIPressAdd()
              {
                  _addingMachine.PressAdd();
              }
      
              [Then(@"the result should be (.*) on the screen")]
              public void ThenTheResultShouldBeOnTheScreen(int p0)
              {
                  Assert.AreEqual(p0, _addingMachine.Screen);
              }
          }
      }
      
    • The example shows a simple AddingMachine class with implemented steps to pass the default feature scenario
      Feature: MyFirstFeature
      	In order to avoid silly mistakes
      	As a math idiot
      	I want to be told the sum of two numbers
      
      @mytag
      Scenario: Add two numbers
      	Given I have entered 50 into the calculator
      	And I have entered 70 into the calculator
      	When I press add
      	Then the result should be 120 on the screen
      

That’s it! Now you should have a passing unit test that verifies the business-language requirement. You can add more scenarios to your feature file with different values and/or steps. Note that if you add more steps, you’ll probably need to re-generate step definitions. When you do this, only new step definitions will be generated. I recommend using the Copy methods to clipboard button in the Generate Step Definitions dialog to avoid overwriting the previously created and implemented step definitions.