A Few Days into BDD

No, that’s not something about bondage and discipline, it’s behavior-directed development.

In a previous life, we had a gazillion lines of unreachable code, but never knew what we could get rid of. In my current life, we have quite a small program that needs testing, but we left testing to the end. Could BDD help?

Introduction

Behavior directed development uses a nice notation to specify how stories should be implemented: the person who wrote the stories should be able to read a “features” file and be able to say if it was what they wanted.

For example, you could write

Scenario: create a file in trial-use
  Given there is no such file as trial-use/junk.txt
  When we can put file trial-use/junk.txt from /tmp/data-file.txt
  Then file trial-use/junk.txt exists
  And put therefor works

and argue convincingly that you had proven the “green” case for put.

Behind the scenes, this turns into normal code, macro-expanded into a programming language, in this case python:

@when(u'we can put file {key} from {data_file}')
def step_impl(context, key, data_file):
    full_path = proto + server_ip + port + key
    implement_put(context, full_path, data_file)
    expect_success(context)

The @when maps an arbitrary string with parameters into a call to step_impl().

Notation

The classic form of a feature file is a list of scenarios, all looking like:

Scenario: X causes Y
 Given some prerequisite
 When I do X
 Then I observe Y
  • The Scenario clause says what I’m trying to achieve.
  • A “Given” clauses set prerequisites, and should always come out true. For example, it might clean out a trial-use/junk.txt if it exists.
  • A “When” clause is the thing I want to test, and which should succeed. If creating the junk.txt file crashes, it should throw an exception so the test runner knows it failed.
  • Finally, a “Then” clause tests whether or not the when clause did what it hoped to.

if you have multiple given, when or then clauses. you can call them “And” clauses, and they will be interpreted as the same kind of clause as the last one read.

Strengths and Weaknesses

What turns my crank is that it’s succinct enough that you can use it after the fact, when your or your colleagues don’t follow TDD or BDD. For a complete file service, I had one feature file and two python files.  I did break it up later, but it was that small.  So I wasn’t late.

What would have been an amazing win in my former life is that I can cover a complete ABI with a small set of tests, all for the success cases.  With those and a coverage tool, I can carefully find all the reachable code in the top-level API, and comment out the rest.  A reachability tool will then tell me what in the rest of the program isn’t needed any more.  That’s something I would have killed for.

There are some problems, though: in the python implementation, anything passed between clauses either had to be a global or an element of “context”, as implementation steps can’t share anything.

Conversely, every phrase in a given, when or then clause becomes part of a global state, so you end up thinking up counterintuitive ways of saying the same thing different ways for different scenarios: “Then I succeeded” can only exist once, with exactly one implementation.

The biggest weakness is one of its strengths: this is a very high-level language. That means that it is difficult to write low-level unit tests as I did in TDD. Instead, you need to think of the BDD tests as black-box tests of the required behavior. That’s wonderful, by the way: all too many unit tests are so low-level that they have to be completely rewritten if you find a better algorithm.

Conclusions

The next thing I plan to do is start writing BDD tests with go language as the implementation. I can write Go faster than I can Python, and I can write them first, in normal TDD/BDD practice. When I’m doing that, I can prune out all the dead code as I go, instead for having a “kill stuff” day at the end.

Advertisements

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s