From: David Masover Date: 2008-08-16T10:59:41+09:00 Subject: Re: BDD and TDD - What are they for? On Friday 15 August 2008 15:10:26 Clinton D. Judy wrote: > I'd like someone to give me very basic reasons for why I need Behavior > Driven Development (BDD, see RSpec) and/or Test Driven Development (TDD, > See Test::Unit). BDD is a philosophy and a vocabulary for talking about TDD. They are not mechanically different -- a good TDD suite should support BDD, and vice versa. But they do introduce a few new ways of thinking about the problem. > I do a very small framework, then attempt to run it and > see if it's giving me the result I expect. If it's not, then I figure > out what's going wrong, and attempt to solve it before going on to the > next small part. That's good. Question: How do you know when it's giving you the result you expect? BDD adds an extra step: You write down the result you expect, in code form, as tests. You then write your framework, pretty much as you've described, until the test passes. There are two direct benefits to this approach: First, you know when you're done. If it passes a test and you don't think it's done, write down _why_ you don't think it's done -- again, as a test. In other words, it prevents you from writing a ton of unnecessary code. The second benefit is that, coding this way, you accumulate some small measure of documentation: By reading your tests (which BDD calls "specs"), it's possible for someone to get an idea of what your code is supposed to do. > It looks like TDD does exactly what I'm doing, but introduces far more > code to the equation. Correct. I won't sugarcoat it -- when I'm doing proper BDD/TDD, I will sometimes have twice as much code in tests as I do in the actual program. > One of the biggest features of TDD is being able > to run a suite of tests to make sure new features don't break old > features. Not just new features, but any code change. It means that you can do a massive internal refactoring, or even replace one library (or program) with another, and have some assurance that things still work exactly the way they're supposed to. A simple example: Web browsers. Having the spec, in written form, wasn't good enough. That's why we have the Acid2 and Acid3 tests -- now we can know which browsers have properly implemented the specs, and to what extent. It also provides something for browser developers to work towards. > Yet I have an eye for this while developing; I either fix the > upcoming problem because I know it's going to happen, or I'm doing it > wrong in the first place. The problem is, you know your own code very, very well right now. Will you know this code that well in five years? Will you be able to change any part of it without fear that you will break something? And, perhaps more importantly, will a total stranger be able to sit down and do the same? > Sure, I occasionally miss, but who doesn't? Your test suite. > BDD looks like a way to make it easy for non-programmers to do > programming, but not having people keep several functions in mind at any > one time. It's not about keeping several functions in your mind. It's about keeping the entire program in your mind at once. But the mention of non-programmers does bring to mind another benefit, and one which I rarely see implemented: Stories. A story is a way to express, in plain text, how a program should behave, from the user's point of view. Ideally, a customer could write stories by themselves. Realistically, you would probably write the stories with the customer -- they do read like plain English, so the customer can understand them, but they need to be somewhat stricter, so that you can more easily use them to write tests later. Given a story, and a bit of translation, you can define your eventual target behavior, exactly the way the customer (or your boss) wants. Converted to integration tests, you have feedback as to when you're done -- when it does exactly what the customer wants. I'm still not fluent enough at writing tests that I can actually start with a clean project and test first. I still usually end up doing an evening or a weekend worth of code before I have enough of a program in place that I can properly reason about what my tests would look like -- what I actually expect from this program. But I'm not sure yet whether this is a deficiency in BDD or in my own line of thought. And I do find that after a week or so of development, the program has gotten to a point where I need tests -- or at least, where I'm doing so much testing manually that it's a pain. Simple example: I'm writing a program which spiders a certain website, scrapes some useful information out of the HTML, and dumps it into a database. I've been building it incrementally, as you've described, but every time I want to make sure something works, I have to start with a fresh database, open up an irb console, and have it download the same page. I then have to browse through the database records, making sure they match what I'm expecting. I'm about to convert this process to a test suite -- some pre-downloaded HTML, so I'm not hitting the site every time, and a test to cover this behavior, so that I don't have to keep browsing through records.