Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage Interviews Dan North on Behavior Driven Development

Dan North on Behavior Driven Development


1. Hi, my name is Ryan Slobojan and I am here with Dan North. So Dan, what is BDD?

What is BDD? BDD now is kind of quite different from BDD several years ago, when I started using the term which is around 2003 I guess. I would describe BDD as a full stack Agile methodology which is growing up a bit. What I mean by that is that's a way of delivering high value software frequently for good Agile stuff. When I say full stack, it works at the application behavior level, so when we are describing how an application works from the point of view of a stake holder of a user of someone interacting with that system, but also down at the code level describing interactions between objects, between components of the system. So it's kind of fractal, self similar, turtles all the way down.

And it started as a thought experiment if you like, it started as a linguistic experiment. I was coaching Test Driven Development, or coaching Agile teams to learn TDD and paring and all that contentious stuff, and I would hear some developers saying "I don't want to write tests. We've got testers to writing tests. I am too important to write tests". And this is typically an organizational coach where the testers are junior programming, testing is a thing you have to do, in order to become a junior programmer in order to become that so there's not very much for pecking order.

Whereas now I would like to think that certainly and a lot of that and the industry is growing up a lot in terms of understanding that testing is it's own domain and there's folks like here at Qcon like James Bloch and those sort of guys who are expert testers.

They specialize in the domain of testing. Now that testing and programming are kind of complimentary, side by side activities, this is five six years ago I guess, so your testers were considered like second class citizens of a program, so programmers don't want to write tests the flip side is the testers are going "Don't let programmers write tests, they got no idea how testing works, they shouldn't be allowed". And I was thinking "Well, we're not writing tests here." We are writing an executable specification here.

So we are describing behavior, and so I just switched the language and said "Right instead of talking about Test Driven anything, I said what we are going to do now is write an example of code you don't have". So, and they wrote me an example of code so it's not like specification anyway, these guys are used to working with functional specs. So I said what we are going to do is express that specification as Java code. And he said, ok that makes sense. And it's a much more obvious segue into your regular TDD cycle. So that was the initial push if you like was "Let's try and get out of the rat hole conversation about testing because it's not".

And around that time actually I wrote an article for a Java developers journal called "Test Driven Development is not about testing" and I was really badly dinged by programmers and by testers they went "Oh, they shouldn't be writing tests" and I am like "Didn't you get as far as the title?" I don't mind if you didn't read the article but if you start getting at me and you didn't even read the title that's a bit. So started there and I guess fairly rapidly I guess over six to twelve months it then started becoming obvious that or becoming apparent that the stuff we were talking about at a very low level in terms of describing behavior of tests also applied to an acceptance testing level.

So, I can express behavior of an application in the same way, it's equally useful so writing automated acceptance tests, is always more useful, it's like a direct value stream back to the user or back to the stakeholder so someone says "I care about this thing" what would you need it to do? Well we need it to do this. Let's describe that, let's describe the system in operating, acting in that way. And we will do that in an executable way and we can run it if it's executable and the first thing it tells me is that the system doesn't do that. Or mostly it tells us it doesn't do that if it happens to do that we're done, right? First I tell you it doesn't do that and now I have a and end point and it all seems when you talk about methodologies like Scrum and it talks about done-done which is code complete, it's ready for you, it's productionized.

I don't think you can even talk about done-done unless you've got that level of process automation and test automation because what happens is if you have a feature-wise delivery model I guess your traditional model is write a module park it, write another module park it and you got this big park of modules, all over again. With feature-wise development you tend to be going through all of your layers, all of your modules, you tend to be touching, re-visiting code very frequently and the whole kind of re-factoring thing happens because you are doing that because a lot more of your code base is volatile anyone time. The likelihood of introducing regression is huge, so I deliver feature number three and I am done.

I can show you that and show you that feature number three is done, fantastic, thank you. I am now doing feature number seventeen weeks later; I introduce a bug into feature number three but who cares. And no one is even going to notice until we are all down the line "Hang on a minute, feature number three is broken! Ah it's not done-done anymore". So, then we get into what I call outside-in development. So in other words you start now from the stakeholders and you say we are going to start from the outside, we are going to start from someone saying "Looking at this opaque system and I need it to do X". And then you work inwards from there and then you stop and you are done.

As soon as I can deliver that value, I am done. Or rather seems like I can deliver that value and I have got a sustainable ecosystem in my code, I have done my clearing out so it's done in a well factored way. So you get the layers going in. And something else about this behavior driven approach is you start to identify there is lots of different kinds of stakeholders so I don't like the term customer. I don't think there is a customer there's typically many categories of customers and I distinguish between what I call the core stakeholders and everyone else. So the core stakeholders are the people whose problems you are solving or whose vision you are realizing or who you are delivering the value to. I can't book my holiday online, once I can book my holiday online I am happy.

Those guys, they are the core stakeholders, or the people who are saying "I am a holiday company I want my customers to be able to book their holiday online" they are the core stakeholders. Anyone else who you introduce by the way you solve your problem, I call them incidental stakeholders so as soon as you use a database you have got a DBA as soon as you use a computer you've got a network and computer people and that kind of stuff. So those guys are all incidental stakeholders and what I mean by that is if I need to solve it a different way, I end up with different incidental stakeholders. So if I suddenly go all cloudy that I suddenly got like sort of an internet cloud providers are stakeholders, any type of relationship with those guys some other infrastructure guys that are in my organization and they are no longer stakeholders.

But these guys were delivering stuff to those guys as well. So anything that we can't recall like a non-functional requirement I use an analogy on my Maths lectures at college he used to talk about and he said one of the classes I did was non linear algebra. And he said talking about non linear algebra is like talking about non elephant zoology. I loved that. So what he was saying is actually just because it happens to start with linear algebra there's millions and millions of other kinds out there, and we kind of call all the rest non, to the one thing we knew. So it's the same thing, non-functional requirements, the functions, the things it does are one interesting aspect of behavior. But what about things like latency, availability, security, compliance? What about things like failover? All of those things there are stakeholders who care about those things.

If there aren't don't bother doing them. If you think security is going to be an issue here, find the person in the company who cares so all stakeholders now BDD speaks to those as well. We can describe the behavior you expect, the features you want they are still behavior, they are still saying that it needs to do this, well is that likely to have a material effect at deliver? If it is it's a feature and it needs to be accounted for. So BDD is kind of grown up I guess, now all these different groups of stakeholders it looks at behavior at application level and in fact folks like Jim Webber and Ian Robinson the kind that work with the big SOA guys that do big enterprise apps, they look at behavior driven across enterprise. This is describing behavior between collaborative services or between organizations so it's scaling up as well which is interesting.


2. So what's the relationship between functional and non-functional requirements and core and incidental stakeholders?

It's the "Of course" stuff. So like if you say to the core stakeholders "I want to book a holiday" then you don't expect them to say "I want to book a holiday and I would like that when I am half way through booking my holiday it doesn't crash". Why would I bother specifying that? Of course that I don't want it to crash. I would also like my credit card details not to be stolen, ok at what point do we stop here? I would like the sky not to fall in etc. this is the kind of responsibility that we have and so that's the role of the stakeholders to say "Here is all the stuff they are not telling you" but they will really notice if it's not there." They would really notice if they have blind users to say "I want to book a holiday and I can't use your stupid site".

So I am going to take my business elsewhere and if fact actually in lots of country that's illegal to present a site that excludes certain disabled categories. Those kinds of things, and that comes into compliance if you are doing financial systems or life critical systems, health systems, there's a whole bunch of external regulatory bodies that you have to involve. Non-functional is massively understating a vast area of what is interesting behavior characteristics.


3. With what you have been describing I think about frameworks like Fit or FitNesse which allow you to almost have the business stakeholders create tests in a sense in a language that they understand. So do you see that as being something that is complementary to BDD is it essential how does it fit in?

I think with anything you have a systemic reinforcing tools and process or tools and method if you like so once you understand that the method you have is close collaboration between stakeholders and delivery folks, using stakeholder language describing behavior for their terms, then if you provide tooling that makes that easier, makes it easier to do that and not do that then that is going to be useful to reinforcing but it's one of those things neither necessary not sufficient.

So using JBehave behave using Cucumber using any of the BDD frameworks or story kind of level frameworks or feature level frameworks, doesn't guarantee you are doing anything that could be described as behavior driven development, at its essence it's that relationship the feedback cycle between the stakeholders and the delivery team and shortening that and making it as expressive as you can in the language of the domain. The original vision for Fit was that you were describing behavior it's the what versus how thing, you are describing what the system needs to do to the extent that if you got it right, you should be able to roll a whole new system under it and if it does all that these Fit fixtures say then at that level it's the same system, it's an equivalent replacement system.

It turns out that it's a bit of a cow to use and things like for anything like that in any domain you would have abstractions. Programming languages support abstractions well or some programming languages support abstractions well. The tooling around any kind of automated acceptance criteria anything like that needs to support exceptions, need to support abstractions so, I might say if I am talking about authentication, if I am talking about logging in I might have a quite fine grained scenario, or functionality, whereas say I am going to navigate to a login view, login screen, enter my name as Dan and my password as "secret" and I am going to submit that. Two things: firstly at no point did I mention anything like what the screen was, so it could be a web page and that description would be equally appropriate if it was a rich application, or equally appropriate if it was a terminal. So I am not talking about the implementing technology, this is the first thing.

The second things that's going to get old really fast, so my next scenario given that I am logged in now, and I have to do this things all the abstractions over that called login as Dan. Given I have logged in as Dan, I logged in as Dan means I have gone off and done all these other steps. So the different levels of abstraction for this scenario it's where I am talking about that flow that's an interesting conversation where I am not, I just want to be logged in as Dan. And Fit struggled with that. Now I don't know what the state of the art is into the Fit world these days but I imagine that's a solved problem. But that was one of the things they struggled with.

Now, things like Jbehave2 and cucumber in the Ruby world, are bringing that much, much, more to life so literally I can write scenarios I can write these descriptions of behavior in plain text I just take them into the editor, which means anyone can write it in plain text. I can run those, I can execute those and any steps, any of the bits of behavior in there that aren't doing anything yet, it will tell me. So the developer tester cycle is really close so I can describe what the behavior is like I need it tell you if I can't even exercise that behavior I don't know if it's done yet. So the first thing is to define what it is, the second thing is to automate it so now let's say I can now go through all the steps of this scenario and demonstrate that they don't work yet now I can go and implement them so it's a pull model, it's pulled from the desire as a stakeholder I want to solve this problem, that pulls the scenario into being, I need to write this description down, which I now need to automate it because I add value there and I now I implemented just enough system that it does that.

Right now I am done-done but also I can take this automated scenario and I can immediately make it a regression test. So now when feature number nineteen now try to do a regression to feature number three bang it's going to get really quick feedback. So it's really hard to screw up a properly behavior driven system. Or rather now, it's just as easy to screw it up as it is to screw up any other system. But it's harder to not notice. So it's that kind of obviousness. So, good tooling is always going to help you. You can wire a plug with a butter knife which is not a great idea, and if you use a screwdriver it's just the right tool for the job. Having said that the vast majority of BDD stuff or stuff you could call BDD that I have done has been with JUnit what do I need? I need a base mail to write code and have it run.

That's a pretty well established family of stuff and the tooling, the IDE supports all that, it looks as if it's Jbehave2 with its plain text stories, and it will play nice with any runner, we didn't go and reinvent stuff so it's ok if you want to use JUnit3, JUni 4 as your runner if you want to use TestNG that's fine which is kind of cool, because now we are just solving the interesting problem of how you express behavior in stake holder language rather than you write a testing framework which is where I screwed up with Jbehave1. I solved the wrong problem.


4. It strikes me that a lot of what is required to get a good BDD implementation in place, like to get these tests from these stakeholders, you need to have good communication. What are your thoughts on that and how important is the communication to ensuring a successful BDD approach or a successful approach period?

I think it's probably the most important thing so that communication that feedback needs to be very high quality, virtually continuous. It needs to be constant and on-going. I can't remember who did the research someone like Alistair Cockburn who figured out there is a distance of your stakeholders from your team and it's based like if they are out of earshot there is a dramatic drop off of in terms of quality because they are not over hearing, you don't have these serendipitous of these conversations. Whereas someone happens to overhear you are talking about this thing in the domain and they say "Oh now that practically doesn't work like that. Oh really? No, let me just fix it.

Ah, thank you for that tiny little correction or adjustment". And you can now go down and complete your own path. The more likely you can make those situations, the better shape you're in and that's what I mean by systemic. As soon as they are in a different room that drops of dramatically but at least if they are accessible that's a good thing. If they are in a different office, that is harder again, if they are in different time zones, sucks. But it's about going into those things with your eyes opened. So, you can scale this stuff, I have seen this work well on large distributed teams.

But as long as you know what it is you are trading off, so you know as soon as I got a team in India and a team in the UK I know that that stuff I need to manage so at least I am aware of that. So what does that mean? It means that I need to over compensate for that communication, that impedance. A lot of the stuff I think in the past with distributed teams was how it worked it was a lack of understanding of the enormity of the impact over just being at distance. And the fact that you can't package up the testing and bang it over there, package off the development and bang it over there, you need to collocate these teams because that communication and that feedback cycle is everything. I can't possibly know I am delivering value unless I am showing you my steps towards that and you are saying that's exactly what I had in mind.

But it's also that's a virtuous cycle, where I show you something, it's like the art of the possible, you see and you go "Wow! I didn't know you could do that! Well in that case, could I have this thing? And actually I don't care about the other thing I was talking about the other day because it is not important now if we solve it this way, I hadn't even thought of that". Or although when we mocked this out we talked about the flow being like this, we found that now we are actually able to play with it a bit, tend to do these particular sequences quite a lot, and it feels like there is far too many clicks involved, and can we maybe shorten those cycles. Yes sure, let's look at how you are using it, ethnography, let's find how it is to be you doing this. And again those sort of things happen much more frequently I guess and with much greater success than if you could shorten that loop.


5. One of the things that you have been doing in the past is helping to rescue broken systems. So fix broken architecture or refactor things.

We don't call them rescue projects. Yes, I like to think of ThoughtWorks as kind of like getting in rentakill, we are really, really good at what we do, we are really, really effective at that stuff, you don't have to admit you have to guess for entire classes for problems, like there are obviously a lot of engagement where there is more like we want to do this really courageous, exciting, big bold thing, and we want a partner who can do big bold thing we do this stuff together, that's enormous fun, then there's other stuff where we have got this big ugly legacy system and my definition of legacy is making me money, valuable and I am not scared to change it. And other folks talk about legacy systems are systems without tests and I am like "Testing is one vector for making it safe to make changes, but any system where I am scared to change it" so the reasons of my two criteria: if it's not valuable get rid of it, it's not interesting and also with all this legacy code with all this ugly systems, the first thing to note about them is they are useful, they have value, you can't go "Oh this is rubbish, who wrote this?" No, stop, this thing is making us money.

We are already in a pretty good place. What we want to do now is change it to do different stuff. Those projects are quite interesting typically and again it comes back to like Conway's law the system will reflect the organization it was built in. so if you have a large sprawling system, lots of things in the organization, lot s of silos of knowledge and lots of command and control structures that's how your code is going to look like. And this is why you get this very defensive code or sprawling, leaky abstractions and leaky domain models all over the place domain model it's just kind of moving data around and data structures that kind of stuff is really sucky. So you are looking at that and say "How do we start here?" and say typically where I start is by trying to ask questions of the system "What is it you do? I am going to run some assumption tests, I am going to document what I think you do because that is my own exploration, I am going to explore you as a system, the way I am going to do that is I am going to write some tests. And each test is, if you imagine a one-liner, one sentence "I think you do this".

I think that when I put these values in this happens. I think you sent that message, this is what I think you do. Instead of just writing that assumption down, in a document Dan's system assumptions, each of those is now a test and I can run that test and one of two things happen, either it passes so my assumptions is true or if it were to fail I would now my assumption was wrong. I have got evidence to support my assumption now. Still a hypothesis but now I found evidence to support it. If the test fails, great that means either my assumption is wrong so I definitely learnt something there, or my assumption is right, it's supposed to do that and I found a bug. Either of those is useful, either of those is a good outcome. And then gradually build up an awareness of the system in that way.

So I guess the question is what kinds of things do I see when I get there? You can take a pretty good temperature check, you can take the health check of the team, the organization, all that kind of stuff by looking at what it's created if you like, so every system has outputs, every system is doing stuff, so let's look at what is that path to production like? What is that build like? How do they do work date to date? What is the communication like in the team? What is the energy like in the team? Are they having fun? Are they engaged? Are they checked out? I would much, much rather meet angry people than checked out people. Because angry people have energy have passion they are typically frustrated and you can hardly direct that and that's brilliant that's a really good fun. When they are checked, it's like "Oh you poor people" because normally you've got smart people and by the time they are checked out they must have been through some stuff so you got to reach out to those guys. So it's as much a social exercise, it's probably more a social exercise than it's a technical exercise.

It's let's understand what is true in this organization and what it's like to do work in this organization to be part of this. And you have to go in there thinking like a novice, thinking like a beginner you got to go in there it doesn't matter what your experience is, how much you know about stuff, when you walk in that environment you know nothing about that environment, you don't know the people the politics, the organizational structures, the motivating factors, what's good what's bad, what sucks, you don't know any of that stuff, so it's kind of presumptuous to go in and say "hi I am going to come in and fix some stuff". No I am not, I am going to come in and listen, I am going to come in and try to find out what it's like to be here and then maybe I can form some opinions as we go. But it's that going in with the curiosity I think it's the most useful thing I have learnt about getting into these situations.


6. And with your sets of assumptions and your compatible tests, you almost sound like you are talking about a BDD approach to learning how the system works.

Absolutely so what I am looking at it and say "What should this system do?" and it's funny because it ties in a lot with Michael Feathers work around legacy systems where he is talking about things he is talking about where areas of responsibility leaves and what is the hand off between those areas of responsibility. It's a very similar approach whereas who is responsible for it, where does the behavior live? What does this system do? And you can often find an entire chunks of a system that have grown up over time evolving the big ball of mud the spaghetti architectures they sometimes just have a really simple responsibility and actually the problem is solved although the point where problem was address it was a good resolution.

Every one has written a cache at some point at the point where this ten year old system was written there maybe wasn't a good commodity caching product so we had to solve that problem and people have solved it better ever since. So now we see that this whole chunk over here is actually solving the problem of cached stuff. So I can take it out and replace it with something else that solves the problem of cached stuff. So I can do enterprise or architecture level re-factorings big scaling re-factorings but understanding where the responsibilities are where the boundaries are for those responsibilities and who does what? Where the behavior is? So absolutely as a BD approach it's outside and the whole thing is a black box what does it do? If I poke it there, does this thing come out? If it does I have just learnt some stuff, if I thought I poked it there some stuff came out and actually stuff came out over here and nothing came out over there, well it's not the system I thought it was. So either my assumptions are wrong like I said or I found a bug. Cool, either of those is good news.

Apr 02, 2010