Navigation and service panel


Content

Behavior-driven Development in .NET

By Dawid Dworak on 17. June 2016, No comments

Good communication between business and development is one of the biggest predictors of project success. It is proved by The Standish Group CHAOS report. It identifies user involvement (15.9%), executive management support (13.9%) and clearly stated requirements (13.0%) as the greatest factors of project success. Behavior-driven Development (BDD) is a software development process that significantly improves communication between business and IT and elevates TDD to the next level by filling a gap between user stories, their acceptance criteria and developed code.

In this article I'll present fundamentals of Behavior-driven Development (BDD) in the .NET world. To show the BDD in action I'll use Habitat - a Sitecore solution example built on a modular architecture. More information about how to set up Habitat you'll find on the Habitat Getting Started page.

Basics

Behavior-driven Development is an extension of Test-driven Development (TDD). It enhances TDD with gathering requirements and preparing specifications in a language that both business users and programmers can understand. Those specifications are later implemented by software developers in a form of unit or integration tests to prove that the specified piece of functionality works correctly.

BDD User Stories

User stories originated with Extreme Programming and got more popular with the development of Agile and Scrum. They are usually written by or for business users to describe a piece of software functionality. In BDD it is expected that user stories contain a title that describes an activity, a narrative that includes a role, a feature and a benefit and one or more scenarios written in a form of Givens, Events and Results.

As a matter of fact the most popular language used in BDD to write user stories is Gherkin. The typical file written in the Gherkin language consists of the title, feature and scenarios written in a form of Given x When y Then z. The purpose of givens is to put the system in a known state before the user starts interacting with the system. The purpose of When is to describe the key action and Then to observe and verify outcomes.

There is an example of a user story written in Gherkin language in context of Sitecore Habitat:

Title: Visitor Information Sidebar

Feature: As a visitor
         I want to see duration of my visit on pages in milliseconds
         In order to have very precise information about my visit

Scenario: Preview duration of a visit on More Info page
    Given David opened the Home page
    And he clicked More Info item on the main navigation
    And he read More Info page content for 5500 milliseconds
    And he scrolled up the page
    And he clicked the logo
    And he opened the visitor information sidebar
    And he clicked the Refresh button on the visitor information sidebar
    When he clicks the Engagement tab on the information sidebar
    Then his recent visit on the More Info page is present on the list
    And he can read the duration of his visit on More Info page in milliseconds

Tools and Patterns

There are a number of tools that support BDD in the .NET environment. SpecFlow lets us write user stories in the Gherkin language, integrates with Visual Studio very well and it's compatible with many testing frameworks like xUnit or NUnit. It's free, by the way. Another tool useful especially when executing tests that require cooperation with other systems or technologies (integration tests) is Selenium - a web browser automation tool. To assure high maintainability and reduce code duplication when writing integration tests, it's very helpful to get familiar with the Page Object design pattern.

Use Case

Enough theory - let's get the hands dirty. Imagine that our clients require more precise information about duration of their visits on pages than it is now. Habitat presents this information with one second precision at the moment.

Image

In preparation for using BDD for implenting this requirement SpecFlow and NUnit 3 Test Adapter need to be installed as Visual Studio extensions. Let's create a new solution and a test project for our user stories and tests. We'll create an integration test, because it's Sitecore xDB technology that monitors and collects user interactions. Let's install required nuget packages to the project:

Install-Package Selenium.WebDriver
Install-Package Selenium.Support
Install-Package NUnit
Install-Package NUnitTestAdapter
Install-Package SpecFlow
Install-Package SpecFlow.NUnit

Once the required nuget packages have been added we can create a new folder UserStories to the project and add a new item - SpecFlow Feature File for our Visitor Information Sidebar feature:

Image

Let's paste our user story without a title to a newly created file:

Feature: As a visitor
         I want to see duration of my visit on pages in milliseconds
         In order to have very precise information about my visit

Scenario: Preview duration of a visit on More Info page
    Given David opened the Home page
    And he clicked More Info item on the main navigation
    And he read More Info page content for 5500 milliseconds
    And he scrolled up the page
    And he clicked the logo
    And he opened the visitor information sidebar
    And he clicked the Refresh button on the visitor information sidebar
    When he clicks the Engagement tab on the information sidebar
    Then his recent visit on the More Info page is present on the list
    And he can read the duration of his visit on More Info page in milliseconds

SpecFlow generates a code-behind VisitorInformationSidebar.feature.cs file. In case it's missing, right click the feature file and select Run Custom Tool.

Right click on the free space within feature file pane and click Generate Step Definitons and Copy methods to clipboard.

Let's add a new folder StepDefinitons to the project and a new class VisitorInformationSitebarSteps. We can paste the methods and implement them using Selenium and Page Object pattern. Selenium and Page Object design pattern are out of scope of this article but you can read more about them in the links presented under section References and see the implementation on GitHub. Beneath there is an implementation of the third step of our user story.

So for: And he read More Info page content for 5500 milliseconds it is:

[Given(@"he read More Info page content for (.*) milliseconds")]
public void GivenHeReadMoreInfoPageContentForMilliseconds(int readingTime)
{
this._homePage.ReadContent(readingTime);
}

After all the steps are implemented and the test is executed it will fail because the requirement is not implemented in Habitat yet:

Image

We can fulfill the requirement by changing line 76 in _Visits.cshtml in Habitat to @pageView.Duration.TotalMilliseconds. Once we execute the test again, it will pass successfully:

Image

Source Code

The complete source code is available on GitHub: https://github.com/dawiddworak88/BddHabitat.

To run the solution without any code changes, make sure that Firefox 46.01 is installed on your machine and automatic updates are disabled for the time being. The Selenium 2.53.0 is compatible and works well with this version of Firefox. As already mentioned SpecFlow and NUnit 3 Test Runner should be installed as Visual Studio extensions.

The test will fail with a default Sitecore Habitat solution because it displays visit duration in minutes and seconds. Set up a modified Habitat solution to execute the test successfully.

References

BDD in Action by John Ferguson Smart

Page Object Design Pattern by Anton Anelov

Automated Business Readable Web Tests with Selenium and SpecFlow video tutorial by Jason Roberts

Categories  ASP.NET MVC  Best Practice Tags  BDD  TDD  .NET

No comments

Add your comment

Your email address will not be published. Required fields are marked *

*