Behaviour Driven Development With NBehave Linking User Stories
Behaviour Driven Development With NBehave Linking User Stories and Domain Driven Design to Testing David Ross W: www. pebblesteps. com E: willmation@gmail. com
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 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 Portfolio. Maintenance. Story { [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. As. A(“Operations team member"). IWant("To create a new portfolio on behalf of a portfolio manager"). So. That("the portfolio manager can configure the portfolio and the front office can trade");
Creating a Scenario Fluent interface to define the story. With. Scenario("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. With. Scenario("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 mb. Unit • Ouch we get an error? ? ? • The scenario throws an exception – NBehave isn’t validating any code • Use Pending story. With. Scenario("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 portfolio. Name = ""; Portfolio p = null; var portfolio. Repository = Mock. Repository. Generate. Stub<IPortfolio. Repository>(); var portfolio. Service = Mock. Repository. Generate. Stub<IPortfolio. Service>(); s. With. Scenario("portfolio already exists"). Given("portfolio name is $name", "Aggressive Fund", n => { portfolio. Name = n; p = new Portfolio { Name = portfolio. Name }; portfolio. Repository. Stub(x => x. Find. Portfolio. By. Name(portfolio. Name)). Return(p); portfolio. Service. Stub(X => X. Create. Portfolio(p)). Throw(new Item. Exists. Exception()); })
Stubbing example Create a new portfolio story. When("portfolio already exists in database", () => Assert. Is. Not. Null( portfolio. Repository. Find. Portfolio. By. Name(portfolio. Na me)) ). Then("new portfolio create should fail", () => Assert. Throws<Item. Exists. Exception>(() => portfolio. Service. Create. Portfolio(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/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. Is. True(component. Is. Valid) component. Is. Valid. Should. Be. True() Assert. Contains(s, “hello world”); s. Should. Contains(“hello world”); NBehave contains extension methods for NUnit, mb. Unit, x. Unit
Fixtures to Specifications Is it necessary? Using Namespace Alias [Test. Fixture] [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 Pebble. Steps. 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 SW 5 1 Hb 1, Stock BHP 1 When market prices are IBM 1, GBP 1, SW 5 1 Hb 1, BHP 1 Then portfolio value is 4 And portfolio constituents are Stock total. Value: 2 percent. Of. Pie: 0. 5 lower: 0. 25 upper: 0. 35, Cash total. Value: 1 percent. Of. Pie: 0. 25 lower: 0. 35 upper: 0. 45, Property total. Value: 1 percent. Of. Pie: 0. 25 lower: 0. 25 upper: 0. 35, And portfolio is balanced
MSBuild <Using. Task Assembly. File="NBehave. MSBuild. dll" Task. Name="NBehave. MSBuild. NBehave. Task" /> <NBehave. Task Dry. Run="false" Fail. Build="false" Story. Output. Path="output. xml" Test. Assemblies=" Pebble. Steps. NBehave. Stories. dll " />
Still in Beta… What’s left to do? • The parameter regular expression is on [a-z][A-Z] – $example 0, $example 1 – 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 Test. Fixture 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?
- Slides: 37