Using AutoFixture To Generate Anonymous Test Data in Web UI Automation With BDDfy and Seleno

I’m currently working on an AutoFixture Pluralsight course and it got me thinking about using it to generate anonymous test data when writing automated UI tests.

The basic premise is that in addition to using AutoFixture to generate unit test data, it can also be used to populate UI elements where the specific data values are unimportant.

If you are unfamiliar with BDDfy and Seleno, they are part of the TestStack project.

BDDfy allows tests to be written and to produce business readable documentation. Seleno allows the automation of web browsers using Selenium and strongly-typed page object models.

Example Scenario

Imagine that we have an (ASP.NET MVC) web site that allows the addition of members of the royal family.

image

If we wanted to test different king/queen names (but didn’t care about the Regnal number) we could start off by defining some strongly typed (Seleno) page object models:

public class HomePage : Page<AddRoyaltyModel>
{
    public CreatedPage CreateRoyalty(AddRoyaltyModel royal)
    {
        Input.Model(royal);

        return Navigate.To<CreatedPage>(By.Id("Create"));
    }
}

public class CreatedPage : Page
{
}

 

(all the examples in this post are fairly quick-and-dirty to demonstrate the AutoFixture involvement)

 

Next we can write some example in BDDfy (using xUnit.net as the test framework):

public class AddRoyaltyTests
{
    private HomePage _home;
    private CreatedPage _confirmationPage;
    public string Name { get; set; }
    public string Number { get; set; }

    [Fact]
    public void ShouldAddRoyaltiesWithDifferentNames()
    {
        this.Given(x => GivenIAmStartingANewRoyalAddition())
            .And("And I have entered <name> as the royalty name")
            .And("And I have entered <number> as the regnal number")
            .When(x => WhenIChooseToAddTheNewRoyal())
            .Then(x => ThenIShouldSeeAConfirmationOfTheNewRoyalHavingBeenAdded())
            .WithExamples(new ExampleTable("name", "number")
                          {
                              {"Richard", "I"},
                              {"Henry", "I"},
                              {"Elizabeth", "I"}
                          })
            .BDDfy();            
    }



    private void GivenIAmStartingANewRoyalAddition()
    {
        _home = Host.Instance.NavigateToInitialPage<HomeController, HomePage>(x => x.Index());
    }        

    private void WhenIChooseToAddTheNewRoyal()
    {
        var royal = new AddRoyaltyModel
        {
            Name = this.Name,
            RegnalRomanNumeral = this.Number
        };

        _confirmationPage = _home.CreateRoyalty(royal);
    }

    private void ThenIShouldSeeAConfirmationOfTheNewRoyalHavingBeenAdded()
    {
        Assert.Equal("Created ok", _confirmationPage.Title);
    }
}

Notice in the preceding code that even though we don’t care about the Regnal number we are still supplying it in the examples. We could just set it manually to a hardcoded value, and in this simple example that might be ok, but if we had a form with many fields then this  will introduce extra work and may make the test less “refactor-safe”.

The following code shows the removal of the Regnal name/number:

public class AddRoyaltyTestsUsingAutoFixture
{
    private HomePage _home;
    private CreatedPage _confirmationPage;
    public string Name { get; set; }

    [Fact]
    public void ShouldAddRoyaltiesWithDifferentNames()
    {
        this.Given(x => GivenIAmStartingANewRoyalAddition())
            .And("And I have entered <name> as the royalty name")
            .When(x => WhenIChooseToAddTheNewRoyal())
            .Then(x => ThenIShouldSeeAConfirmationOfTheNewRoyalHavingBeenAdded())
            .WithExamples(new ExampleTable("name")
                          {
                              "Richard",
                              "Henry",
                              "Elizabeth"
                          })
            .BDDfy();            
    }

    private void GivenIAmStartingANewRoyalAddition()
    {
        _home = Host.Instance.NavigateToInitialPage<HomeController, HomePage>(x => x.Index());
    }        

    private void WhenIChooseToAddTheNewRoyal()
    {
        var fixture = new Fixture();

        // Use AutoFixture to create anonymous data for all properties except
        // name which is set to the BDDfy example value
        var royal = fixture.Build<AddRoyaltyModel>()
            .With(x => x.Name, this.Name)
            .Create();

        _confirmationPage = _home.CreateRoyalty(royal);
    }

    private void ThenIShouldSeeAConfirmationOfTheNewRoyalHavingBeenAdded()
    {
        Assert.Equal("Created ok", _confirmationPage.Title);
    }
}

In this version, AutoFixture’s Build method is being used to automatically generate test data for all the fields, except the royal name which is set to the name(s) specified in the BDDfy examples.

Running this test results in the following automation:

SelenoAutofixture

 

And produces the following HTML BDDfy report:

image

SHARE:

A Feature Based Approach to Organising Test Code in BDDfy and Other Testing Frameworks

We want our test code to be as high quality as possible, this means smaller amounts of code duplication, reasonably easy to find where things are in Visual Studio, etc.

One possible organization structure is to think in terms of the individual features in the application. The approach you take will probably depend on the complexity and size of the test suite, system under test, etc. Because BDDfy is "just code" we can use all the normal techniques of composition and inheritance that we'd use in our production code to get to the right level of code reuse and organization for the application we're testing.

Organisation by Feature

Organising by feature enables a reasonable amount of code reuse between test scenarios and it also helps to think user- or business-first rather than code/implementation first.

So for example, if we’re using BDDfy to test a banking application we might have the following features:

  • Login
  • Logout
  • Move Money
  • Pay Bills
  • View Transactions
  • etc

Each of these features contains a number of scenarios, for example Login would probably contain scenarios for successful login, bad password, locked out account, 2 factor login, etc.

In Visual Studio we could create folders in the test project to represent and organize these features as the following screenshot illustrates.

Visual Studio feature folders

 

So a (cut down) Login BDDfy story class could look like the following code:

namespace Tests.Login
{
    [TestFixture]
    [Story(AsA="As a Customer",
        IWant = "I want to login",
        SoThat = "So that I can manage my accounts and money")]
    public class CustomerLogin
    {
        [Test]
        public void LoginSuccess()
        {
            this.Given(x => GivenIAmOnTheLoginScreen())
                .And(x => x.AndIHaveEnteredMyUsername())
                .And(x => AndIHaveEnteredMyPassword())
                .When( x=> WhenIChooseLogin())
                .Then(x => ThenIShouldBeLoggedIn())
                .BDDfy<CustomerLogin>();
        }

        public void GivenIAmOnTheLoginScreen()
        {
        }

        public void AndIHaveEnteredMyUsername()
        {
        }

        public void AndIHaveEnteredMyPassword()
        {
        }

        public void WhenIChooseLogin()
        {
        }

        public void ThenIShouldBeLoggedIn()
        {
        }
    }
}

Now for arguments sake, say we have a Navigation story class that represents how the user should be able to move around the applications features.

We could reuse the individual given/when/then methods in CustomerLogin but we don’t want our navigations scenarios to be bloated, we want them to represent the essence of the scenario with the right level of detail.

So the first thing we could do is to create a “step aggregation” method in CustomerLogin as follows:

public void GivenIHaveLoggedIn()
{
    GivenIAmOnTheLoginScreen();
    AndIHaveEnteredMyUsername();
    AndIHaveEnteredMyPassword();
    WhenIChooseLogin();
}

This method simply re-uses the existing steps but aggregates them into a method we can call from the navigation tests:

using NUnit.Framework;
using TestStack.BDDfy;
using TestStack.BDDfy.Core;
using Tests.Login;
using TestStack.BDDfy.Scanners.StepScanners.Fluent;

namespace Tests
{
    [TestFixture]
    [Story(AsA="As a Customer",
        IWant = "I want to navigate around the site",
        SoThat = "So that I can get to the features I want to use")]
    public class Navigation
    {
        [Test]
        public void NavigateToMoveMoney()
        {
            var custLogin = new CustomerLogin();

            this.Given(x => custLogin.GivenIHaveLoggedIn())
                .When(x => WhenChooseGotoMoveMoney())
                .Then(x => ThenIShouldBeTakenToTheMainMoveMoneyScreen())
                .BDDfy<Navigation>();
        }

        private void ThenIShouldBeTakenToTheMainMoveMoneyScreen()
        {            
        }

        private void WhenChooseGotoMoveMoney()
        {            
        }
    }
}

So here were are making use of this aggregate method from the CustomerLogin feature class.

If we don’t need to represent the fact that the customer is logged-in in the report and all the tests in the class assume a logged-in user, we could use some (e.g. NUnit) test setup code that logs the user in but doesn’t get reported.

The HTML output of this looks as follows:

BDDfy HTML report

 

While in these examples we have a single story class for the feature (e.g. CustomerLogin) once we start adding scenarios (and steps) this single story class might become too bloated. If this is deemed a problem then we can break it out into sub features/stories or if it’s applicable we could use inheritance to hold common given/when/then steps. The individual story classes relating to the customer login feature would all inherit this base class. We probably however, do not want multiple levels of nested inheritance in our stories as this may make maintenance and discoverability harder.

To see more of what BDDfy can do check out my Building the Right Thing in .NET with TestStack Pluralsight course, head on over to the documentation, or check it out on GitHub

SHARE:

Testing ASP.Net MVC Controllers with FluentMVCTesting

FluentMVCTesting facilitates the writing of tests against MVC controllers in a fluent way.

FluentMVCTesting is available via NuGet: Install-Package TestStack.FluentMVCTesting

There’s a number of things that FluentMVCTesting can help to test such as:

  • A controller action returns the correct view
  • A controller action returns the correct HTTP status
  • A controller action returns an empty result
  • A controller action returns a view if there are model errors
  • A controller action returns a view with the correct model data
  • A controller action should redirect to a Url / Route / Action

It’s also not tied to a specific testing framework, so it can be used with NUnit, xUnit.net, MSTest, etc.

Examples

var sut = new ExampleController();

sut.WithCallTo(x => x.Show()).ShouldRenderView("Orders");

The preceding test code is testing the ExampleController. It is testing that when the Show() action is called then the Orders view is rendered.

The following code checks that an expected HTTP status is returned.

var sut = new ExampleController();

sut.WithCallTo(x => x.MakeAnError())
    .ShouldGiveHttpStatus(HttpStatusCode.InternalServerError);

 

To see more of what FluentMVCTesting can do check out my Building the Right Thing in .NET with TestStack Pluralsight course, check out the documentation, or check it out on GitHub.

SHARE:

Business-Readable, Living Documentation with BDDfy

BDDfy enables the creation of tests that, in addition to verifying that the system works correctly, also results in business-readable, living documentation.

Business-readable means that the tests are described in natural language (e.g. English) that the business can read, understand, and ensure that the correct features and functionality is being built.

Living documentation means that the report results directly from the passing or failing of the tests. It’s not a word document somewhere on a shared drive or SharePoint site that may or may not actually be in sync with what the system actually does.

The Report

Below is an example of what a typical BDDfy HTML report looks like (there is a “metro” inspired report coming in V4). There’s also the ability to output the test report in markdown.

BDDfy HTML report

Notice that it’s not code-centric output, but rather business-centric.

Here the two test scenarios are grouped into a story, but they don’t have to be.

The underlying test framework that is used to execute the test doesn’t matter – you could use NUnit, xUnit.net, MSTest, etc.

The Test Code

The tests that produce this report could be configured in BDDfy in a couple of ways. There is a reflective style that uses methods that following a specific naming convention. There is also the fluent style.

The test code to produce this report looks like the below (we are using NUnit in this example).

using NUnit.Framework;
using TestStack.BDDfy;
using TestStack.BDDfy.Core;
using TestStack.BDDfy.Scanners.StepScanners.Fluent;

namespace BDDfyDemo
{
    [TestFixture]
    [Story(AsA = "As a customer",
        IWant = "I want my order total to add up correctly",
        SoThat = "I'm not overcharged for my goods")]
    public class OrderTotalCalculatorTests
    {
        [Test]
        public void MultipleOrderedItemsTotals()
        {
            this.Given(x => GivenIHaveAddedItemsToMyCart())
                .When(x => WhenICheckout())
                .Then(x => ThenTheOrderTotalExcludingTaxShouldBeCorrect())
                .BDDfy<OrderTotalCalculatorTests>();
        }

        [Test]
        public void SalesTaxAdded()
        {
            this.Given(x => GivenIHaveAddedItemsToMyCart())
                .When(x => WhenICheckout())
                .Then(x => ThenTheSalesTaxShouldBeCorrect())
                .BDDfy<OrderTotalCalculatorTests>();
        }

        public void GivenIHaveAddedItemsToMyCart()
        {
            // test code
        }

        public void WhenICheckout()
        {
            // test code
        }

        public void ThenTheOrderTotalExcludingTaxShouldBeCorrect()
        {
            // test code
        }

        public void ThenTheSalesTaxShouldBeCorrect()
        {
            // test code
        }

    }
}

Here there are a couple of NUnit tests defined – the methods with the [Test] attribute applied to them.

Within these test methods the BDDfy fluent style is being used to define the different steps in the test scenarios.

The “given” phase sets up the initial context or state of the thing being tested. The “when” phase acts upon the system to produce some change. The “then” phase is typically where we have assert code, it’s in this phase that the resulting state of the system is checked.

Notice how the individual method names appear in the test report in a nice business-readable way.

 

There’s a lot more to BDDfy, such as data-parameterised tests and a whole heap of customisation and configuration options. To see more of what BDDfy can do check out my Building the Right Thing in .NET with TestStack Pluralsight course, head on over to the documentation, or check it out on GitHub.

SHARE:

Beyond the Compiler with ConventionTests

We often have conventions in our code. For example all DTOs/entity/etc. classes should be in a specific namespace, or the name of certain types of class should end with a given word. Another example, we may need to make sure that all classes (or those in a specific namespace) contain all-virtual members.

These kind of things are conventions that the team may agree to but the compiler won’t pick up as build errors or warnings. The code may still be completely valid C# even though it violates a convention.

ConventionTests is a brilliant idea (and it’s ideas like this that keep me loving programming) allows us to write tests to verify these conventions, conventions that the compiler cannot verify.

Installation

Simple installation via NuGet into your test project: PM> Install-Package TestStack.ConventionTests

Simple Usage

Using whatever testing framework you prefer (xUnit.net, NUnit, etc.) create a test method.

these kind of things are conventions that the team may agree to but the compiler won’t pick up

In this method, the first thing to do is to select all the types in the production code that we want to check against a convention.

We can do this with code such as:

var typesToCheck = Types.InAssemblyOf<SomeClass>();   

Here the Types.InAssemblyOf method is being used to find which assembly contains the class called SomeClass. Using this overload, all of the types in the assembly will be selected, however there are other overloads that allow the returning of types in a given namespace.

The next step is to create an instance of one of the out-of-the-box conventions.

var convention = new AllClassesHaveDefaultConstructor();

This convention checks that all the selected types have a default constructor defined.

Now we have the list of types we want to check, and a convention to check them against.

To actually perform the check, we use the Convention.Is method:

Convention.Is(convention, typesToCheck);

If any of the classes selected in typesToCheck don’t have a default constructor then an exception will be thrown (with some useful info in it) and the test will fail.

You can see some of the other out-of-the-box conventions on the GitHub site, you can also write your own custom conventions.

 

ConventionTests is one of the tools in the TestStack suite. To learn more about ConventionTests and the other TestStack tools, checkout out my Building the Right Thing in .NET with TestStack Plurasight course.

SHARE:

Building the Right Thing with TestStack

My newest Pluralsight course was just released today: Building the Right Thing in .NET with TestStack.

TestStack is a suite of tools to help the team build better software.

The super-friendly members of TestStack are:

  • Jake Ginnivan
  • Krzysztof Koźmic
  • Mehdi Khalili
  • Michael Whelan
  • Robert Moore

TestStack consists of the following tools:

  • BDDfy: turn tests into business readable, living documentation
  • Seleno: automated UI web testing with strongly-typed page object models
  • FluentMVCTesting: unit test ASP.NET MVC controllers using fluent syntax
  • White: automated UI testing for Win32 based rich client applications
  • ConventionTests: write tests to check coding conventions are being adhered to

To get started learning the TestStack tools check out the Pluralsight course, the documentation site, or learn how to contribute to the TestStack project.

SHARE: