Showing posts with label Behavior Driven Design (BDD). Show all posts
Showing posts with label Behavior Driven Design (BDD). Show all posts

Monday, December 15, 2008

Why I Don't Use "Given, When, Then"

In Introducing BDD, Dan North states that he and Chris Matts were trying to develop a template that, "had to be loose enough that it wouldn’t feel artificial or constraining to analysts but structured enough that we could break the story into its constituent fragments and automate them." This gave birth to Given, When, Then syntax. One example that is given in the article is:

Given the account is in credit
And the card is valid
And the dispenser contains cash
When the customer requests cash
Then ensure the account is debited
And ensure cash is dispensed
And ensure the card is returned

This certainly has structure. But, I personally feel this is still a bit too artificial. Perhaps it is the large amount of content related to the context (account is in credit, the card is valid, the dispenser contains cash). I try to avoid specifying behaviors that have this many moving parts. I would prefer to see a behavior like:

The dispenser when the account is in credit should dispense cash.
The dispenser when the account is in credit should debit the account.
The dispenser when all transactions are complete should ensure the card is returned

I want to read sentences. When possible, I want to read short sentences. Given When Then generates a matrix of sentences to be parsed. GWT also saves some space in the report, but I gladly give that space back to have behavioral sentences that are easier to read quickly.

So, how do I keep the language regular and well-formed? The answer shows up more in the source code of the behvaiors than in the report. So, I might write the following behavior using EasySpec (in Groovy):


@EasySpec(interest='The dispenser')
class Dispenser_happy_path_Test extends GroovyTestCase() {

def account = new Account(balance:1000)
def dispenser = new Dispenser(available:5000)

@Context('when the account is in credit and the dispenser has cash')
public void setUp() {
dispenser.dispense(account, 100)
}

@Behavior
void test_should_debit_the_account() {
assertEquals(900, account.balance)
}

@Behavior
void test_should_dispense_the_requested_cash() {
assertEquals(100, dispenser.totalDespensed)
assertEquals(4900, dispenser.available)
}

@Behavior
void test_should_return_the_card() {
assertTrue(dispenser.lastCardReturned)
}
}

Upon running the EasySpec report, the user will get the following behaviors:


The dispenser when the account is in credit and the dispenser has cash should debit the account

The dispenser when the account is in credit and the dispenser has cash should dispense the requested cash

The dispenser when the account is in credit and the dispenser has cash should return the card


Easy Spec actually generates reports with nice formatting like this.

Perhaps all of this is just personal preference. But, I do find it easy to go back to old specifications and understand what is going on. Language and fluency are important.

You Might Be A Behaviorist...

Are you doing BDD? This is a question I've often heard at recent conferences. As far as I can tell, most people that have looked at BDD concepts are quite sure if they're doing BDD or not. Here are some sign that you might be a Behaviorist:

  1. You talk more about executable specifications and less about "tests."
  2. You write your specifications before you write the production code.
  3. You place high value on natural language in your tests.
  4. You can generate a system-wide report that shows system behaviors in natural language. Bonus points if you do this with every build.
  5. You write your specifications or tests with exactly one context per test class.
Not everyone that is doing these things would classify their projects as using BDD. And, not everyone that says they're using BDD is applying these concepts. But, I think that in the majority of cases you will find a majority of these practices in some form or another.

If I have missed anything, Dear Reader, please let me know.

My English Teacher Would Be Proud -- Proper Language Is Still Important

My high school had one English teacher that was dreaded by all, Mrs. Koch. Mrs. Koch's classes were known to be tough. Most of my friends were accustomed to getting high grades, but this didn't happen too often in Mrs. Koch's classes. Over the course of two semesters, one student got an 'A' in one semester. Mrs. Koch took for granted that we knew the basics that we were supposed to know. For written assignments, she assumed that everything would be spelled correctly and there would be zero grammatical errors. Assignments were graded for content, but grammatical errors caused sever markdowns in one's grade. Language was important.

I am thankful to Mrs. Koch for nurturing a strong sense of grammar in me. Perhaps this is what I have always liked the strict syntax of programming languages. This may also explain why I like Behavior Driven Development so much. Language was critical in Mrs. Koch's class, and language is critical to understanding business software.

BDD brings language into what I believe is its proper place -- the forefront. Language allows developers to understand the business. Language allows the development team to communicate with the project sponsors and domain experts. The more prominent, clear, and accessible our language is, the more readily we understand each other. The more accessible the language is in the code base, the easier it is to understand what we are doing and why we are doing it.

This is why I like BDD so much. When I read through specifications, I can understand what the system does. The more natural the language is, the faster I can stop thinking about syntax and start thinking about the correctness of the system. Natural language also helps to engage the non-developers on the team. While I've watched our project managers look at Java code and guess about what the system is doing, its much easier for us to have a conversation without Java language constructs getting in the way. Likewise, the less we talk about exceptions, try/catch blocks, and if-else statements, the better. Instead, we prefer discussing how the system should and should not behave under certain conditions.

Case in point: Instead of, "The protected area should thrown an exception for unauthenticated users," I would prefer to say, "The protected page should require the user to be logged in." We shouldn't have to acclimate the business types to programmer speak.

Clear language also helps us identity when the design is going astray. One simple word is often a clue to me that a class has too much responsibility. That magic word is, "and." Here's an example:

Lets assume that we're developing a console application that takes in a relatively complex configuration file. The customer has told us that, when the configuration is bad, he wants to be notified in a variety of ways. Sometimes this process will be run manually, and he would like the operator to receive immediate console output for bad configuration. Sometimes, the process is launched automatically and unattended, so he would like configuration problems to be emailed as well. For a final good measure, he has also requested that problems be logged to the logging system we have chosen for the project. We'll assume that the logging and email services live behind a nice interface that is easy to test. We might, then, get a specification that looks like this

The ConfigurationHandler, when some configuration properties are missing and logging is configured and email is configured should log an error for the missing properties and send an email for the error and write an error message to the console.

Assuming that our logging and email systems are properly testable (injected somehow), the actual calls to those services could be a pretty small footprint in the production code. However, this is too much responsibility for the ConfigurationHandler. We see it logging, sending email, printing to the console and killing the process somehow. There are lots of "ands" in the specification indicating that perhaps too much responsibility has been given to the ConfigurationHandler.

If we look at the behaviors shown, they are all about reporting the error. This is when we notice that, perhaps what we need is one more concept called the ErrorService. We can hide all the emailing and logging behind that. So, we break out a new class and a new interface and we end up with the following specifications:

The Configuration Handler, when some configuration properties are missing should report the missing properties to the ErrorService.

The ErrorService should forward errors to the log file, email, and console.


There are still some "and's" there, but the responsibilities are better broken down.

Language is critical to understanding software. BDD helps bring language into more prominence. What does the language of your specifications tell you?

Package Properly: Where Your Tests Live Is Important

About nine months ago, our team decided to start using Behavior Driven Design. Rather than making big changes in the build system to bring in a BDD framework, I put together a BDD reporting framework called EasySpec that allowed us to continue to leverage JUnit. One of our goals in trying BDD was to really push the limits of natural language in testing and determine what the limits were for BDD. We ran into limits with our mocking framework, but Mockito solved those problems for us (more on that in a future post).

One thing that we found was that BDD works pretty well for all levels of testing. Many of the BDD practitioners will only use BDD for higher level integration testing. However, I've found that I really like it for unit-level testing as well. Language is important regardless of where. It is certainly nice to understand system behavior in the large, but as a developer I need to understand behavior in the small as well.

We package our unit-level tests in a test source tree that parallels the production code source tree. So, if I am spec'ing out the com.company.foo.NewFoo, then the production source lives in myProject/src/com/company/foo/NewFoo.java and the first spec will end up in myProject/test/com/company/foo/NewFoo_when_X_Test.java.

One unintended advantage of staying with JUnit and EasySpec was that our new BDD tests landed right next to the old JUnit tests. The subconscious communication that this packaging created was wonderful. It removes the step of questioning where the next test or spec should live. The next spec goes into the parallel package. This also communicates that we are going to be driving the same requirements with BDD that we drove previously using TDD methods. In other words, we aren't just writing larger integration tests with BDD. We are writing as much as possible using BDD because again, langauge is paramount to understanding the system.

How do you package your specs? And, have you pushed the limits to find out how low-level you can drive BDD concepts into your design? I love designing in the small with BDD. My production code is better, and the specification artifacts are wonderful. When supporting code writting six months ago, I find it much easier to understand the system if we have EasySpec specifications rather than JUnit tests -- regardless of the level of abstraction under test.

Wednesday, May 28, 2008

Why Behavior Driven Development?

Two years ago, I became completely test-infected. I hate writing implementation code without writing the test first. Then, about six months ago, I was introduced to Behavior Driven Development (BDD). I liked what I saw, but I really didn't see any tools that I wanted to bring into our build system. The last thing that I wanted to introduce to the company was another test framework. JUnit was meeting our needs fairly well, and we were already using FitNesse on our team whereas the rest of the company was not. We didn't want to add another tool on top of that.

Then, a few months ago, I saw Scott Bellware give a talk on BDD and saw how he simply did BDD within a normal unit-testing framework and used .Net attributes to markup the tests with the BDD language. I liked what I saw. That night, I started a similar tool for JUnit called EasySpec. The tool still has some kinks to work out, but BDD has definitely brought some interesting insights into how we design our tests.

So, why BDD? At first, it was simply a trial of a style that seemed to do a good job of pulling out the Ubiquitous Language. Now that we have been using the techniques for about three months, I must say that I really like using BDD for creating software -- especially around the Domain Model.

BDD cleans up the language and gets the developers talking more about behaviors and less about implementation. Where, in the past, I might have been tempted to write a test with a method name like, "the_service_should_throw_an_exception_if_the_user_is_not_authenticated," I would now write that same test with a name like, "the_service_should_require_authenticated_users." Internally, the test would still be implemented in the same fashion, with probably the same code. However, language is important. It's important for the developers to think in the domain rather than hiding in the implementation layer. If I'm interested in the details of how the service requires authenticated users, then I can look at the details of the test (which should still be cleanly written) and see that in fact, the service will throw an exception if it somehow is handed an unauthenticated user.

This is merely one example. Keep a watch here for more information about BDD and why I'm hooked. Also, I should be putting some polish into EasySpec in the next week or two so that it's more user-friendly. If you're already using JUnit, and you want to try out BDD, take a look at EasySpec.

Friday, March 14, 2008

EasySpec in the works

I have started a new project named EasySpec for doing Behavior Driven Development in Java and Groovy. There is plenty of functionality that I want to add soon, but the core of it is available (as a .jar). The project page on GoogleCode can be found at http://code.google.com/p/easyspec/.

Our team has been using EasySpec for guiding our behavioral specifications for the last three months. I am hooked. If you want specific examples, leave some feedback here. I should be finishing up the current feature development within the next day or so. Then, I will be finishing some examples to be posted by the end of next week.

Saturday, October 6, 2007

altnetconf - Behavior Driven Design

This post is separated into summary and thoughts.

Summary


This thing called "Behavior Driven Design" (BDD) doesn't seem to have a formalized definition. Not everyone in attendance could agree on what "it" is. However, the most clear definition presented involves several components. Scott Bellware asserted that BDD = UserStories + TDD + UbiquitousLanguage + Solubility.

Some constraints on the above components should be explained. User stories must be well-formed. So, the idea is that during a conversation that the business analyst and the developer would work together to produce a story of the form "As a... I want to... So that..." The assumption is made that the TDD being used is driving design at a granular level with only one assertion per test. To extend Scott's definition of Solubility linked to above, another term "grokability" was proposed by Scott Hanselman.

The Behavior Driven Design (BDD) session began with many questions, asked many more, and perhaps answered a few things. Bellware started by saying that BDD is not about testing. He later stated that BDD provides better tests. So, to summarize, BDD is not about testing... except when it is. So, that make that about as clear as mud.

Much of the discussion centered on improving the conversation. More specifically, the conversation between the developer and the business analyst was discussed.

One criticism presented is that BDD is using programming languages to discuss things with the business analyst. The concern was that we would be asking business analysts to write specifications including the markup. This bred a great deal of consternation.

This critique was perhaps diffused later when the suggestion was made that the business analyst would sit down with the programmer, and the two would discuss the user story and the specifications. During that discussion, the developer would transcribe the conversation into the story markup used by the spec tool (RSpec, NBehave...). Another possibility presented was that the conversation could be initially captured onto a story card and then transcribed to the tool by the developer at a later time.

There was the assertion made that BDD provides or formalizes context for conversations with the business analyst and context for the developer to write the implementation.

Scott Hanselman says, "This is like NUnit that generates prose." There seems to be a bit of buy-in for this. Perhaps C# doesn't lend itself to the readability of the spec implementation. The business owner writes this through the ears of the developer that is sitting next to him.

Part of BDD is generating a specification document directly from the tests. This allows the tests and the information being passed back to the business analyst to stay in sync better. This is NOT to replace verbal communication, but again to provide a talking point to augment the conversation.

Thoughts


It seemed as though the thoughts around BDD have application in many parts of the development life-cycle. BDD practices are useful for clarifying the discussions that should be taking place during the entire process. The initial definition of user stories is helped by these practices. During development, BDD practices help developers see the bigger picture. Finally, and importantly, the executable specifications serve as a note to the future self. In other words, when you come back to the code, it is easier to understand why the test was written in the first place.

Much of the confusion came about because these thoughts are useful in so many different places. It seemed that participants saw the potential to have certain pains alleviated, then latched onto that particular portion of usefulness. BDD is aspect-oriented. It is a cross-cutting concern and does not simply fit into a single portion of the development process. Wherever there is conversation in the development process, formalizing that conversation helps to remove ambiguity.

Perhaps this is more useful when you MUST generate documentation. Not everyone needs to have everything generated in paper form. For some business, people, they feel better seeing the specifications generated as either a sheet of paper or a web site. Even in situations where this documentation must be generated, this documentation is not set in stone.

I'm pretty convinced that we don't need a separate tool to do effective Behavior Driven Design. We need to get much better at language - both natural language and expressing natural language with programming languages. As if the natural language wasn't ambiguous enough, we are forced to complicate it by writing something that the parser can understand.

The conversation about this is still in process. I'm sure that I don't know everything about this. I hope to continue to look in this area and find ways to write better software with less pain.