h4ck3r+=boi v 2.0

  1. Search
  2. About
  3. Subscribe
  4. Archive
  5. Random

h4ck3r+=boi v 2.0

Newer
Older
  • I think I get BDD now (and why we don’t have tools to really do it well)

    Disclaimer: The Road I’ve been on

    Let me start this off saying that I’ve never worked in a strict Agile shop. The kind of “story cards on the walls, pairs of programmers, onsite client” strict Agile shop that does things very close to what the book says.

    Oh, I’ve been on projects that give lip service to agile. Some of them were awesome teams, in spite of not following the book much at all. One team I was on: awesome team, we got stuff done, and we didn’t story pointing tickets or have format iterations. (Looking back on this project, it was a Kanban project… except Kanban didn’t exist back then like it does now.)

    Some of my previous teams were not as good. At another team I was on, weekly iterations meant a massive, looming, critical-must-hit deadline every week. To be fair to that project, maybe it was just where I was situated in the dev process: getting written-on-Windows-first code Wednesday and expected to test and make appropriate changes for the Mac version by end of the iteration on Friday.)

    The Specification Story as it exists (for most folk)

    So as programmers, we’re assigned functionality to implement. But where does this functionality come from?

    In my never-been-in-a-strict-Agile-shop experience, I’ve seen functionality given to me one of three ways:

    1. Wireframes / mockups
    2. business descriptions in English
    3. Technical “how to do it” specifications: “Product must have a store price field” (even if that’s might not actually be the correct place to put it in the programmer’s opinion (“what about historical data?”))
    4. Pseudocode with (comparatively) poor logic and little understanding of how the system is actually implemented.

    My current project uses a mix of all three, and a dash of the fourth on occasion.

    The situation now, for developers

    I’ve been doing Ruby work for the last 2.5 years, so I’m going to use popular Ruby test frameworks here.

    After getting the description of a ticket, a test-first developer goes and converts this into RSpecs, Shoula, or Test::Unit. Red/Failing tests, great. Implement the feature and they turn to green/Success. Red light to green light, awesome.

    Business often doesn’t see these tests. RSpec people who have perked up at this point, I have a whole section of the article for you. Shoulda people? Yes, I know about rake shoulda:list.

    How we can use BDD to make this better

    I’d love to use a Behavior Driven Testing tool which enables business to give us behaviors, and we go make the tests turn green.

    Why?

    • Further bridge the gap between business talk and programmer talk
    • We can use a BDD tool to help business write good tickets for us

    Scenario: Using BDD to build an internal website for Grace Brothers department store

    At the beginning of the iteration, business comes to us with the following tasks for this sprint:

    features of "a product"
       it "should keep track of its price"
       it "should keep track of the number we have in stock"
       it "should keep track of the dates sold"
       it "should decrease the number in stock when a customer buys a product"
       it "should suit Madame"
    end
    

    Each of these line items is broken up into a user story (or a collection of user stories), describing the functionality in more detail. Each user story also describes why the story delivers business value to the client:

    The user stories for “should decrease the number in stock when a customer buys a product” read like so:

    story "should decrease the number in stock when a customer buys a product"
        As the inventory controller
        When a customer buys a product
        I want the number of items remaining in stock for that product to decrease
        So that I can accurately keep track of what's in my inventory
    end
    
    story "should decrease the number in stock when you customer buys a product"
        As the product buyer for the store
        When a customer buys a product
        I want the number of items remaining in stock for that product to decrease
        So that I know if my buying decision was correct, or if the product is not a good fit for the store
    end
    

    Notice that the two stories above match a user story pattern. A pattern like this gives us almost a domain specific language to talk about stories.

    Notice we’ve actually broken out this feature line item into two user stories: two users care about this functionality, and in slightly different ways. This also gives programmers clear, uncluttered and structured tickets, to analyze and ask questions about during the estimation sessions. It also gives programmers some context to think about patterns in the app, or where the app is going in the future.

    During the estimation sessions, because of the uncluttered structure, Programmer Alice can clearly see the specification laid in front of her. She has a thought about the “should decrease the number in stock when a customer buys a product” stories, scans them and sees that her question is not addressed. She raises it to the group:

    “I see that we decrease the number when a customers buy a product. Do we also want to do some inventory forecasting, and alert the inventory controller with an email when the count gets below a certain number?”

    Wait, did someone say DSL?

    If business people describe the behaviors in some DSL, it’s closer to what programmers want, it avoids business specifying tickets by specifying implementation, and lets them focus on what they’re good at: business expectations and user expectations of the software.

    Because it’s a DSL, we can take this and turn it into runnable code, perhaps like Cucumber

    Why Cucumber is not it

    I’m pretty sure Cucumber, as it’s normally marketed, is not the DSL we want. Cucumber, while it’s awesome, feels marketed to the Integration Test crowd… which is awesome, but I’m talking about behavior, not:

    Given I'm at a products page
    When I should click "Buy"
    Then the inventory count should change
    

    Promise of Cucumber:

    • Business people can write QA tests, from a user perspective
    • Can give a full, runnable description of the system to the end client

    The problem is separation of concerns. As programmers we know things should be separated into model (business logic), view (what the user sees), and controller (glue). But this cucumber test gets these two concepts intertwined.

    More specifically, this test checks to see that the inventory count has changed. Yet, customers (probably) shouldn’t see inventory count. So you’re in your integration tests, describing how the UI should act… and then inserting this test of business logic.

    It also doesn’t tell us who cares about this functionality, and it describes the feature by navigating the interface… which is probably changing too, as business and QA try to figure out what the best user experience is.

    Why RSpec (and other unit testing tools) is not it

    Yes, the user story DSL I presented above can be translated this code into Shoulda/RSpec manually. You might structure your RSpec tests like:

    describe "inventory control system" do
      it "should decrease the inventory when the user buys a product" do
          product = Product.make(:pants, :inventory_count = 37)
    
          product.buy(1)
          product.inventory_count.should eq(36)
      end
    end
    

    But, see, this misses the point of the Agile story: what business user cares about this functionality? What business value does this feature deliver those people? What is the behavior they want to see which would speed up the business process for them?

    Also, if you show this to business, they see 5 out of 7 lines worth of noise. Those two lines they do care about (buy pair of pants, our inventory count for those pants should go down by one) border on “yeah, duh, that’s right, you asked me if I was free for this?!”.

    Why a DSL for behavior (user story) specification

    Generating the user story, and only using it until it has been implemented, feels wasteful. Business has gone through a lot of work creating these: why throw them away when we’re done?

    Given a well defined DSL (seven keywords: “features”, “it”, “story”, “as”, “when”, “I”, “so”) we can integrate this into our automated test suite!

    Yes, we have similar problems as Cucumber: this is a pretty high level of specification, still, and we need to translate this into executable code: setting up our mocks, fixtures, running the app through it’s paces internally.

    Which is where business specification stops, and development takes over. Again, we want to avoid technical “here’s how you’re to do this” specifications from business.

    Perhaps we solve this in a similar way as Cucumber: blocks triggered by regex.

    When "a (\w+) buys a product" do |who|
      @initial_count = 37
      @product = Product.make(:pants, :inventory_count = @initial_count)
      @product.buy(1)
    end
    
    I "want the number of items remaining in stock for that product to decrease"
      @product.inventory_count.should eq(@initial_count - 1)
    end
    

    I’m not 100% sold on this approach (using blocks matched by regex), but I’m approaching this problem through the eyes of a polyglot: “How would this work in Python, or Objective-C?”

    Regardless of implementation details, the goal is to turn user stories from an artifact, that gets thrown away or ignored when completed, into a part of the product that lives with the application and assures that business goals continue to be met though the lifecycle of the program.

    Also, the business specifies behavior of the application that exists regardless of the user interface used to access it. Maybe tomorrow Grace Brothers wants to make an iPhone app that uses web services to talk with the website, allowing customers to order a hat from their phone? New interface, but the behavior of the app stays the same (purchases should still decrease inventory count!)

    Conclusion

    I think such a domain specific language would:

    • Make it easier for business to deliver high quality tickets to us developers
    • Ensure business needs continue to be met in the application
    • Reduce translation efforts of programmers, on the “specs to unit tests” front.

    Posted on September 25, 2010

  • staff

Field Notes Theme. Designed by Manasto Jones. Powered by Tumblr.