Let’s go back to history first!
Behavior Driven Development is well-accepted and current methodology in agile projects. Behavior Driven Testing (BDT) is a lesser known companion of Behavior Driven Development (BDD). BDT can be used without BDD.
In software engineering, behavior-driven development (abbreviated BDD) is a software development process based on test-driven development (TDD). Behavior-driven development combines the general techniques and principles of TDD with ideas from domain-driven design and object-oriented analysis and design to provide software developers and business analysts with shared tools and a shared process to collaborate on software development.
Although BDD is principally an idea about how software development should be managed by business interests and technical insight, the practice of BDD does assume the use of specialized software tools to support the development process. Although these tools are often developed specifically for use in BDD projects, they can be seen as specialized forms of the tooling that supports test-driven development. The tools serve to add automation to the ubiquitous language that is a central theme of BDD.
Behavior-driven development was developed by Dan North as a response to the issues encountered teaching test-driven development:
- Where to start in the process
- What to test and what not to test
- How much to test in one go
- What to call the tests
- How to understand why a test fails
At the heart of BDD is a rethinking of the approach to unit testing and acceptance testing that North came up with while dealing with these issues. For example, he found that unit test names should be whole sentences starting with the word “should“ and should be written in order of business value. Acceptance tests should be written using the standard agile framework of a User story: “As a [role] I want [feature] so that [benefit]”. Acceptance criteria should be written in terms of scenarios and implemented as classes: Given [initial context], when [event occurs], then [ensure some outcomes].
BDD & BDT Advantages
It involves getting stakeholders and delivery team with different perspectives onto the same page and ensuring that all have the same expectations. BDD starts with a business goal and goal that translates to features and stories.
The goal of BDT is a business readable and domain specific language that allows you to describe a system’s behavior without detailing how that behavior is implemented.
In BDT, Tests in the form of plain text features descriptions with scenarios are typically written before anything else and verified by the non-technical stakeholders.
Testing. It often gets left to the last minute, then cut because you’re out of time, over-budget, or whatever else.
Management wonders why developers can’t just “get it right the first time”, and developers (especially on large systems) can be taken off-guard when different stakeholders describe different parts of the system, like the story of the blind men describing an elephant.
It’s inevitable, however, that the first step in every project is a discussion about the behaviors of the software or feature to be built. A client or business person comes up to someone on the development team and explains what they want.
Sometimes these interactions come in form of an Agileuser story. Sometimes they come in the form of design documents, as in Chris Fox’sblog entry last year. They could also come as flowcharts or mockups in Keynote, or even hurried phone calls.
From these communications alone, a developer is responsible for constructing a system that "just works".
From these communications alone, a developer is responsible for constructing a system that “just works”. This is especially difficult for freelancers working outside the larger system.
Why does testing get cut?
There’s an obvious gap here: if the business owner has envisioned the system’s behaviors at the start, why is testing that these behaviors actually work often the step that gets cut?
The answer may be blindingly simple: tests are often not seen as shared capital; they are not thought of as having value to the project, because “they’re just for the engineers”, or similarly, providing value to a single one department or group of people.
How do we make tests this shared capital, this list of system behaviors? By embracing not only test-driven development (TDD), but behavior-driven development (BDD).
What is BDD?
Behavior-driven development should be focused on the business behaviors your code is implementing: the “why” behind the code. It supports a team-centric (especially cross-functional) workflow.
I’ve seen agile BDD work really well when a developer and either the Agile product owner or a business analyst sit down together and write pending specs (to be filled in later by the developer) in a plain text editor:
- The business person specifies behaviors they want to see in the system.
- The developer asks questions based on their understanding of the system, while also writing down additional behaviors needed from a development perspective.
Ideally, both parties can refer to the list of current system behaviors to see if this new feature will break existing features.
I’ve found this simple act gives me enough constraints that I’m able to think like a developer: “given that I have to implement these tests, how does that constrain me/everyone into specification I can implement in code”? Since they are pending specs, they’re fast and easy to write in the thick of collaboration.
This collaborative approach lets me focus on what the feature provides for the end user, and having the business person right there constrains me to talk about behavior, not implementation. This highlights the differences in BDD vs TDD.
Let’s see an example of Behavior-Driven Development
The scenario: You’re a developer on a team responsible for the company accounting system, implemented in Rails. One day, a business person asks you to implement a reminder system to remind clients of their pending invoices. Because you’re practicing BDD per this tutoria; (versus TDD), you sit down with that business person and start defining behaviors.
You open your text editor and start creating pending specs for the behaviors the business user wants:
This focus on behavior during development makes the test useful as verification that you’re building the right feature, not just that your code is correct. Note that the phrasing is in business language, not in the system’s internal implementation language. You don’t see or care that an invoice an account, because nobody outside the development team cares about that.
The phrasing is in business language, not the system's internal implementation language. You don't see or care that an invoice belongs_to an account, because nobody outside the dev team cares about that.
Some developers prefer to write test cases on the spot, calling methods in the system, setting up expectations, like so:
The test suite will fail because we’re yet to write the code to set the .
Vis-à-vis failing specs
I understand developers that write failing specs, but with the business person by my side, this has never worked for me. The wrong business person will either get distracted by the details or take this new knowledge and try to micromanage things that the developer knows more about (proper database design, code reuse).
In my experience, writing more than a one-line overview of a specific behavior will bore the business person. They’ll view it as a poor use of their time or grow anxious to describe the next behavior while it’s on their mind.
How does BDD differ from TDD?
Let’s look at this a different way, with a Test-Driven Development approach, and write out pending tests:
These tests are helpful, but only helpful to one group of people: engineers. BDD is useful for communicating with every member of a cross-functional product team.
You can certainly do test-first development while in a BDD mindset through the use of pending behaviors. First, write the test; then run it (red); then make it work (green); then make it right (refactor).
A lot of work in the BDD community has gone into making the assertion checks inside the test read like English. Here’s a stereotypical RSpec test:
This format makes things easier to read later on. But remember this is not what we’re doing here—the point is to get behaviors down as fast as possible—and enforce the principle of ‘one tested behavior per spec’. Ideally, the pending spec title should tell you what you’re testing.
BDD isn’t about fancy ways to validate your results; it’s about sharing expected behaviors across all members of the team.
Behavior-driven development is about collaboration & communication
Let’s step back into our scenario: working on the company accounting system.
You walk going through the item’s functionality with the business person, with you analyzing the system through its internals (how the objects fit together internally), and them analyzing the system from the outside.
You think of some conditions and ask the business analyst what happens in the following scenarios:
And you get answers. It’s important that the business person understand that you’re not trying to punch holes in their pet idea, or being overly pedantic.
In this way, Behavior-Driven Development is a tool to aid collaboration and start a conversation between the two departments. It’s also a way to clarify the scope of a desired feature and get better estimates from the dev team. Perhaps you realize that there’s no way to calculate 10 business days from a given point in time; that’s an additional, separate, feature you’ll need to implement.
Developers will have developer considerations (“What exactly do you mean when you say, ‘day’?”), while business people will have their own considerations (“Please don’t use the term overdue here, that means something different”). Having one group or the other go off and try to write these business logic behavior tests themselves (the promise of Cucumber) cuts out each side’s valuable input.
It’s also a good stand-in for when the Agile Client isn’t physically in the room anymore: to have their desires on paper, mixed with developer analysis (and translation) of what you’re building.
An earlier Toptal Blog post Chris Fox talks about design documents, especially at the beginning of a project. Understanding and extracting the business behaviors scales down from projects where the system is somewhat knowable, to those that require decades of programmer-years to accomplish and have hundreds or thousands of behavioral specs.
Chris’s article also mentions on-screen behaviors of elements, and this is an area where I’m constantly at odds with designers: “What does this button look like when it’s dim” or, “How does this look on 11” screens, because this page is obviously designed for 24” screens?” This back-and-forth with the business person can find gaps in the graphics assets of a project or layout of a page.
In very large cross-functional teams, there are many team members with their own concerns: designers, developers, potentially someone from operations, the database administrator—perhaps QA people (yes, there’s a place for everyone in TDD and BDD!), each with their own concerns and questions. BDD can drive this collaboration more than test-driven development does. From “what happens when the data is too big for this table?” to, “Hmmm, that’ll be an expensive query, we’ll want to cache that somehow” to, “Wait, should the user see all of that confidential information?”, there may be more at stake than just a developer and a business analyst with questions about this new feature
Behavior-driven development is about shared artifacts
What is a shared artifact?
I like to think of “artifacts” in software engineering as potentially physical things that describe the project or the project team, and which are findable six months down the line. Good artifacts explain why things are the way they are.
Good artifacts explain why things are the way they are. An artifact is some source code saved to a repository or shared space, or tickets in the ticket system.
Hallway conversations aren’t artifacts. Nor are whiteboard drawings. Whiteboard drawings that get turned into big long class documentations or design documents—these are artifacts. Minutes from meetings are artifacts too.
An artifact is some source code saved to a repository or shared space, and tickets in the ticket system, or notes on the internal Wiki—or even persistent chat logs.
Shared artifacts are, in my mind, the best artifacts. They show not just why something is the way it is, but why it exists in the app at all.
How do you use them in BDD?
Behaviors should be a shared team artifact—tests should not just be busy-work for programmers! While it’s best to have a system in which the entire team can easily view the current specs (perhaps the deployment system also extracts and saves the list of behaviors to a private area of the site or a wiki), you could also do it manually every sprint.
The name of the game is “help developers create the specs we need to deliver business value quicker, collaborate interdepartmentally, and make better estimates”.
This company-wide understanding of what the system does is a form of capital too. It’s the “why” to the code’s “how”.
How do we solve the problem of buggy software being delivered to customers? By making sure that testing is not seen as something “only the developers care about”.
Describing and understanding the needs of a system has a ton of benefits beyond code correctness: establishing inter-departmental dialog and making sure all stakeholders’ concerns are met (and not just the stakeholders with big fancy titles). Using behavior-driven development to understand these needs from the start and testing external business behaviors that the entire team cares about—that is a great way to ensure a quality project.
About the author
member since October 3, 2011
Mac OSAWS OpsWorksObjective-CPythonRuby on Rails (RoR)CocoaRubyGit+ more
Hiring? Meet the Top 10 Freelance Developers for Hire in March 2018