Just Behave! Part 1 of 2

The advantages of using Gherkin with Cucumber are well documented. This is the first of two posts that describe how to integrate NBehave (the .NET port of Cucumber) into your test project, specifically our Hello World! test project.

There are frameworks that support Gherkin for many languages, such as JBehave for java, Behave.js for javascript, or Behave for python. This post will describe how to implement NBehave, which is a C# solution.

Get the NuGet Package

The first step in implementing NBehave is to get its NuGet package. The name of the package is NBehave and it can be added to your project using the process described in the Hello World! post.

Create the NBehave steps

The biggest advantage NBehave offers is the ability to write your tests in a language that non-technical users may be able to understand.

The individual units that make up NBehave tests are called steps. To create these steps, we will add a class named Steps to our Hello World! project. Steps allow sections of code, written in C#, to be executed via strings, thus allowing tests to be written by non-technical stakeholders, such as product owners or QA engineers w/o programming experience.

We will need the NBehave library as well as the Selenium libraries to build the steps.

using NBehave.Narrator.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;

Directly before the Steps class declaration we need to add the ActionSteps tag. This tells the architecture that this class contains steps.

[ActionSteps]
public class Steps
{
}

The first step we’ll add to the Steps class is a browser step.

[Given("a Firefox browser")]
public void LaunchFirefox()
{
    FeatureContext context = FeatureContext.Current;
    IWebDriver webDriver = new OpenQA.Selenium.Firefox.FirefoxDriver();
    context.Add("browser", webDriver);
}

This method introduces a new concept, the context. NBehave consists of three contexts, a Feature context, a Scenario context, and a Step context. A context is essentially a dictionary whose scope is limited to the element it describes (a step context’s scope is a single step).

This provides two advantages.

  1. A place to store your variables.
  2. If something within your context implements the IDisposable interface, it’s automatically disposed of once the end of the context’s scope is reached.

Next, lets add a step for navigation.

[When("I visit $url")]
public void NavigateTo(string url)
{
    FeatureContext context = FeatureContext.Current;
    IWebDriver webDriver = context.Get<IWebDriver>("browser");
    webDriver.Navigate().GoToUrl(url);
}

The first thing we do in this step, is get the driver from the context. Then we can use the .Navigate().GoToUrl() syntax to navigate the browser to the URL described in the url variable. In NBehave ‘$” annotates that the text following the ‘$’ is a variable name.

Next, the SearchFor step.

[When("I search for \"$text\"")]
public void SearchFor(string text)
{
    FeatureContext context = FeatureContext.Current;
    IWebDriver webDriver = context.Get<IWebDriver>("browser");
    IWebElement textBox = webDriver.FindElement(By.Id("gbqfq"));
    textBox.SendKeys("Hello World!" + Keys.Enter);
}

Finally, the validation step.

[Then("the help button exists")]
public void HelpExists()
{
    FeatureContext context = FeatureContext.Current;
    IWebDriver webDriver = context.Get<IWebDriver>("browser");
    webDriver.WhenThisFails(dr =>
    {
        new WebDriverWait(dr, TimeSpan.FromSeconds(5)).Until<bool>(d =>
        {
            try
            {
                IWebElement helpButton = d.FindElement(By.XPath("//span[@id='fsl']/a"));
                Assert.AreEqual("Help", helpButton.Text);
                return true;
            }
            catch
            {
                return false;
            }
        });
    }).TakeScreenShot();
}

Ninja Level

  • Create a method that gets the WebDriver from the context to avoid redundant code.

Up Next

  • We will implement the NBehave test runner and replace the code in the Google class with a .feature file.

Leave a Reply

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