Showing posts with label TDD. Show all posts
Showing posts with label TDD. Show all posts

Thursday, 7 August 2008

Early and continuous feedback - ftw

Feedback We’re having a beautiful summer here in London.  (Update: Typical!  That jinxed it!  Sorry.) It seemed like I would have been wasting it to rush back to work.  But feet get itchy.  So I’m very excited to be starting at Conchango on Monday as a Senior Technical Consultant.  I’ve known about Conchango for a while and theirs was the first name that came to me when I was thinking about who I’d like to work with.  Agile, modern, pragmatic, talented people etc. 

One thing that’s really impressed me is the feedback that I’ve been getting during the recruitment process (thanks Michelle).  At both interviews I was given immediate feedback (including from a technical test).  That’s something that’s never happened to me before!  I’ve probably only been for a dozen interviews in my career but I’ve interviewed lots more candidates.  Always the feedback has been something that happens after the event – I’ve been as guilty of it myself. Usually over the phone or in an email a few days later. But early feedback is very important.  It makes everything clear, transparent, honest.  It prevents time being wasted and gets things moving much quicker.

In Agile we depend on early feedback.  We can’t work without it.  The whole thing breaks down if the customer is not available to let us know what’s good and bad about what we’re doing.  It helps prevent us making speculative assumptions and wasting our time.  Test-Driven Development and Behaviour-Driven Development give us early feedback – green lights everywhere for that nice fuzzy feeling.  Make it fail --> Make it pass --> Make it right --> Feel good.  Feedback makes us feel good.  Early feedback makes us feel good sooner.

At London Underground we used a product from JetBrains called TeamCity for Continuous Integration (CI).  A lot of people use CruiseControl.  I found TeamCity easier to set up (it has loads of features and the professional edition is free).  Whatever tool we use, the reason we do CI is to give us early feedback – we know immediately when the build is broken or the tests start failing.  Why?  So that we can fix it straight away.  That keeps the team working and the software quality high.

All these feedback mechanisms help prevent us from introducing bugs (or going off on tangents) – or at least they help us catch problems early – and we know how quickly the cost of fixing stuff rises the longer it takes to discover it.  The feedback helps us get it right.  Everyone wins.

Feedback should be something we do all the time.  In every conversation we ever have.  I know one thing - I’ll never interview anyone ever again without giving them honest and immediate feedback at every stage.

Tuesday, 22 July 2008

The Language of Behavior

Software quality is directly proportional to the quality of communication that takes place between the business and the developers My mother researched our genealogy back several centuries and I’m just about as English as they come – so I decided to spell “Behavior” without a “u”.  That’s the correct way to spell it – at least it was before we changed it to please the French!  Plus it Googles better.

Why is this important?  Well, the spelling’s not.  But the language of behavior is.  Eric Evans in his book “Domain-Driven Design” coined the term “ubiquitous language” meaning that the domain model should form a language which means as much to the business as it does to the software developer.  Software quality is directly proportional to the quality of communication that takes place between the business and the developers – and speaking the same language is essential.  How the software behaves should be described in terms that have meaning to everyone.

Enter “Behaviour-Driven Development” (BDD) which takes “Test-Driven Development” (TDD) to the next level using the language from the “Domain-Driven Design” (DDD).  It’s the holy grail.  To be able to describe what an application is required to do, in the ubiquitous language of the domain, but in an executable format.

Developers hate testing.  They even hate the word “Test”.  Loads of developers just don’t get TDD. It’s because the language is wrong.  Take the T-word out of the equation and it suddenly makes more sense.  Replace it with the S-word.  Specification.  We’re going to specify what the application is going to do (using the vocabulary) in an executable format that will let us know when the specified behavior is broken.  Suddenly it all makes sense.

So in BDD we have the user story expressed in the following way:

As a <role>
I want <to do something>
So that <it benefits the business in this way>

Then the story can feed the specification using Scenarios:

With <this Scenario>:
Given <these preconditions>
When <the behavior is exercised>
Then <these post-conditions are valid>

Which is effectively the Arrange, Act and Assert (3-A’s) pattern ( Given == Arrange, When == Act, Then == Assert) for writing tests specifications.

And, don’t forget, the specification needs to be executable.  For this we would love to have a language enhancement – we actually need Spec# right now.  But we won’t get that for a while (although I encourage you to check it out, and petition Microsoft to get C# enhanced with DbC goodness).  So in the meantime, we need a framework.  In the .Net space several frameworks (NSpec, Behave#) came together to form NBehave.

Now you can write code like this:

[Theme("Account transfers and deposits")]
public class AccountSpecs
{
    [Story]
    public void Transfer_to_cash_account()
    {
        Account savings = null;
        Account cash = null;

        var story = new Story("Transfer to cash account");

        story
            .AsA("savings account holder")
            .IWant("to transfer money from my savings account")
            .SoThat("I can get cash easily from an ATM");

        story.WithScenario("Savings account is in credit")
            .Given("my savings account balance is", 100,
                 accountBalance => { savings = new Account(accountBalance); })
            .And("my cash account balance is", 10,
                 accountBalance => { cash = new Account(accountBalance); })
            .When("I transfer to cash account", 20,
                 transferAmount => savings.TransferTo(cash, transferAmount))
            .Then("my savings account balance should be", 80,
                 expectedBalance => savings.Balance.ShouldEqual(expectedBalance))
            .And("my cash account balance should be", 30,
                 expectedBalance => cash.Balance.ShouldEqual(expectedBalance))

            .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)

            .Given("my savings account balance is", 500)
              .And("my cash account balance is", 20)
            .When("I transfer to cash account", 30)
            .Then("my savings account balance should be", 470)
              .And("my cash account balance should be", 50);

        story.WithScenario("Savings account is overdrawn")
            .Given("my savings account balance is", -20)
              .And("my cash account balance is", 10)
            .When("I transfer to cash account", 20)
            .Then("my savings account balance should be", -20)
              .And("my cash account balance should be", 10);
    }
}

And you can run that in a test runner like Gallio (which even has ReSharper plug-in).  Just like you would run your NUnit/MbUnit/xUnit tests.

Jimmy Bogard, one of the authors of NBehave, wrote a great post about writing stories using the latest version (0.3).

NBehave is young.  But I love the fluent interface.  And the caching of the delegates.  And the console runner outputs a formatted (more readable) specification that you can give to the business.  It makes for really readable specs.

What about the granularity of these specs?  There’s definitely more than one thing being asserted.  But they’re much more than tests.  They are unit tests specs and acceptance tests specs combined. They define the behavior and check that the software conforms to that behavior, at the story and scenario level.  That’s good enough for me.  I’d much rather have this explicit alignment with atomic units of behaviour (OK, the English spelling just looks better).

Also, it reduces the coupling between the behaviour specification and it’s implementation, which means you can alter the implementation (refactor) without having to change the tests specs.  At least not as much as you might with traditional TDD.

To me it brings a great perspective to software development.  I’ve always believed in unit tests and in TDD.  This is just better.  By far.