behaviour driven development v 0.1
DESCRIPTION
Introduction to Behaviour Driven Development using the NBehave library.TRANSCRIPT
Behaviour Driven DevelopmentWith NBehave
Linking User Stories and Domain Driven Design to Testing
David Ross
W: www.pebblesteps.com
Behavior Driven DevelopmentTools 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 DevelopmentAnalysis/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 applicationExcel spreadsheet replacement
• 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
Simple Trading application
Requirements
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 DevelopmentHow 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 DevelopmentDo 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?
RequirementsWhat 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
RequirementsPrecise and clear over verbose
We want requirements that
• Can be tested!!!
• Are attainable!!!
• Are traceable into code!!!
Requirements GatheringBDD 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
Story TemplateAs a [User/Role]
I want [Behaviour]so that [I receive benefit]
ExampleAs a “Operations staff member”
I want “To create a Portfolio”so that “So that it can be traded”
BDD User StoriesFormal template for User Stories
BDD User StoriesFormal template for User Stories
Scenario TemplateGiven some initial context (the givens),
When an event occurs,then ensure some outcomes.
ExampleGiven “New portfolio is called Balanced
Fund”When “Portfolio already exists”then “Portfolio can no be created”
• .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
NBehave
What is it?
[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 BDD ThemeCollection of related stories
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 Story 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");
Creating a ScenarioFluent interface to define the story
• 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");
Executing the testWith NBehave runner or mbUnit
StoryPending Scenario
Stubbed Scenario
Real Behaviour
Acceptance Test
Behavior Driven Development
Across the Project (Story) Life Cycle
1. Story2. Pending Scenario3. Stubbed Behavior Cycle (Red, Green, Refactor)
4. Real Behavior Cycle (Red, Green, Refactor)
5. Acceptance Test
Stubbing out the behaviorWith 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
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 out the behaviorWith NBehave and Mocking
Stubbing example
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());
})
Create a new portfolio story
Stubbing example
.When("portfolio already exists in database",
() => Assert.IsNotNull(
portfolioRepository.FindPortfolioByName(portfolioNa
me))
)
.Then("new portfolio create should fail",
() => Assert.Throws<ItemExistsException>(() =>
portfolioService.CreatePortfolio(p))
);
Create a new portfolio story
TFD/BDD Comparison
Test First
• Bottom Up approach
• Lots of little steps working towards a solution
Output • Tests
Behavior Driven
• Top down approach• Design starting with
interfaces (using stubs)
• Back fill with code later
Output• API creation
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
User Acceptance Test
Test Driven DevelopmentDevelopment/Testing Phases
User Stories
Behaviour Driven
Development
Unit &
Component
Test
System
Integration
Test
User
Acceptance
Test
Deployment
Verification
Test
Stubs
Domain
Model
Mocks
Implemented
Behaviour
No
Mocks
/Stubs
GUI Testing
Fitness
Fixtures to Specifications
Assert.IsTrue(component.IsValid)
component.IsValid.ShouldBeTrue()
Assert.Contains(s, “hello world”);
s.ShouldContains(“hello world”);
NBehave contains extension methods for NUnit, mbUnit,
xUnit
Loosing Assert from tests. Easier to read? For BAs, yes...
Fixtures to Specifications
[TestFixture] [Context]
[Test] [Specification]
[Context]
public class When_using_tokenized_stories
{
[Specification]
public void should_replace_token_with_value()
{}
Stories for BDD. Specifications for focussed
tests.
The word Test has become a dirty word...
Is it necessary?
Stories to documentationNBehave-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
<UsingTaskAssemblyFile="NBehave.MSBuild.dll" TaskName="NBehave.MSBuild.NBehaveTask" />
<NBehaveTask
DryRun="false"
FailBuild="false"
StoryOutputPath="output.xml"
TestAssemblies="
PebbleSteps.NBehave.Stories.dll "
/>
Still in beta…
• The parameter regular expression is on [a-z][A-Z]
– $example0, $example1 – In story output first
parameter is printed twice
• Gallio integration/replacement of current story
runner
• Current story runner text output formatting is poor
– HTML
– or a XSLT for current XML output
• Occassional crash in the parsing engine that links
text to delegate parameters
What’s left to do?
• http://nbehave.org/
• http://www.codeplex.com/NBehave
• http://behaviour-driven.org/
• http://dannorth.net/
Code will be placed onto
www.pebblesteps.com
Questions?
More information