Behaviour Driven Development With NBehave

Behaviour Driven Development
With NBehave
Linking User Stories and Domain Driven Design to Testing
David Ross
W: www.pebblesteps.com
E: [email protected]
Behavior Driven Development
Tools and techniques
Talk overview
• What is BDD and how to use NBehave
Topics
• What are high quality requirements?
• Top down and Bottom up Testing
• NBehave
• Using library
• Using the test runner
• Top down design with Rhino.Mocks and Nbehave
• Acceptance testing
Behavior Driven Development
Analysis/Design Methodology by Dan
North
Response to:
– confusion about Test Driven Development and
Test First Development
– Lack of rigor around User Stories (Requirements)
– Projects that generate documentation out of Unit
tests
Culminated in:
– the BDD method for writing User Stories
– JBehave unit testing framework
Behavior Driven Development
BDD is not:
• a testing framework or style of testing
• a method for writing tests
BDD is:
• A formalised template for User Stories
• Able to create testable User Stories since they
are defined in a formal manner
• Promotes “security” to a first call citizen in the
analysis process
Simple Trading application
Excel spreadsheet replacement
Simple Trading application
Requirements
• Allow Portfolio Manager to decide the
percentage split between Cash, Property
and Stock within the Portfolio
• Inform the Trader when the Portfolio needs
to be rebalanced (ie split in the pie has
changed significantly)
• Allow Operations to standardise Portfolio
names
Test First Development
Small steps
Red - Analysis/Design Hat
• Create a test that defines the expected outcome
• Asking "What I want is...“
Green - Creative Hat (Fun part)
• Experiment/Prototype/Build until the test passes
Refactor - Engineering
• Refactor, refactor, refactor
Red
Green
Refactor
Test First Development
How easy is it to use TFD for the following
Requirement/Story
•Value = Units * Market Price
•Increase the performance of the User Security
module by automatically caching the user’s
manager Id
•The system must email the Portfolio manager
when the Portfolio needs to be rebalanced
•Build a web site so that customers can see the
performance of the portfolio
Test First Development
Do you feel guilty??
•Do you write a Failing unit test before
every piece of code?
•Do you write a line of Unit Test code for
EVERY line of production code?
Behavior Driven
How do you write a test when you don’t
know where you are going?
Maybe we need requirements that are easy
to write tests for?
Requirements
What are they
•Describes what a system should do but
not how it will be done
•Contract between the implementation
team and the analysis team
•Audience is typically the stake holders
and not the development team
Requirements
Precise and clear over verbose
We want requirements that
• Can be tested!!!
• Are attainable!!!
• Are traceable into code!!!
Requirements Gathering
BDD merges two different approaches
User Stories
•Short one or two line statement that maps to
a few days of development work
•Highly focused
Domain Driven Design
•Ubiquitous language – Ensure business
terminology permeates into code
•Clear single definition (within the project) for
each business concept - Account has a single
meaning
BDD User Stories
Formal template for User Stories
Story Template
As a [User/Role]
I want [Behaviour]
so that [I receive benefit]
Example
As a “Operations staff member”
I want “To create a Portfolio”
so that “So that it can be traded”
BDD User Stories
Formal template for User Stories
Scenario Template
Given some initial context (the givens),
When an event occurs,
then ensure some outcomes.
Example
Given “New portfolio is called Balanced
Fund”
When “Portfolio already exists”
then “Portfolio can not be created”
NBehave
What is it?
• .NET Library for writing automated BDD style tests
• Fluent syntax for building up a BDD Style User
Stories
• Test runner that executes the stories and
generates a report listing the contents of the
stories
• BSD License
Creating a BDD Theme
Collection of related stories
[Theme("Portfolio Maintenance")]
public class PortfolioMaintenanceStory
{
[Story]
public void portfolio_create_story () { ... }
[Story]
public void portfolio_delete_story() { ... }
}
Reference: NBehave.Narrator.Framework.dll
Creating a Story
Fluent interface to define the story
var story = new Story("Create portfolio");
story.AsA(“Operations team member")
.IWant("To create a new portfolio on behalf of a
portfolio manager")
.SoThat("the portfolio manager can configure
the portfolio and the front office can trade");
Creating a Scenario
Fluent interface to define the story
story.WithScenario("portfolio does not exist")
.Given("portfolio name is $name", "Aggressive
Fund")
.When("portfolio does not exist in the database")
.Then("new portfolio should be created");
story.WithScenario("portfolio already exists")
.Given("portfolio name is $name", "Aggressive Fund")
.When("portfolio already exists in database")
.Then("an error should occur");
Executing the test
With NBehave runner or mbUnit
• Ouch we get an error???
• The scenario throws an exception – NBehave isn’t
validating any code
• Use Pending
story.WithScenario("portfolio does not exist")
.Pending("In progress")
.Given("portfolio name is $name", "Aggressive Fund")
.When("portfolio does not exist in the database")
.Then("new portfolio should be created");
Behavior Driven Development
Across the Project (Story) Life Cycle
1.
2.
3.
4.
5.
Story
Pending Scenario
Stubbed Behavior Cycle (Red, Green, Refactor)
Real Behavior Cycle (Red, Green, Refactor)
Acceptance Test
Story
Pending
Scenario
Stubbed
Scenario
Real
Behaviour
Acceptance
Test
Stubbing out the behavior
With NBehave and Rhino.Mocks
Steps to generate an API
1. Go through the User story and find all the
domain objects
2. Create a class for each domain object but
don’t add state
3. Go through the User story and create a
find all the services that are required
(Repositories etc)
4. Create an interface for each service but
don’t add any methods
Stubbing out the behavior
With NBehave and Mocking
Steps to generate the API continued...
5. Slowly implement the story
6. Add domain object properties as required
7. Add methods signatures as required
8. Use Stubs to explore Inputs/Outputs to the
methods
Stubbing example
Create a new portfolio story
string portfolioName = "";
Portfolio p = null;
var portfolioRepository =
MockRepository.GenerateStub<IPortfolioRepository>();
var portfolioService = MockRepository.GenerateStub<IPortfolioService>();
s.WithScenario("portfolio already exists")
.Given("portfolio name is $name", "Aggressive Fund", n => {
portfolioName = n;
p = new Portfolio { Name = portfolioName };
portfolioRepository.
Stub(x => x.FindPortfolioByName(portfolioName)).Return(p);
portfolioService.
Stub(X => X.CreatePortfolio(p)).Throw(new
ItemExistsException());
})
Stubbing example
Create a new portfolio story
.When("portfolio already exists in database",
() => Assert.IsNotNull(
portfolioRepository.FindPortfolioByName(portfolioNa
me))
)
.Then("new portfolio create should fail",
() => Assert.Throws<ItemExistsException>(() =>
portfolioService.CreatePortfolio(p))
);
TFD/BDD Comparison
Test First
Behavior Driven
• Bottom Up
approach
• Lots of little steps
working towards a
solution
• Top down approach
• Design starting with
interfaces (using
stubs)
• Back fill with code
later
Output
• Tests
Output
• API creation
Test Driven Development
Development/Testing Phases
Stubs
Domain
Model
User Stories
Behaviour Driven
Development
GUI Testing
Fitness
User
Acceptance
Test
Deployment
Verification
Test
Unit &
Component
Test
System
Integration
Test
Mocks
Implemented
Behaviour
No
Mocks
/Stubs
User Acceptance Test
NBehave
– test cases are compiled
– Must be created by developers or technical
testers
– Are created at the start of the project
Fitnesse
– User Acceptance tests are Wiki based and so
are dynamic
– Can be created by end users and business
analysts
– Can be created at the start of the project
– But are only “implemented” by the
development late in the SDLC
NBehave specific features
What else is in NBehave?
Fixtures to Specifications
Loosing Assert from tests. Easier to read?
For BAs, yes...
Assert.IsTrue(component.IsValid)
component.IsValid.ShouldBeTrue()
Assert.Contains(s, “hello world”);
s.ShouldContains(“hello world”);
NBehave contains extension methods for NUnit, mbUnit,
xUnit
Fixtures to Specifications
Is it necessary? Using Namespace Alias
[TestFixture]
[Test]
[Context]
[Specification]
[Context]
public class When_using_tokenized_stories
{
[Specification]
public void should_replace_token_with_value()
{}
Stories for BDD. Specifications for focused
tests.
The word Test has become a dirty word...
Stories to documentation
NBehave-Console.exe
PebbleSteps.NBehave.Stories.dll /o stories.txt
Theme: Trade Compliance
Story: Pretrade compliance check
As a Trader
I want verify a trade against the portfolio before I call the broker
So that the portfolio does not move out of compliance
Scenario: trade will move portfolio out of compliance
Given portfolio with name Balanced Fund
And asset allocation pie contains segments Cash 0.4, Stock 0.3, Property 0.3
And allocation pie 0.05
And portfolio contains Stock IBM 1, Cash GBP 1, Property SW5 1Hb 1, Stock BHP 1
When market prices are IBM 1, GBP 1, SW5 1Hb 1, BHP 1
Then portfolio value is 4
And portfolio constituents are Stock totalValue:2 percentOfPie:0.5 lower:0.25
upper:0.35, Cash totalValue:1 percentOfPie:0.25 lower:0.35 upper:0.45, Property totalValue:1
percentOfPie:0.25 lower:0.25 upper:0.35,
And portfolio is balanced
MSBuild
<UsingTask
AssemblyFile="NBehave.MSBuild.dll"
TaskName="NBehave.MSBuild.NBehaveTask" />
<NBehaveTask
DryRun="false"
FailBuild="false"
StoryOutputPath="output.xml"
TestAssemblies="
PebbleSteps.NBehave.Stories.dll "
/>
Still in Beta…
What’s left to do?
• The parameter regular expression is on [a-z][A-Z]
– $example0, $example1 – First parameter is printed
twice is the story output
• Gallio integration/replacement of current story runner.
• NBehave small dev team...
• Current story runner text output formatting is poor
– HTML
– or a XSLT for current XML output
• Occasional crash in the parsing engine that links text to
delegate parameters
Giving it a go
Adding NBehave to your team
Developer Driven
• Story as Pseudo code
• Peer programming – One person writes the scenario the
other person removes Pending() and “makes it green”
• Don’t use “specification” syntax
• Consider not using NBehave story runner and host
Stories within current Continuous Integration setup (Use
NUnit TestFixture as opposed to Theme)
Giving it a go
Adding NBehave to your team
continued...
Scrum Master/PM driven
• Ask for detailed requirements in BBD style
• Embedded BDD Lifecycle (API->Stubs->Implementation>UAT) into estimates/deliverables
• Use NBehave story output as a deliverable to
analysis/test team – ie as part of the release notes
More information
•
•
•
•
http://nbehave.org/
http://www.codeplex.com/NBehave
http://behaviour-driven.org/
http://dannorth.net/
Code will be placed onto
www.pebblesteps.com
Questions?