Back in 2010, Tom Preston-Werner published his now classic article “Readme Driven Development”.
He starts from a simple idea: good implementation matters, but building the right software matters even more.
A perfect implementation of the wrong specification is worthless.
Tom’s surprising answer is:
write your README first
The reasoning will resonate with BDD/TDD practitioners: before it’s a way to communicate with others, a README is a way to communicate with yourself and clarify your intent. It’s a design tool that helps the right product emerge.
You could jump straight into coding and eventually reach the same result, but you’ll pay for it with many more, and much longer, iterations. And in practice, it often doesn’t go that well: it’s easy to get lost along the way, run into conflicting ideas, and quietly give up on the original intention. Rewriting a section of your README to adjust the specification is trivial; throwing away a code base and starting from scratch is not.
By contrast, clearly expressing what you need through concrete use cases or usage examples gives you a much sharper vision before you even write the first line of code.
You might think this sounds obvious, almost embarrassingly so. Yet it clearly isn’t obvious enough, otherwise we wouldn’t keep reinventing the wheel with shiny new labels like Specification Driven Development — an acronym that manages to be both impressive and perfectly tautological.
The Nightmare: No README and No Tests!
Here’s a simple observation: on public repositories, there are way too many utilities with no README at all, and just as many with no tests — and sometimes you get both.
When you’re focused on your main task, it’s very tempting to hack together a small side tool “quick and dirty”. You tell yourself you’ll write the README and tests later.
Of course, if there were an easy way to describe what your utility does once, and reuse that description directly as tests, the trade‑off would look very different.
The Idea: Write One README, Get Both Docs and Tests
The good news: such a solution exists, and it’s surprisingly simple.
It’s called bbt.
Let’s take a very simple example. Suppose I want to write a brand new tool that searches for strings in a text file. I’ll call this new tool grep.
A well-structured README will typically include sections like:
# Introduction
# Installation
# Usage
# Contributing
The Usage section often includes examples showing how to use the tool. That’s a good practice to help users get started quickly.
For example:
# Usage
## Case-insensitive search
`grep` can perform case-insensitive search
Given the file `Cities.txt` containing the line `Barcelona`
> grep -i barcelona Cities.txt
Returns
> Barcelona
But
> grep barcelona Cities.txt
Returns nothing
With very little effort, we have a clear description that is useful both for the developer as a specification, and for the user as a user guide.
The next logical step would be to add tests that check this behavior. Unfortunately, that usually means writing separate test scripts, wiring a test harness, and keeping everything in sync. Because tests largely duplicate what’s already written in the README (or any documentation), the two can easily start to drift apart without anyone noticing.
The same goes for examples: because they are not tested, they can contain errors or simply be out of sync with the current version of the software.
This is exactly where bbt comes into play.
With bbt, your example not only works as a specification and as a user guide, but it also becomes a test script. bbt reads the README, extracts the usage examples, runs them, and checks that the actual results match the expected ones.
How bbt Works: A Light Gherkin-Inspired Syntax
How is that possible?
bbt uses a specific syntax for usage examples so it can recognize and execute them. This syntax is directly inspired by Gherkin, and more precisely by MDG – Markdown with Gherkin.
We’re going to slightly adapt our README so that it becomes compatible with bbt.
1. Organize Examples as Scenarios
First, we put the examples under sections whose titles use Gherkin terms such as Scenario or Example. (Any header that doesn’t use a Gherkin term is simply ignored.)
Our README structure becomes:
# Introduction
# Installation
# Usage
## Example 1: Case-insensitive search
## Example 2: Recursive search
etc.
# Contributing
2. Use Given–When–Then Steps
Next, we use the classic Given–When–Then structure from Gherkin, and we follow bbt’s simple syntax for the steps.
Our case-insensitive search example becomes:
`grep` can perform a case-insensitive search.
## Example 1: Case-insensitive search
- Given the file `Cities.txt`
~~~
Barcelona
Lima
Ankara
Osaka
Tulsa
~~~
- When I run `grep -i barcelona Cities.txt`
- Then the output is `Barcelona`
- When I run `grep barcelona Cities.txt`
- Then there is no output
The structure is so light that it almost reads like natural language. But it is structured enough for bbt to parse it and turn it into an automated test.
And using it is as simple as:
bbt README.md
That’s it. With very little effort, you’ve turned a purely informative README into an executable README.
No test harness, no extra scripts, not even a tests directory.
And, most importantly, no more silent inconsistencies.
Conclusion
If there are two things to remember about bbt, they are these:
First, it turns your documentation into a single source of truth: by making the README executable, it leaves very little room for any gap to appear between what the documentation says and what the code actually does.
Second, it does this in a very efficient way: the scripts are quick to write and the tool is easy to use. In practice, you (almost) get documentation plus tests for the price of documentation alone.
In short, bbt gives README-Driven Development a new superpower: it turns READMEs into a living, executable specification.
If it only helped more authors take the small step of actually writing a README — and keeping it correct — that alone would be a huge win.
What’s Next?
Getting started with bbt is straightforward: just follow the instructions on the project’s page.
For the impatient, you can:
- install bbt by following the installation section
- look at another concrete example, such as the GCC “hello world” scenario, and start from there.
Note that the tool also comes with a built-in tutorial:
bbt help tutorial
If you maintain small command-line tools or libraries, try turning your README into an executable specification. You might find that writing the README first becomes the fastest way to get reliable behavior — almost by accident.
Top comments (0)