Kash Farooq's software development blog

.NET Developer

BDD with SpecFlow and Coypu (Part 2)

Posted by Kash Farooq on August 23, 2011

In my last post I introduced BDD with SpecFlow. I created a  feature file and got to a point where I now needed to hook up my BDD tests with browser integration. To do this, I’m going to use Coypu and the Selenium headless browser. See my previous post for download links.

First, let’s configure Coypu to use the Selenium headless browser:

[Binding]
public class CoypuInitializer {
    [BeforeTestRun]
    public static void BeforeTestRun()
    {
        //I'm using the Dev Studio cassini server;
        Configuration.AppHost = "localhost";
        Configuration.Port = 64567;

        ConfigureForHeadlessBrowser();
    }

    private static void ConfigureForHeadlessBrowser()
    {
        Configuration.Driver = typeof(SeleniumHtmlUnitWebDriver);
    }

    [AfterScenario]
    public static void AfterScenario()
    {
        Coypu.Browser.EndSession();
    }
}

 

public class SeleniumHtmlUnitWebDriver : SeleniumWebDriver {
    public SeleniumHtmlUnitWebDriver() : base(new RemoteWebDriver(DesiredCapabilities.HtmlUnit())) {}
}

You will also need to add DLL references to Coypu.dll and WebDriver.dll (which is in the Coypu zip).

You can use this class to make other global configuration settings such as the Timeout, or the time Coypu waits between retries when looking for a HTML element. Full details can be found at the GitHub Coypu website, or the README.md file that comes with the Coypu binaries.

Now we are ready to implement the first feature step. As a reminder, the feature file is:

Scenario: Display Pi using Taylor series and Bucknall's BigNumber to many decimal places
	Given I visit the Pi.NET website
	And I have selected the 'Bucknall Big Number' algorithm
	And I have entered 500 decimal places
	When I press Go
	Then Pi should be displayed to the correct number of decimal places
	And Calculation statistics should be displayed

Let’s implement the “Given I visit the Pi.NET website” step:

[Given(@"I visit the Pi\.NET website")]
public void GivenIVisitThePiWebsite() {
    Browser.Session.Visit(string.Format("/"));
}

Using Coypu, I’m going to open the website specified in the CoypuInitializer class and visit the root of that website.

I now go to my MVC app and implement just enough to get that step passing.

Once I’ve done that, running the tests now gives:


Given I visit the Pi.NET website
-> done: PiNetSteps.GivenIVisitThePiWebsite() (15.4s)
And I have selected the 'Bucknall Big Number' algorithm
-> pending: PiNetSteps.GivenIHaveSelectedTheBucknallBigNumberAlgorithm("Bucknall Big Number")

i.e. – the first step has completed and the test has stopped at the next pending step. We’ve successfully hit the website.

I proceed like this, step by step, until I end up with the following steps file. I’ve added comments to explain the Coypu features I am using:

[Binding]
public class PiNetSteps:Steps {
    private string numberOfDecimalPlaces;

    [Given(@"I have selected the '(.+)' algorithm")]
    public void GivenIHaveSelectedAnAlgorithm(string algorithm) {
        //pass on this call to the generic radio button method (later in this class)
        Given(string.Format("I select the radio button '{0}'", algorithm));
    }

    [Given(@"I have entered (.+) decimal places")]
    public void GivenIHaveEnteredTheNumberOfRequiredDecimalPlaces(string numberOfDecimalPlaces) {
        this.numberOfDecimalPlaces = numberOfDecimalPlaces; //store for later use in an assert
        //populate a text box
        Browser.Session.FillIn("NumberOfDecimalPlaces").With(numberOfDecimalPlaces);
    }

    [When(@"I press Go")]
    public void WhenIPressGo() {
        //click a link. This fires an AJAX post to controller action
        //(I wanted to test JS capabilities of Selenium headless browser)
        Browser.Session.ClickLink("Calculate");
    }

    [Then(@"Pi should be displayed to the correct number of decimal places")]
    public void ThenPiShouldBeDisplayedToTheRequestedNumberOfDecimalPlaces() {
        //Check page HasContent I'm after - "Number of iterations" is displayed by AJAX call result
        if (Browser.Session.HasContent("Number of iterations:")) {
            //check Pi is calculated to correct number of places
            string piToNumberOfRequiredDecimalPlaces = Pi.Get(Convert.ToInt32(numberOfDecimalPlaces));
            Element piElement = Browser.Session.FindField("pi"); //find HTML element
            string calculatedPi = piElement.Text;
            Assert.That(piToNumberOfRequiredDecimalPlaces, Is.EqualTo(calculatedPi));
        }
        else {
            Assert.Fail("Could not find PI");
        }
    }

    [Then(@"Calculation statistics should be displayed")]
    public void ThenCalculationStatisticsShouldBeDisplayed() {
        //you can use actions/funcs with different retry timeouts
        Assert.IsTrue(Browser.Session.WithIndividualTimeout(TimeSpan.FromMilliseconds(1),
                       () => Browser.Session.HasContent("Number of iterations: ")),
                       "Number of Iterations taken not found");
        Assert.IsTrue(Browser.Session.WithIndividualTimeout(TimeSpan.FromMilliseconds(1),
                       () => Browser.Session.HasContent("Number of decimal places: " + numberOfDecimalPlaces)),
                       "Number of Decimal places calculated not found");
        Assert.IsTrue(Browser.Session.WithIndividualTimeout(TimeSpan.FromMilliseconds(1),
                       () => Browser.Session.HasContent("Elapsed Milliseconds: ")),
                       "Time taken not found");
    }

    [Given(@"I select the radio button '(.+)'")]
    public void SelectARadioButton(string radioButtonValue) {
        //select a radio button by value
        Browser.Session.Choose(radioButtonValue);
    }

    [Given(@"I visit the Pi.NET website")]
    public void GivenIVisitThePiPage() {
        //visit a web page at site specified in Coypu initialization.
        Browser.Session.Visit(string.Format("/"));
    }
}

I’ve used several SpecFlow and Coypu features in the class above. There are many more that you can read about at the GitHub Coypu website, or the README.md file that comes with the Coypu binaries. The documentation also shows how to use a real browser, rather than the Selenium headless one.

Advertisements

Sorry, the comment form is closed at this time.

 
%d bloggers like this: