Download - Why BDD is our BFF
Matt DaubertMeYou Health@mdaubs83
TDD is about code design
“It’s harder to read code than to write it.”
- Joel Spolsky
“Agile processes harness change”
- 2nd Principle, Agile Manifesto
“No matter how slow you are writing clean code, you will always be slower if you
make a mess.”- Uncle Bob Martin
TDD does not address...
Which test do I need to write next?
Starting point.
How do I know when I’ve written the last test?
Definition of done.
How does this new code add value for the user?
Am I writing the right code?
BDD
TDD
Unit test
Code to pass test
Refactor
Scenario
“If you can’t explain it simply, you don’t understand it well
enough.”- Albert Einstein
Developingacceptancetests
Implementingacceptance
tests
Successful products provide value to users.
Users derive value by interacting with products.
Interactions are testable.
Two sides to every (user) story
Narrative- User/persona/role- Goal or value the user would like to achieve- The interaction the user should have with the product in order to achieve their goal and gain value
Acceptance Criteria- Multiple concrete examples describing how the feature works
Our goals, user goals
Scope
Specification
Key Examples
Acceptance Test
Living Documentation
Dom
ain Language
Shared U
nderstandingincreasing
Ain't Nobody Got Time For That
Refining User Stories
- Stories are refined through collaboration
- Stories may divide if they get complex
- Stories will often start with a small number of key examples and expand as shared understanding develops
- Refinement is complete when a story passes the "INVEST" test.
INVEST in User Stories
INVEST in User Stories
IndependentCan be scheduled and re-prioritized with minimal risk of being blocked.
INVEST in User Stories
IndependentNegotiableCan be changed or discarded if business, market, or technical needs require.
INVEST in User Stories
IndependentNegotiableValuableStories that don't add value for users will never see a return on investment.
INVEST in User Stories
IndependentNegotiableValuableEstimableA reasonable idea of effort required to complete is needed to pace the sprint.
INVEST in User Stories
IndependentNegotiableValuableEstimableSmallQuicker to implement, minimize risk, get feedback sooner.
INVEST in User Stories
IndependentNegotiableValuableEstimableSmallTestableA story isn't considered done until its acceptance tests pass.
What is an acceptance test?
● Executable version of a refined user story
● Written in domain language
● Scenarios validate story acceptance criteria
● Defines start and finish lines
● Documents value proposition
● Respects "Three Levels of Description"
Three Levels of Description
Business RuleWhat is the scenario demonstrating?
Scenario: Free delivery is offered to customers who order two or more books
Three Levels of Description
Business RuleWhat is the scenario demonstrating?
User WorkflowHow can a user exercise the functionality?
Given I put two books in my cart
When I checkout
Then I should be able to select free delivery
Three Levels of Description
Business RuleWhat is the scenario demonstrating?
User WorkflowHow can a user exercise the functionality?
Technical ActivityWhat are the technical steps required to exercise each workflow step?
step 'I checkout' do
click_on 'Checkout'
end
Protips(Lightning Round)
Disambiguate w/Concrete ExamplesScenario Outline: Users cannot sign in after the sixth failed sign in attempt over a one
day period
Given I have failed to sign in <yesterday> times yesterday
And I have failed to sign in <today> times today
Then I should be <result> to sign in
Examples:
| yesterday | today | result |
| 0 | 0 | able |
| 0 | 5 | able |
| 0 | 6 | unable |
| 5 | 0 | able |
| 5 | 5 | able |
| 5 | 6 | unable |
| 6 | 0 | able |
| 6 | 5 | able |
| 6 | 6 | unable |
Gherkin Protip: Hide Implementation
Scenario: Selected customers are notified of a flash sale
Given I am a store manager
When I create a flash sale for VIP customers that starts tomorrow
And it’s tomorrow
And Resque jobs are run
Then VIP customers receive a Flashmail
Gherkin Protip: Hide Implementation
Scenario: Selected customers are notified of a flash sale
Given I am a store manager
When I create a flash sale for VIP customers
Then VIP customers receive a Flashmail the day of the flash
Gherkin Protip: Don’t Write Scripts
As a party planner with BFFs
In order to have the best party ever
I want to invite as many BFFs as possible
Given there is a user named Alice
And there is a user named Bob who is BFFs with Alice
And there is a user named Charlie who is BFFs with Bob
When Alice invites Bob to a party
But Alice does not invite Charlie to the same party
Then Alice receives a message
"Do you also want to invite Charlie?"
Gherkin Protip: Don’t Write Scripts
As a party planner with BFFs
In order to have the best party ever
I want to invite as many BFFs as possible
Given I am planning a party
When I invite my BFF Bob
Then I am asked if I might want to invite his BFF Charlie
Gherkin Protip:
Be skeptical of "I should see" stepsIs the act of seeing the thing valuable to the user or is it an implementation detail?
YesThen I should see that the patron has overdue books
NoThen I should see the overdue book icon
Gherkin Protips:
Be skeptical of "And" and “But” keywordsAre these steps really one step?Are these steps not focused on the feature?Is this feature really two features?
Be skeptical of "and" and "or" in stepsIs this step really two steps?Is this scenario really two scenarios?
Gherkin Protips:
Don't test every caseAdd examples to disambiguate around edge cases
Never use generic steps to DRY testsDRY Ruby code behind the steps
Listen when your Gherkin fights youCan you explain the feature in simple terms?
Use ctags - Never Grep for Steps
● Open a .feature file
● Move cursor to a scenario step
● Press Ctrl+] to open the step definition
● Press Ctrl+t to go back to the .feature file
Step Definitions# Gherkin
When I sign up with "[email protected]" and "password"
# Cucumber step definition
When /^I sign up (?:with|as) "(.*)" and "(.*)"$/ do |email, pw|
# More Ruby code here
end
# Turnip step definition
step "I sign up with/as :email and :password" do |email, pw|
# More Ruby code here
end
Use Custom Placeholdersstep "there are :count monsters" do |count|
count.times { Monster.new(name) }
end
placeholder :count do
match /\d+/, &:to_i # { |count| count.to_i }
match /no/ { 0 }
end
(or use Step Argument Transforms in Cucumber)
Use Helper Methods
module MyAccountSteps
step 'I am modifying my AwesomeApp account' do
sign_in @user = create(:user)
select_from_user_drop_down 'My account'
end
end
Organize Your Suite
spec|- acceptance |- features |- encouragement.feature |- macros |- session_macros.rb
|- steps |- encouragement_steps.rb
Every product and team is different, optimize for yours.
Thanks!
Matt DaubertMeYou Health@mdaubs83
Learn from smart peoplehttp://alindeman.github.io/acceptance_testing
http://blog.carbonfive.com/2012/02/14/beginning-outside-in-rails-development-with-cucumber-and-rspec/
http://en.wikipedia.org/wiki/INVEST_(mnemonic)
http://specificationbyexample.com/
http://janetgregory.blogspot.com/2010/08/atdd-vs-bdd-vs-specification-by-example.html
http://www.drdobbs.com/tdd-is-about-design-not-testing/229218691