Woah, Nellie.NET!

From my simple mind to… mine…

Behave#, Part 5

with 6 comments

It’s time, as the programmer (preferably with a pair programmer), to get into some code! This post will be yet another step by step walk-through, but I will do my best to describe the thought processes behind each step.

The first part of the Given statement in the first scenario is:

                     .Given(“a new Family File”)

How does this translate into code? What is a Family File?

From a domain driven perspective, the Family File is an important concept, encapsulating all the information needed for the customers of a child care center, including children and guardians. The concept does not currently exist in code, so we’ll add the Family File into the domain:

image

Complete the Given statement with a relevant delegate to satisfy that a new Family File exists in context:

                .Given(“a new Family File”,

                      delegate() { familyFile = new FamilyFile(); }

                )

The next part of the Given refers to a child that will eventually be added to the Family File:

                .And(“a child that will be added to the Family File”)

This is referring to a domain level “child concept”, which does not exist in code. We will capture that concept in the domain as a class, and then fulfill the Given.

                .And(“a child that will be added to the Family File”,

                    delegate() { child = new Child(); }

                )

This part of the Given refers to the child’s personal information:

                .And(“the child’s first name is”, “John”)

Create the delegate such that “John” is passed through the delegate as the firstName parameter, for assignment to the child object’s FirstName property. I’ll use ReSharper’s Create Property functionality to quickly add the code for the FirstName property and we end up with:

                .And(“the child’s first name is”, “John”,

                    delegate(string firstName) { child.FirstName = firstName; }

                )

So far the specification has resulted in this Child domain class:

    public class Child

    {

        private string firstName;

 

        public string FirstName

        {

            set { firstName = value; }

        }

    }

We continue through all parts of the Given statement, writing enough code to pass the statements and complete our list of pre-conditions.

The When statement is the behavior under test in the scenario. In this case, the action of adding a child to a Family File.

                .When(“I add the child information to the Family File”)

To satisfy this behavior, we will add a method to the FamilyFile domain object, AddChild():

                .When(“I add the child information to the Family File”,

                      delegate() { familyFile.AddChild(child); }

                )

Finally, we work through the Thens – assertions after the behavior is executed, starting with:

                .Then(“the number of children in the Family File should be”, 1)

Once the child information has been added to the Family File, there should be one child in the file, implying that a list of children can be added to the Family File. At this point, we are in traditional TDD territory, creating Assertions to verify functionality:

                .Then(“the number of children in the Family File should be”, 1,

                    delegate(int childCount)

                    {

                      Assert.That(familyFile.Children.Count, Is.EqualTo(childCount));

                    })

We’ve mixed in testing the list size with testing the property values. You might separate the two concerns in you scenarios. Keep going, working on the domain and applying TDD to complete the code.

Here is what the entire test fixture looks like:

using BehaveSharp;

using ChildCare.Domain;

using NUnit.Framework;

using NUnit.Framework.SyntaxHelpers;

 

namespace Specifications.ChildCare.Domain

{

    [TestFixture]

    public class Establish_a_new_Family_File

    {

        private Story establishANewFamilyFile;

 

        [TestFixtureSetUp]

        public void Narrative()

        {

            establishANewFamilyFile = new Story(“Establish a new Family File”);

 

            establishANewFamilyFile

                .AsA(“childcare center employee”)

                .IWant(“to enter information into a family file”)

                .SoThat(“child and guardian information can be tracked by the center”);

        }

 

        [Test]

        public void Add_child_information_to_a_new_Family_File()

        {

            FamilyFile familyFile = null;

            Child child = null;

 

            establishANewFamilyFile

                .WithScenario(“Add child information to a new Family File”)

                .Given(“a new Family File”,

                      delegate() { familyFile = new FamilyFile(); }

                )

                .And(“a child that will be added to the Family File”,

                    delegate() { child = new Child(); }

                )

                .And(“the child’s first name is”, “John”,

                    delegate(string firstName) { child.FirstName = firstName; }

                )

                .And(“the child’s last name is”, “Doe”,

                    delegate(string lastName) { child.LastName = lastName; }

                )

                .And(“the child’s suffix is”, “Jr”,

                    delegate(string suffix) { child.Suffix = suffix; }

                )

                .When(“I add the child information to the Family File”,

                      delegate() { familyFile.AddChild(child); }

                )

                .Then(“the number of children in the Family File should be”, 1,

                    delegate(int childCount) {

                      Assert.That(familyFile.Children.Count, Is.EqualTo(childCount)); }

                )

                .And(“the child’s first name in the Family File should be”, “John”,

                    delegate(string expectedFirstName) {

                      Assert.That(familyFile.Children[0].FirstName, Is.EqualTo(expectedFirstName)); }

                )

                .And(“the child’s last name in the Family File should be”, “Doe”,

                    delegate(string expectedLastName) {

                      Assert.That(familyFile.Children[0].LastName, Is.EqualTo(expectedLastName)); }

                )

                .And(“the child’s suffix in the Family File should be”, “Jr”,

                    delegate(string expectedSuffix) {

                      Assert.That(familyFile.Children[0].Suffix, Is.EqualTo(expectedSuffix)); }

                );

        }

}

And the resulting FamilyFile and Child domain objects:

using System.Collections.Generic;

 

namespace ChildCare.Domain

{

    public class FamilyFile

    {

        private List<Child> children = new List<Child>();

 

        public void AddChild(Child child)

        {

            children.Add(child);

        }

 

        public IList<Child> Children

        {

            get { return children; }

        }

    }

 

    public class Child

    {

        private string firstName;

        private string lastName;

        private string suffix;

 

        public string FirstName

        {

            get { return firstName; }

            set { firstName = value; }

        }

 

        public string LastName

        {

            get { return lastName; }

            set { lastName = value; }

        }

 

        public string Suffix

        {

            get { return suffix; }

            set { suffix = value; }

        }

    }

}

A very, very simple example. I hope it made some sense. Please let me know if you have any questions.

Advertisements

Written by Nelson

August 14, 2007 at 10:09 pm

Posted in .NET, BDD

6 Responses

Subscribe to comments with RSS.

  1. […] enough to post his experiences working with Behave#.  Please make sure to check out his post.  His point about the discovery of the his API through the story definition is very […]

  2. […] enough to post his experiences working with Behave#.  Please make sure to check out his post.  His point about the discovery of the his API through the story definition is very […]

  3. Looks great Nelson! You may be interested to know that we’ve just added the ability to create “Pending” scenarios, when you haven’t implemented the code to support the scenarios yet.

    http://grabbagoft.blogspot.com/2007/08/pending-scenarios-in-behave.html

    Hope this helps!

    Jimmy Bogard

    August 17, 2007 at 2:51 pm

  4. Hi Nelson,
    How are you finding the organisation:
    – Test class named after the name of the story
    – Test method named after the name of the scenario
    Is it working out well or are you discovering problems yet?

    I notice that you’re using the stories/scenarios to drive the design and implementation of domain model classes. To what extent are you finding that they replace the traditional TDD unit tests that would usually get written for these classes? Personally I have mixed (but mainly positive) feelings about using this framework to drive the design of the domain model classes. One of the big pros is that you’re only designing/implementing what is called for because of a user requirement (story). The downside of pushing most of the specifications/tests for the domain model classes into Behave# is that their specifications are now spread out over possibly lots of test (story) classes – there is no longer one (or maybe a few) test classes that you can go look at in order to understand the specification for a single production class. Now with is also somewhat the case for xUnit flavoured BDD “tests”, but at least with these you get to use the namespace as a way of grouping test classes that related to a production class (or two). But then maybe this is just an organisation that I holding onto because its one I’m familiar with…

    Have you tried applying this approach to driving the design of the Controllers/Presenters (in an MVP triad)? It seems like another alternative style of development is to use Behave# tests to drive the design of the Presenter as explained here: http://en.wikipedia.org/wiki/Presenter_First. Then to use traditional TDD / xUnit flavoured BDD “tests” to drive the design of the domain model classes that is just necessary to satisfy the behaviour that the Presenter requires. Food for thought.

    Anyway, keep up the good work (blog posts) and I hope to hear from you
    Christian

    Christian Crowhurst

    August 30, 2007 at 8:05 pm

  5. Christian,

    I wouldn’t say that I’m having problems with the format yet… but I am also trying out different formats and Behave# is going through some transformations that may change things altogether. More information on these changes should be coming out soon on the Behave# Wiki, Jimmy’s blog, and/or Joe’s blogs. For now, I can say that the format works for me for now. (Sorry if this isn’t much help.)

    However, I would say that you should group your user centric BDD “tests” (epics, stories, and narratives) by their natural business centric purpose and not based necessarily on the classes they are testing. If you have Resharper (go get it now if you don’t!), you can ask Resharper to tell you the uses of the class in question. The list of tests that the class participates in will come up. If the names of those tests/classes are business focused, you will find it amazingly helpful to infer the various purposes of the class based on those names.

    Personally, I feel your mixed feelings are valid and so I would say that the format you choose should work for you. If your team is not up to par on BDD, story focused requirements, and so on, then go with the format that makes sense. Believe it or not, you can always go back and refactor once you and your team have grown comfortable with this format.

    Now, for a quick example (I hope!).

    We are building some fingerprint reader functionality into our application. To start, we utilized Behave# based stories/tests to define out our interface. The result was a very clean relationship between what the end user wanted (to start/stop the reader and to capture the fingerprint) in Behave# format, how it was to be implemented (via an interface definition), and seperation from the implementation (a Microsoft fingerprint reader).

    At this point, we stopped using Behave# because we were in implementation territory by getting the Microsoft Reader API to correspond to our user’s desired interface. Our tests were still in BDD style, but we really were no longer in user territory. We utilized BDD style tests for continued clarity. Instead of testing “testSetFingerprintReaderToFingerprintReaderStartedStatus”, we specified “Should_indicate_FingerprintReader_has_been_started_correctly” and so on. Then our specification is a traditional BDD/TDD test.

    Let me get back to you on the controller/presenter link. The only thing I would say is that I have not used Behave# with controllers/presenters. Only for capturing the ubiquitous language clearly in non-UI code.

    Hope this helps? I’ll post soon with more details on the Fingerprint Reader.

    nmonta76

    August 31, 2007 at 4:25 am

  6. Hey Nelson, thanks for the helpful reply.

    >you should group your user centric BDD “tests” by their natural business centric purpose and not based necessarily on the classes they are testing.

    Yeah, this I can see being good advise particularly when combined with Resharper “find usages” searches. When it comes down to developer centric class specifications I still can’t help but find it actually a plus that there is a strong correlation between test classes and the class (or two) under test. Also I don’t like Setup methods as I think that this hinders readability of the test (you know got two places to look to understand the test see here http://www.agileprogrammer.com/oneagilecoder/archive/2005/07/23/6261.aspx). I prefer to have well named helper methods (and lean on the ObjectMother pattern) to extract out the common fixture setup code and then call these at the start of the test methods. As a side effect I find that this gives a lot of flexibility as to how you choose to group together specs/tests between classes – you are not restricted to always having to group specs/tests into a separate test class around a common fixture/context. In fact I only tend to split out the tests that share the same fixture into a separate class if I find that I’m repeating a description of the fixture setup in the names of say 3-4 tests. This means for example I can group into a single class all (or a subset) of specs relating to a particular behaviour but that has varying fixture setup – I find this a positive thing when reviewing in the IDE the behaviour descriptions as they are all in one (or two) places. As a related issue I’m also going to start to experiment adding a category to the test methods that will mark a spec/test as “Basic usage” and “Detailed usage”. Leaning on the new Resharper explorer feature, someone who wanted a quick overview of the system under test could then browse the specs in the “Basic usage” category without being bogged down with the detail. The inspiration of this comes from “Tests as documents” article here: http://www.agilestl.com/Articles/DoubleDuty.pdf (by Brian Button)

    The approach you’re taking with the fingerprint reader sounds a good one. I would *really* like to see more examples particularly those that show the delineation of customer focused story specs and then the TDD developer facing specs 🙂

    Christian

    Christian Crowhurst

    August 31, 2007 at 8:37 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: