8. Let’s talk about...
• Things we’ll cover in this talk:
1. What is BDD?
2. Why you should care
3. How to start doing BDD with cucumber
9. So, what is BDD?
• Behavior Driven Development (BDD) is a
software development methodology that
takes an outside-in approach to describe
application behavior by encouraging intense
customer involvement
• Don’t worry, we’ll take this explanation
from textbook to tolerable over the next
20-ish minutes...
10. So, what is BDD?
• BDD borrows it’s core concepts,
workflow and principles from it’s
predecessor, Test Driven Development
15. Well then what’s TDD?!
• TDD == Write tests first, production
code second
16. Well then what’s TDD?!
• TDD == Write tests first, production
code second
• You’re TAFT, right!?
17. Well then what’s TDD?!
• TDD == Write tests first, production
code second
• You’re TAFT, right!?
• Main idea: Use test code to drive
production code
18. Well then what’s TDD?!
• TDD == Write tests first, production
code second
• You’re TAFT, right!?
• Main idea: Use test code to drive
production code
• More on this later...
24. Well then what’s TDD?!
• TDD/BDD Workflow
• Red, Green, Refactor
1. Write a failing test
25. Well then what’s TDD?!
• TDD/BDD Workflow
• Red, Green, Refactor
1. Write a failing test
2. Write the smallest amount of production
code possible to get that test to pass
26. Well then what’s TDD?!
• TDD/BDD Workflow
• Red, Green, Refactor
1. Write a failing test
2. Write the smallest amount of production
code possible to get that test to pass
3. Refactor
27. Well then what’s TDD?!
• TDD/BDD Workflow
• Red, Green, Refactor
1. Write a failing test
2. Write the smallest amount of production
code possible to get that test to pass
3. Refactor
• i.e. add more tests and write better
production code
32. THINK, MAN, THINK!
• The real TDD/BDD Workflow
• THINK, Red, Green, Refactor
33. THINK, MAN, THINK!
• The real TDD/BDD Workflow
• THINK, Red, Green, Refactor
• Thinking is like, really important
34. THINK, MAN, THINK!
• The real TDD/BDD Workflow
• THINK, Red, Green, Refactor
• Thinking is like, really important
• It’s easy to forget to think when you
can just start hacking L337 c0D3Z
35. THINK, MAN, THINK!
• The real TDD/BDD Workflow
• THINK, Red, Green, Refactor
• Thinking is like, really important
• It’s easy to forget to think when you
can just start hacking L337 c0D3Z
36. THINK, MAN, THINK!
k !!
h in
t
t to
ge
n ’t
for • The real TDD/BDD Workflow
D o
• THINK, Red, Green, Refactor
• Thinking is like, really important
• It’s easy to forget to think when you
can just start hacking L337 c0D3Z
37. THINK, MAN, THINK!
k !!
h in
t
t to
ge
n ’t
for • The real TDD/BDD Workflow
D o
• THINK, Red, Green, Refactor
• Thinking is like, really important
• It’s easy to forget to think when you
can just start hacking L337 c0D3Z
39. Problem: Thinking is
HARD.
• Unfortunately, TDD, and the nature of
traditional TDD tools often make it harder
to think about what you’re trying to do.
41. BDD Picks up where
TDD leaves off
• TDD defines a really awesome workflow
(think, red, green, refactor)
42. BDD Picks up where
TDD leaves off
• TDD defines a really awesome workflow
(think, red, green, refactor)
• BDD crystallizes some of the things that
TDD leaves unclear or undefined.
43. BDD Picks up where
TDD leaves off
• TDD defines a really awesome workflow
(think, red, green, refactor)
• BDD crystallizes some of the things that
TDD leaves unclear or undefined.
• BDD == TDD 2.0
44. BDD Picks up where
TDD leaves off
• TDD defines a really awesome workflow
(think, red, green, refactor)
• BDD crystallizes some of the things that
TDD leaves unclear or undefined.
• BDD == TDD 2.0
• BDD bridges the gap between specs/
requirements and actual implementation
46. BDD Picks up where
TDD leaves off
• Programmer goals and priorities are more
clearly aligned with requirements
47. BDD Picks up where
TDD leaves off
• Programmer goals and priorities are more
clearly aligned with requirements
• Why??
48. BDD Picks up where
TDD leaves off
• Programmer goals and priorities are more
clearly aligned with requirements
• Why??
• BDD is implemented in business language
not programmer pig latin
52. Come to think of it...
• In doing this whole TDD/BDD thing, what
exactly are we trying to do?
53. Come to think of it...
• In doing this whole TDD/BDD thing, what
exactly are we trying to do?
• Test code?
54. Come to think of it...
• In doing this whole TDD/BDD thing, what
exactly are we trying to do?
• Test code?
• Describe behavior?
55. Come to think of it...
• In doing this whole TDD/BDD thing, what
exactly are we trying to do?
• Test code?
• Describe behavior?
• Bill hours?
56. Come to think of it...
• In doing this whole TDD/BDD thing, what
exactly are we trying to do?
• Test code?
• Describe behavior?
• Bill hours?
• Bawl like ca$h money millionaires?
57. Come to think of it...
• In doing this whole TDD/BDD thing, what
exactly are we trying to do?
• Test code?
• Describe behavior?
• Bill hours?
• Bawl like ca$h money millionaires?
59. Come to think of it...
• In doing this whole TDD/BDD thing, what
are we “trying to do?”
• Test code?
• Describe behavior?
• Bill hours?
• Bawl like ca$h money millionaires?
60. Come to think of it...
• In doing this whole TDD/BDD thing, what
are we “trying to do?”
How bout both,
• Test code? AT THE SAME TIME!?
• Describe behavior?
• Bill hours?
• Bawl like ca$h money millionaires?
61. Come to think of it...
• In doing this whole TDD/BDD thing, what
are we “trying to do?”
How bout both,
• Test code? AT THE SAME TIME!?
• Describe behavior?
• Bill hours?
• Bawl like ca$h money millionaires?
62. Come to think of it...
• In doing this whole TDD/BDD thing, what
are we “trying to do?”
How bout both,
• Test code? AT THE SAME TIME!?
• Describe behavior?
• Bill hours?
• Bawl like ca$h money millionaires?
64. Double-whammy
• We can describe the behavior we want first,
and through that process, we drill down into
lower level unit and functional tests for our
code.
65. Double-whammy
• We can describe the behavior we want first,
and through that process, we drill down into
lower level unit and functional tests for our
code.
• What’s the point of testing code before we
pin down what that code should do?
66. Double-whammy
• We can describe the behavior we want first,
and through that process, we drill down into
lower level unit and functional tests for our
code.
• What’s the point of testing code before we
pin down what that code should do?
• In other words, we need to define the
behavior we want/expect before we
go about testing it.
67. Dig deeper: What’s the goal of
“testing” code?
• Is it to test code or describe behavior?? Both.
• TDD is about ensuring behavior.
• BDD is about describing behavior.
• First we describe the behavior, then we
ensure that behavior works as expected.
69. The Fallacy of TDD
• Simply writing tests doesn’t necessarily
yield any value
70. The Fallacy of TDD
• Simply writing tests doesn’t necessarily
yield any value
• assert_equal(1, 1) # == true
71. The Fallacy of TDD
• Simply writing tests doesn’t necessarily
yield any value
• assert_equal(1, 1) # == true
• To be useful, our tests must have meaning,
and that requires:
72. The Fallacy of TDD
• Simply writing tests doesn’t necessarily
yield any value
• assert_equal(1, 1) # == true
• To be useful, our tests must have meaning,
and that requires:
1. Listening to our customers.
73. The Fallacy of TDD
• Simply writing tests doesn’t necessarily
yield any value
• assert_equal(1, 1) # == true
• To be useful, our tests must have meaning,
and that requires:
1. Listening to our customers.
2. Thinking. Hard.
76. Problems with TDD
1. Unit and functional tests are exclusive
to the “programmer domain”
77. Problems with TDD
1. Unit and functional tests are exclusive
to the “programmer domain”
• Bad for agile because we lose the
customer-centric nature of agile at
this point in the process
78. Problems with TDD
1. Unit and functional tests are exclusive
to the “programmer domain”
• Bad for agile because we lose the
customer-centric nature of agile at
this point in the process
• Agile encourages deep customer
involvement and interaction (as
opposed to pre-defined
requirements gathering phase)
79. Problems with TDD
1. Unit and functional tests are exclusive
to the “programmer domain”
• Bad for agile because we lose the
customer-centric nature of agile at
this point in the process
• Agile encourages deep customer
involvement and interaction (as
opposed to pre-defined
requirements gathering phase)
• This breaks down when
programmers start writing
tests in programmer
language
82. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
83. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
84. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
• Good:
85. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
• Good:
• Tests run faster
86. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
• Good:
• Tests run faster
• Tests are less brittle because not dependent on other
parts of app
87. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
• Good:
• Tests run faster
• Tests are less brittle because not dependent on other
parts of app
• Rarely the case with web apps
88. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
• Good:
• Tests run faster
• Tests are less brittle because not dependent on other
parts of app
• Rarely the case with web apps
• Bad:
89. Problems with TDD
2. TDD tends to be associated with isolated tests
• Unit and functional tests as opposed to integration tests
• This is both good and bad (mostly bad though)
• Good:
• Tests run faster
• Tests are less brittle because not dependent on other
parts of app
• Rarely the case with web apps
• Bad:
• Tests become brittle due to excessive state setup (see
next slide)
91. Problems with TDD
3. Writing isolated tests can feel contrived
(again, especially in web apps), which often
produces crappy test code, which results in
crappier production code
92. Problems with TDD
3. Writing isolated tests can feel contrived
(again, especially in web apps), which often
produces crappy test code, which results in
crappier production code
• Typically happens when we have
complex state setup (like a web app)
93. Problems with TDD
3. Writing isolated tests can feel contrived
(again, especially in web apps), which often
produces crappy test code, which results in
crappier production code
• Typically happens when we have
complex state setup (like a web app)
• Secondary problem: This “contrived-
ness” pushes devs away from testing
altogether, which is even worse.
96. Problems with TDD
4. A lot gets lost in translation due to these
problems
• Trying to translate customer
conversations into test code is hard as it is
97. Problems with TDD
4. A lot gets lost in translation due to these
problems
• Trying to translate customer
conversations into test code is hard as it is
• Trying to overcome the frustration of
writing seemingly contrived test cases
makes it even harder
98. Problems with TDD
4. A lot gets lost in translation due to these
problems
• Trying to translate customer
conversations into test code is hard as it is
• Trying to overcome the frustration of
writing seemingly contrived test cases
makes it even harder
• Frustration from testing leads to loss of
focus and decreased productivity
102. BDD
• BDD takes an outside-in approach
• Starts at the user level, rather than programmer
103. BDD
• BDD takes an outside-in approach
• Starts at the user level, rather than programmer
• In short, it’s a different way of thinking about and doing TDD
104. BDD
• BDD takes an outside-in approach
• Starts at the user level, rather than programmer
• In short, it’s a different way of thinking about and doing TDD
• Caveat
105. BDD
• BDD takes an outside-in approach
• Starts at the user level, rather than programmer
• In short, it’s a different way of thinking about and doing TDD
• Caveat
• Technically, we could adapt our TDD tools to serve a
BDD-like role, but we’ll still run into the problems
just mentioned
110. Sweet BDD Diagram.
Customer
requireme
nts
Cu
s
to
me
rr
eq
uir
em
en
ts
Custom
er requi
rements
111. Sweet BDD Diagram.
Customer
requireme
nts
Cu
s
to
me
rr
eq
uir
em
en
ts
n ts
e
em
quir
r re
e
m
s to
Custom Cu
er requi
rements
112. Sweet BDD Diagram.
Customer
requireme
nts
Cu
BDD (integration tests)
s
to
me
rr
eq
uir
em
en
ts
n ts
e
em
quir
r re
e
m
s to
Custom Cu
er requi
rements
113. Sweet BDD Diagram.
Customer
requireme
nts
Cu
BDD (integration tests)
s
to
me
rr
eq
uir
em
en
ts
n ts
e
em
quir
BDD (integration tests) re
e r
m
s to
Custom Cu
er requi
rements
114. Sweet BDD Diagram.
Customer
requireme
nts
Cu
BDD (integration tests)
s
to
me
rr
eq
uir
em
TDD (unit/functional
en
tests)
ts
n ts
e
em
quir
BDD (integration tests) re
e r
m
s to
Custom Cu
er requi
rements
115. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
em
TDD (unit/functional
en
tests)
ts
n ts
e
em
quir
BDD (integration tests) re
e r
m
s to
Custom Cu
er requi
rements
116. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
By now you might be
em
TDD (unit/functional
thinking, “Aren’t
en
tests)
these just integration
ts
n ts
tests showed through e
em
a totally awesome
quir
diagram?” BDD (integration tests) re
e r
m
s to
Custom Cu
er requi
rements
117. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
By now you might be
em
TDD (unit/functional
thinking, “Aren’t
en
tests)
these just integration
ts
n ts
tests showed through e
em
a totally awesome
quir
diagram?” BDD (integration tests) re
e r
m
Yes. s to
Custom Cu
er requi
rements
118. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
By now you might be
em
TDD (unit/functional
thinking, “Aren’t
en
tests)
these just integration
ts
n ts
tests showed through e
em
a totally awesome
quir
diagram?” BDD (integration tests) re
e r
m
Yes. s to
Custom Cu
er requi
rements
119. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
By now you might be
em
TDD (unit/functional
thinking, “Aren’t
en
tests)
these just integration
ts
n ts
tests showed through e
em
a totally awesome
quir
diagram?” BDD (integration tests) re
e r
m
Yes. s to
Custom Cu
er requi
rements
120. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
By now you might be
em
TDD (unit/functional
thinking, “Aren’t
en
tests)
these just integration
ts
n ts
tests showed through e
em
a totally awesome
quir
diagram?” BDD (integration tests) re
e r
m
Yes. s to
Custom Cu
er requi
rements
121. Sweet BDD Diagram.
Customer
We start at the requireme
nts
outside and drill
down, inwards
Cu
towards unit and BDD (integration tests)
s
to
functional tests
me
rr
eq
uir
By now you might be
em
TDD (unit/functional
thinking, “Aren’t
en
tests)
these just integration
ts
n ts
tests showed through e
em
a totally awesome
quir
diagram?” BDD (integration tests) re
e r
m
Yes. s to
Custom Cu
er requi
rements
122. Dig deeper: What’s the point of
testing code?
• Is it to test code or describe behavior??
123. Dig deeper: What’s the point of
testing code?
• Is it to test code or describe behavior?? Both.
124. Workflow
• Describe code with cucumber integration tests
• Use Red, Green, Refactor
• As you go through this process, write unit and
functional tests along the way
126. Sample Cucumber Feature
Feature: User login
Scenario: A registered user attempts to login
Given I am a registered user with login "ajsharp" and password "secret"
When I go to the user login page
And I fill in "Login" with "ajsharp"
And I fill in "Password" with "secret"
And I click the "Log In" button
Then I should be redirected to my profile page
And I should see "ajsharp's profile"
129. Sample Cucumber Feature
Feature: User login
Scenario: A registered user attempts to login
Given I am a registered user with login "ajsharp" and password "secret"
BDD Outside-in Workflow
• Cucumber feature
130. Sample Cucumber Feature
Feature: User login
Scenario: A registered user attempts to login
Given I am a registered user with login "ajsharp" and password "secret"
BDD Outside-in Workflow
• Cucumber feature
131. Sample Cucumber Feature
Feature: User login
Scenario: A registered user attempts to login
Given I am a registered user with login "ajsharp" and password "secret"
BDD Outside-in Workflow
• Cucumber feature
132. Sample Cucumber Feature
Feature: User login
Scenario: A registered user attempts to login
Given I am a registered user with login "ajsharp" and password "secret"
BDD Outside-in Workflow
• Cucumber feature
From here, cucumber looks “step definition” files that match (via
regular expressions -- shout out Perl) the statements in
your .feature file.
133. Sample Cucumber Feature
BDD Outside-in Workflow
• Cucumber feature
From here, cucumber looks “step definition” files that match (via
regular expressions -- shout out Perl) the statements in
your .feature file.
134. Sample Cucumber Feature
BDD Outside-in Workflow
• Cucumber feature
From here, cucumber looks “step definition” files that match (via
regular expressions -- shout out Perl) the statements in
your .feature file.
Next Step: Write a failing test
137. Cucumber step definition file
Given /^I am a registered user with username "(.+)" and password "(.+)"$/ do |login, pass|
@user = User.create!(:username => login, :password => pass)
end
BDD Outside-in Workflow
• Cucumber feature
• Step Definition
138. Cucumber step definition file
Given /^I am a registered user with username "(.+)" and password "(.+)"$/ do |login, pass|
@user = User.create!(:username => login, :password => pass)
end
BDD Outside-in Workflow
• Cucumber feature
• Step Definition
We haven’t implemented the User model yet, so let’s do that....
139. Cucumber step definition file
Given /^I am a registered user with username "(.+)" and password "(.+)"$/ do |login, pass|
@user = User.create!(:username => login, :password => pass)
end
BDD Outside-in Workflow
• Cucumber feature
• Step Definition
We haven’t implemented the User model yet, so let’s do that....
But wait!! To implement the User model, we need to write some
unit tests for it....Red, Green, Refactor
140. Cucumber step definition file
Given /^I am a registered user with username "(.+)" and password "(.+)"$/ do |login, pass|
@user = User.create!(:username => login, :password => pass)
end
BDD Outside-in Workflow
• Cucumber feature
• Step Definition
We haven’t implemented the User model yet, so let’s do that....
But wait!! To implement the User model, we need to write some
unit tests for it....Red, Green, Refactor
Next Step: Green - To make the cucumber step pass (higher level, more outside) we need to
do Red - write failing tests for user model (lower level, more inside)
142. User Model Unit Test
(or spec, in this case)
describe User do
it { should validate_presence_of :username }
it { should validate_presence_of :password }
end
143. User Model Unit Test
(or spec, in this case)
describe User do BDD Outside-in Workflow
it { should validate_presence_of :username }
it { should validate_presence_of :password } • Cucumber feature
end • Step Definition
• User model unit test/spec
144. User Model Unit Test
(or spec, in this case)
describe User do BDD Outside-in Workflow
it { should validate_presence_of :username }
it { should validate_presence_of :password } • Cucumber feature
end • Step Definition
• User model unit test/spec
145. User Model Unit Test
(or spec, in this case)
describe User do BDD Outside-in Workflow
it { should validate_presence_of :username }
it { should validate_presence_of :password } • Cucumber feature
end • Step Definition
• User model unit test/spec
This will fail, because we haven’t written any production code yet
146. User Model Unit Test
(or spec, in this case)
describe User do BDD Outside-in Workflow
it { should validate_presence_of :username }
it { should validate_presence_of :password } • Cucumber feature
end • Step Definition
• User model unit test/spec
This will fail, because we haven’t written any production code yet
Next Step: Green - Make our model unit tests
pass by writing some production code
147. User Model Unit Test
(or spec, in this case)
class User < ActiveRecord::Base
validates_presence_of :username
validates_presence_of :password
end
148. User Model Unit Test
(or spec, in this case)
class User < ActiveRecord::Base
validates_presence_of :username BDD Outside-in Workflow
validates_presence_of :password
end • Cucumber feature
• Step Definition
• User model unit test/spec
• User model production code
149. User Model Unit Test
(or spec, in this case)
class User < ActiveRecord::Base
validates_presence_of :username BDD Outside-in Workflow
validates_presence_of :password
end • Cucumber feature
• Step Definition
• User model unit test/spec
• User model production code
150. User Model Unit Test
(or spec, in this case)
class User < ActiveRecord::Base
validates_presence_of :username BDD Outside-in Workflow
validates_presence_of :password
end • Cucumber feature
• Step Definition
• User model unit test/spec
• User model production code
This will make our unit tests pass. Nice.
151. User Model Unit Test
(or spec, in this case)
class User < ActiveRecord::Base
validates_presence_of :username BDD Outside-in Workflow
validates_presence_of :password
end • Cucumber feature
• Step Definition
• User model unit test/spec
• User model production code
This will make our unit tests pass. Nice.
“Bubble up” back to the cucumber .feature as our
unit/functional tests pass
152. Awesome workflow
• This workflow keeps us focused on building
business value in our code for our
customers
• i.e. customer requirements
153. Resources
• BDD
• http://behaviour-driven.org/
• Cucumber
• http://cukes.info
• http://github.com/aslakhellesoy/cucumber
• Rspec Beta Book
• http://pragprog.com/titles/achbd/the-rspec-
book
154. Resources
• My Blog
• http://alexjsharp.com
• I’ll post these slides there
• My github account
• http://github.com/ajsharp
• Questions?
• ajsharp@frothlogic.com