More BDD xBehave Madness!

Well over the past week or so I have been working off and on with improving the usage of NUnit.Behave.  It started off being tightly coupled with NUnit since you actually had to inherit an abstract fixture that exposed the “Given, When, Then” BDD constructs.  With a bit of tinkering with C# generics and some fluent interface magic, I managed to decouple the code into its own, dare I say,  framework.

Before I continue I need you to understand the goal of what I am creating.  Based on Dan North’s initial vision of rbehave, I modeled the syntax of the xBehave (insert catchy agile term here) framework around rbehave.  The primary goal of rbehave is a framework for defining and executing application requirements.  These definitions are modeled after BDD terms such as Story, Scenario, Given When Then. Using a minimum of syntax (a few “quotes” mostly), this becomes an executable and self-describing requirements document.  By utilizing the definitions within the actual unit test code of the application, the ubiquitous nature of the architecture and domain become one cohesive amalgam.  With the help of Domain Driven Design all these concepts seemingly bring together our software.  The code actually becomes what we have always wanted, living requirements that are constantly asserted on to insure their viability and accuracy from the inception of the software architecture.  Can you say true tracebility!

Now lets consider something for a moment.  Who are the owners of our requirements(stories)? If you said the product owner, then you guessed correctly.  So we have a product owner who wants to tell us how they think our software should behave.  So lets take this a little further. 

In my shop, we practice agile development. Our release cycles are comprised of a storming phase, planning phase, development phase, SIT/UAT phase and finally production deployment.  Each release cycle is typically 6 weeks long.  During the storming and planning phase, we conduct modeling sessions comprised of a product owner, modeler, developer and systems analyst (QA). Utilizing a Domain Driven approach we model each story to understand the business need and value.  The problem is that various artifacts have to be maintained during these sessions.  Namely wire frames, domain models, and test plans.  Not to mention the actual story cards.  I am not going to lie to you and tell you that everything runs like a well oiled machine. After all we do have people in the equation here.  Their in lies the problem, people think in different ways.  Trying to enforce certain story context structures As, I want, So that, seems to be hit and miss.  These concepts are hard to enforce when the business is your customer.  So my goal was to try and see if a product owner could actually code the requirements in Visual Studio and hope that my type constraints would be enforced at design time.

I approached one of our product owners and asked her if she would be willing to try an experiment with me.  She was very reluctant at first but when I explained that I may have an idea that can save her time from a story authoring standpoint and introduce quality from inception she quickly became interested.  Like most product owners she had never utilized an IDE.  I opened up Visual Studio and created a basic NUnit test fixture.  I opened up Dan North’s blog on another monitor and showed her the basic story for transfer account.

Story: transfer to cash account
  As a savings account holder
  I want to transfer money from my savings account
  So that I can get cash easily from an ATM

I told her we are going to create a new story based on this model but I want you to type it in code.  She quickly told me that she had never typed any code in her life and she doesn’t know how productive she could be.  So I walked her though the instantiation of the story as I knew this would probably be the hardest concept to grasp.

Story story = new Story(“Transfer to cash account”);

I explained to her that the title of the story is the first piece of information that is needed.  I showed her the intellisence that visual studio would lend to help her along.

image

After that we went ahead and created the remainder of the story using a fluent interface.  I made certain not the expose all the fluent behaviors off the story class.  I did this because I wanted to walk the user through the template.  If I exposed all the behaviors at once they could mess up the fluidity of the interface. Such as:

story.I_want(“to transfer money from my savings account”)
     .As_a(“savings account holder”)
    .So_that(“I can get cash easily from an ATM”);

This doesn’t help the user, so after they press “.” on the story class the only methods that are exposed are:

image

I did this by chaining together conjunction types that expose only the required methods at one given point in time.  Works out quiet well since the editor enforces the type hierarchy at design time.  Notice how similar it is to rbehave (lots of quotes).

In the end we ended up with the following syntax.

        [Test]
        public void Transfer_to_cash_account()
        {
            Story transfer_to_cash_account = new Story(“Transfer to cash account”);

            transfer_to_cash_account.As_a(“savings account holder”)
                .I_want(“to transfer money from my savings account”)
                .So_that(“I can get cash easily from an ATM”);

            Scenario savings_account_is_in_credit = new Scenario(“savings account is in credit”);

            savings_account_is_in_credit
                .Given(“my savings account balance is”, 100)
                .And(“my cash account balance is”, 10)
                .When(“I transfer to cash account”, 20)
                .Then(“my savings account balance should be”, 80)
                .And(“my cash account balance should be”, 30);

            savings_account_is_in_credit
                .Given(“my savings account balance is”, 400)
                .And(“my cash account balance is”, 100)
                .When(“I transfer to cash account”, 100)
                .Then(“my savings account balance should be”, 300)
                .And(“my cash account balance should be”, 200);
        }

When you run the test runner you receive the following output.

Story: Transfer to cash account
    As a savings account holder
    I want to transfer money from my savings account
    So that I can get cash easily from an ATM

Scenario: savings account is in credit
    Given my savings account balance is 100 <pending action>
    And my cash account balance is 10 <pending action>
    When I transfer to cash account 20 <pending action>
    Then my savings account balance should be 80 <pending action>
    And my cash account balance should be 30 <pending action>

Scenario: savings account is in credit
    Given my savings account balance is 400 <pending action>
    And my cash account balance is 100 <pending action>
    When I transfer to cash account 100 <pending action>
    Then my savings account balance should be 300 <pending action>
    And my cash account balance should be 200 <pending action>

The <pending actions> indicate that the development team still has to wire up the implementation code.

I asked her if she thought if she could do this with ALL the stories her team creates.  I proposed that during the storming phase her team(business analyst) just create the stories.  During the planning phase we can come up with the scenarios and edit them together.  From there the developers can take these behavioral scenarios and implement the code to insure that we created the functionality according to business teams specifications.  We both agreed that it was possible but that it would take time to get everyone on board.

I asked her 3 closing questions.

  1. Was the story easy to author? Yes “After I got use to the little boxes popping up and remembering to use quotes.”
  2. Were the scenarios east to author? Yes, “but the action value took me a while to get use too.”
  3. Is the output valuable? Not really, it helps but I don’t see how we would use it.

I followed up question 3 with ” I am working on a way to output all the output to an HTML page similar to CruiseControl and you can visually see after every build what stories have been completed and what stories haven’t.  She seemed OK with the response but reserved on actually seeing the final product.

 

So as a developers we would simple use the Action<T> delegates to pass in statement blocks of the actual code implementation.  Which would look like the following code.

        [Test]
        public void Transfer_to_cash_account()
        {
            Story transfer_to_cash_account = new Story(“Transfer to cash account”);

            transfer_to_cash_account.As_a(“savings account holder”)
                .I_want(“to transfer money from my savings account”)
                .So_that(“I can get cash easily from an ATM”);

            Account savings = null;
            Account cash = null;

            Scenario savings_account_is_in_credit = new Scenario(“savings account is in credit”);
            savings_account_is_in_credit
                .Given(“my savings account balance is”, 100,
                       delegate(int accountBallance)
                           {
                               savings = new Account(accountBallance);
                           })
                .And(“my cash account balance is”, 10,
                     delegate(int accountBallance)
                         {
                             cash = new Account(accountBallance);
                         })
                .When(“I transfer to cash account”, 20,
                      delegate(int transferAmount)
                          {
                              savings.TransferTo(cash, transferAmount);
                          })
                .Then(“my savings account balance should be”, 80,
                      delegate(int expectedBallance)
                          {
                              Assert.AreEqual(expectedBallance, savings.Ballance);
                          })
                .And(“my cash account balance should be”, 30,
                     delegate(int expectedBallance)
                         {
                             Assert.AreEqual(expectedBallance, cash.Ballance);
                         });

            savings_account_is_in_credit
                .Given(“my savings account balance is”, 400)
                .And(“my cash account balance is”, 100)
                .When(“I transfer to cash account”, 100)
                .Then(“my savings account balance should be”, 300)
                .And(“my cash account balance should be”, 200);
        }

When you run this test with the delegates wired up you receive the following output:

Story: Transfer to cash account
    As a savings account holder
    I want to transfer money from my savings account
    So that I can get cash easily from an ATM

Scenario: savings account is in credit
    Given my savings account balance is 100
    And my cash account balance is 10
    When I transfer to cash account 20
    Then my savings account balance should be 80
    And my cash account balance should be 30

Scenario: savings account is in credit
    Given my savings account balance is 400
    And my cash account balance is 100
    When I transfer to cash account 100
    Then my savings account balance should be 300
    And my cash account balance should be 200

 

As you can tell the <Pending Action> flags are gone indicating that the code has been implemented.  The fact that we didn’t receive any assertion errors means that the code passes the behavioral expectations.

The magic of generics and anonymous generic delegates

I learned a great deal about generics implementing this framework, so I thought I would pass some tidbits of information on to the rest of you.

lets look at the following method:

public GivenContext Given<T>(string theGivenSentence, T actionValue)

Since <T> is declared at the method level the C# compiler will infer the type being passed to the method.  This inference model is what allows the xBehave framework to persist it’s syntactic goal of being as similar to rbehave as possible.  With out it a Given statement would look like this.

.Given<int>(“my savings account balance is”, 100)

Imagine training a business analyst to make sure they use the correct types in the angle brackets.  Ummmm No.

But the magic doesn’t stop there.   You can use the generic type within an anonymous delegate.  Consider the following Given method:

public GivenContext Given<T>(string theGivenSentence, T actionValue, Action<T> delegateAction)

You will notice the Action<T> delegate type.  This is wonderful as it allows the inferred “T” type to be passed to the delegate as well.  You cannot break the signature, even if you try the editor (with ReSharper that is) will flag an error a follows:

image

Notice that the actionValue being passed in is an integer and in the delegate the developer accidentally thought it should be a string.  This type checking at design time Forces the developer to implement the correct parameter types within their code.

 

I emailed Dan to make certain I was on the correct path with his intentions of rbehave as I created this framework.  My hope is that it will gain momentum and help to synergies development around the story aspect of agile development.  Bringing the product owners ever closer to the foundation of code can only be a good thing.

 

As always the latest code can be downloaded from here.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Joe Ocampo

My personal philosophy is simple: "Have a good strategy that sets the environment for success through the enablement of the whole. Be agile but with a mind towards pragmatism. Delegate to the best qualified individuals, but don’t be afraid to involve yourself in all parts of a job. Treat everyone with respect, humility, and with a genuine pursuit towards excellence." Respected business and technical leader with expertise in directing organization towards effective results driven outcomes. Proven ability to perform and communicate from both technical and business perspectives. Strong technical and business acumen developed through experience, education and training. Provides the ability to utilize technology, harness business intelligence and execute strategically by optimizing systems, tools and process. Passionate about building people, companies and software by containing cost, maximizing operational throughput and capitalize on revenue. Looks to leverage the strengths of individuals and grow the organization to their maximum potential by harnessing the power of their collective whole and deliver results. Co-Founder of LosTechies.com
This entry was posted in BDD (Behavior Driven Development), Domain Driven Design (DDD). Bookmark the permalink. Follow any comments here with the RSS feed for this post.

7 Responses to More BDD xBehave Madness!

  1. David Starr says:

    Wow. Just, wow.

  2. David Starr says:

    Wow. Just, wow.

  3. Jeremy says:

    This is really impressive, Joe. I’ve just started getting into BDD with NBehave so my eyes are still getting opened to a lot of possibilities but I’ve been hoping to involve our business analysts similar to how you have here. I’m really lucky in the sense that one of my BAs actually has a CS degree so I think that’ll help to ease the pain. Thanks for the info!

    Jeremy

  4. Joe Ocampo says:

    Jeremy,

    Let me know how it goes with your BA. I would welcome the feedback.

  5. casper says:

    Thanks for leaving the comments .. I’ll definitely write more once I get a chance to test it in the real world :)

  6. Matt Kelly says:

    Great work, it’s started me thinking about all sorts of possibilities!

    One thing – in the code samples balance has a rogue extra L (ballance) ;)