BDD – antonymarcano.com /blog Thinking through writing... on innovation, business, technology and more Sat, 03 Sep 2016 10:48:44 +0000 en-US hourly 1 https://wordpress.org/?v=4.8.14 Segue Steps /blog/2014/05/segue-steps/ /blog/2014/05/segue-steps/#comments Fri, 02 May 2014 12:25:06 +0000 /blog/?p=556 Continue reading Segue Steps ]]> Sometimes customer scenarios using Gherkin (Cucumber, SpecFlow etc.) can be harder to read than necessary. Once there’s more than one “And” line in a row, I find that there’s more clutter than I’d like and it doesn’t flow as well when I read it. Let’s take this example scenario of upgrading a fremium service.

Scenario: Upgrade my SomeService subscription from Basic to Pro.
Given I am on the Basic plan
When I upgrade to the Pro plan
Then I see a message confirming the upgrade
And I see that I am now on the Pro plan
And I receive a personal thank you by email
And SomeService keeps a record of when the upgrade happened
And SomeService keeps a record of payment

There’s a feature I rarely see used, the ability to use bullets (with asterisks ‘*’). I’ve found that using this among steps with Given/When/Then can remove some of the clutter, making the scenario easier on the eye…

Scenario: Upgrade my SomeService subscription from Basic to Pro.
Given I am on the Basic plan
When I upgrade to the Pro plan
Then I see a message confirming the upgrade, and:
* I see that I am now on the Pro plan
* I receive a personal thank you by email
* SomeService keeps a record of when the upgrade happened
* SomeService keeps a record of payment

What I don’t like about this, however, is how the ‘Then’ step appears in a different context to the bullets and seems less important. To make sure that all the steps are seen as equally important, I can do this:

Scenario: Upgrade my SomeService subscription from Basic to Pro.
Given I am on the Basic plan
When I upgrade to the Pro plan
Then the following occurs:
* I see a message confirming the upgrade
* I see that I am now on the Pro plan
* I receive a personal thank you by email
* SomeService keeps a record of when the upgrade happened
* SomeService keeps a record of payment

Note how I’ve put in a “Then” step that segues from the “When” to the actual expectations.
A ‘Segue Step’ doesn’t have to do anything, other than transition the reader from the previous steps to a list of expectations:

Then /^the following occurs:$/ do #nothing
#just segue to the next step
end

Another way of using a Segue Step could be like this:

Then I should:
* See a message confirming the upgrade
* See that I am now on the Pro plan
* Receive a personal thank you by email
And SomeService should:
* Keep a record of when the upgrade happened
* Keep a record of payment

Asterisks can replace the opening keyword of any type of step, but using them in this way for Given or When steps could be a scenario-smell, suggesting that the scenario has too much detail or those steps are at the wrong level of abstraction. Using asterisks and Segue Steps are most appropriate in “Then” statements with two or more “And” lines.

After doing this, reading scenarios without asterisks and ‘Segue Steps’ now feels like the “And Then” scene from “Dude, Where’s my Car”…And then? I hope you find it useful to write better scenarios too… And then? And then? And theeeeeeeeeeeeen! And thenandthenandthen!

 

Special thanks to Andy Palmer for reviewing this blog post and helping me say it with fewer words.

]]>
/blog/2014/05/segue-steps/feed/ 3
Scenario-Oriented vs. Rules-Oriented Acceptance Criteria /blog/2011/10/scenario-oriented-vs-rules-oriented-acceptance-criteria/ /blog/2011/10/scenario-oriented-vs-rules-oriented-acceptance-criteria/#comments Sun, 02 Oct 2011 13:59:19 +0000 /blog/?p=393 Continue reading Scenario-Oriented vs. Rules-Oriented Acceptance Criteria ]]> Acceptance Criteria, Scenarios, Acceptance Tests are, in my experience, often a source of confusion.

Such confusion results in questions like the one asked of Rachel Davies recently, i.e. “When to write story tests” (sometimes also known as “Acceptance Tests” or in BDD parlance “Scenarios”).

In her answer, Rachel highlighted that:

…acceptance criteria and example scenarios are a bit like the chicken and the egg – it’s not always clear which comes first so iterate!”

In that article, Rachel distinguishes between acceptance criteria and example scenarios by reference to Liz Keogh’s blog post on the subject of “Acceptance Criteria vs. Scenarios”:

where she explains that acceptance criteria are general rules covering system behaviour from which executable examples (Scenarios) can be derived

Seeing the acceptance criteria as rules and the scenarios as something else, is one way of looking at it. There’s another way too…

Instead of Acceptance Criteria that are rules and Acceptance Tests that are scenarios… I often find it useful to arrive at Acceptance Criteria that are scenarios, of which the Acceptance Tests are just a more detailed expression.

I.e. Scenario-Oriented Acceptance Criteria.

Expressing the Intent of the Story

Many teams I encounter, especially newer ones, place higher importance on the things we label “acceptance criteria” than on the things we label “acceptance tests” or “scenarios”.

By this I mean that, such a team might ultimately determine whether the intent of the story was fulfilled by evaluating the product against these rules-oriented criteria. Worse still, I’ve observed some teams also have:

  • Overheads of checking that these rule-based criteria are fulfilled as well as the scenario-oriented acceptance tests
  • Teams working in silos where BAs take sole responsibility of criteria and testers take sole responsibility for scenarios
  • A desire to have traceability from the acceptance tests back to the acceptance criteria
  • Rules expressed as rules in two places – the criteria and the code
  • Criteria treated as the specification, rather than using specification by example

If we take the approach of not distinguishing between acceptance criteria and acceptance tests (i.e. see the acceptance tests as the acceptance criteria) then we can encourage teams away from these kinds of problems.

I’m not saying it solves the problem – it’s just easier, in my experience, to move the team towards collaboratively arriving at a shared understanding of the intent of the story this way.

To do this, we need to iteratively evolve our acceptance criteria from rules-oriented to scenario-oriented criteria.

Acceptance Criteria: from rules-oriented to scenario-oriented:

Let’s say we had this user story:

As a snapshot photographer
I want some photo albums to be private
So that I have a backup of my personal photos online

And let’s say the product owner first expresses the Acceptance Criteria as rules:

  • Must have a way to set the privacy of photo albums
  • Private albums must be visible to me
  • Private albums must not be visible to others

We might discuss those to identify scenarios (as vertical slices through the above criteria):

  • Create new private album
  • Make public album private
  • Make private album public

Here, many teams would retain both acceptance criteria and scenarios. That’s ok but I’d only do that if we collectively understood that the information from these two will come together in the acceptance tests… And that whatever we agree in those acceptance tests supersede the previously discussed criteria.

This understanding tends to occur in highly collaborative teams. In newer teams, where disciplines (Business Analysts, Testers, Developers) are working more independently this tends to be harder to achieve.

In those situations (and often even in highly collaborative teams) I’d continue the discussion to iterate over the rules-oriented criteria to arrive at scenario-oriented criteria, carrying over any information captured in the rules, discarding the original rules-based criteria as we go. This might leave me with the following scenarios:

  • Create new private album (visible to me, not to others)
  • Make public album private (visible to me, not to others)
  • Make private album public (visible to me, & others)

Which, with a subtle change to the wording, become the acceptance criteria. I.e. the story is complete when we:

  • Can create new private album (visible to me, not to others)
  • Can make public album private (visible to me, not to others)
  • Can make private album public (visible to me, & others)

Once the story is ‘in-play’ (e.g. during a time-box/iteration/sprint) I’d elaborate these one at a time, implementing just enough to get each one passing as I go. By doing this we might arrive at:

Scenario: Can Create new private album
When I create a new private album called "Weekend in Brighton"
Then I should be able to see the album
And others should not be able to see it

Scenario: Can Make public album private
Given there is a public album called "Friday Night"
When I make that album private
Then I should be able to see the album
And others should not be able to see it

Scenario: Can Make private album public
Given there is a private album called "Friday Night"
When I make that album public
Then I should be able to see the album
And others should be able to see it

By being an elaboration of the scenario-oriented acceptance criteria there’s no implied need to also check the implementation against the original ‘rules-oriented’ criteria.

Agreeing that this is how we’ll work, it encourages more collaborative working – at least between the Business Analysts and Testers.

These new scenario-based criteria become the only means of determining whether the intent of the story has been fulfilled, avoiding much of the confusion that can occur when we have rules-oriented acceptance criteria as well as separate acceptance test scenarios.

In short, more often than not, I find these things much easier when the criteria and the scenarios are essentially one and the same.

Why not  give it a try?

]]>
/blog/2011/10/scenario-oriented-vs-rules-oriented-acceptance-criteria/feed/ 4
Old Favourite – More Sharks and Delaying Critical Mass /blog/2011/06/old-favourite-more-sharks-and-delaying-critical-mass/ /blog/2011/06/old-favourite-more-sharks-and-delaying-critical-mass/#respond Tue, 07 Jun 2011 10:26:41 +0000 /blog/?p=352 Continue reading Old Favourite – More Sharks and Delaying Critical Mass ]]> This article originally featured on my old blog on 19th January 2010.

In a previous post I talked about Critical Mass of software. I showed how an ever-increasing cost of change resulted in it becoming more economical to completely rewrite the system than to enhance and maintain the original.

I explained how this could be avoided by using practices that sustain a consistent and flat cost of change. I also mentioned that you could defer reaching critical mass. Some teams find it difficult to get the time to do this because “the business” always has “more important” or “higher-value” things on their backlog.

What are the implications of reaching critical mass? Well, depending on what the software does and whether the rewritten version still has to do all of those things, it could cost millions… or more.

Presented with the situation that the product could reach critical mass within a year – costing millions to replace – do you think “the business” would start to think it is worth investing in reducing the cost of change? Obviously, I would advise teams to avoid this situation in the first place:

The reality for many teams I’ve encountered is that they don’t feel empowered to push back on the business’ demands for that next feature in half the time it takes to do it properly. If we could present back the impact of that choice as shortening the time to Critical Mass and bringing about costs to replace the software far in excess of the value gained by delivering that feature a month early then perhaps the business would be better informed.

A big visible chart on the wall, showing the estimated point at which Critical Mass was reached could play a big role in getting the business more interested in sustainable change, or at least inspire a conversation on the subject.

Convincing “the business” to invest in some remedial refactoring or allowing three times as long for each feature to facilitate enough remedial refactoring for each new feature and refactoring-as-we-go for the new feature might be easier if we could represent this idea visually:

The problem with this idea is how do we credibly determine when Critical Mass is going to be reached? Many experienced practitioners could probably reasonably accurately estimate when that was going to happen purely on gut feel but this would be torn to pieces by many product managers. I’ve not solved this problem yet because doing this would require a mathematical model, determined by empirical data.

Perhaps someone will take inspiration from the ideas in these blog posts and find a solution. Perhaps someone has already done this or maybe this is an idea for a future PhD I might undertake? Maybe someone else will take inspiration from this article and undertake that work before I do. If so, they’re welcome to (with due attribution where applicable of course 😉

I think it is possible, however, to come up with a simple model based on the average complexity per unit of value (assuming that the team is using value and complexity). Trending this and keeping an estimate of a complete re-write up to date might allow the simple charts above to be maintained along side release-level burn-down charts.

These ideas are still in their infancy for me. Has this problem been solved already? If not, I encourage others to explore my hypothesis and help take it from just an interesting idea to something more useful.

]]>
/blog/2011/06/old-favourite-more-sharks-and-delaying-critical-mass/feed/ 0
Old Favourite – Sharks, Debts, Critical Mass and other reasons to Sustain Quality /blog/2011/06/sharks-debts-critical-mass/ /blog/2011/06/sharks-debts-critical-mass/#respond Tue, 07 Jun 2011 10:23:16 +0000 /blog/?p=350 Continue reading Old Favourite – Sharks, Debts, Critical Mass and other reasons to Sustain Quality ]]> This article originally featured on my old blog on 18th January 2010.

A while back I tweeted about critical mass of software:

Critical Mass of Code – past which the changeability of the code is infeasible, requiring that it be completely rewritten.

An elaboration of this might be:

Critical Mass of Software: the state of a software system when the cost of changing it (enhancement or correcting defects) is less economical than re-writing it.

This graph illustrates a hypothetical project where the cost of change increases over time (the shape of which reminds me of a thresher shark):

Note:The cost of a rewrite gradually grows at first to account for the delay between starting the re-write and achieving the same amount of functionality in the original version of the software at the same point in time. The gap between the cost-of-change and the cost-of-rewrite begins to decrease as the time it takes to implement each feature of comparable benefit in the original version grows.

It was just one of those thoughts that popped into my head. I soon discovered that critical mass of software is not a new idea.

One opportunity that I feel organisations miss out on is that this can be used as a financial justification for repaying technical debt, thus preventing or delaying the point at which software reaches its Critical Mass, or avoiding it altogether.

Maintaining quality combined with practices that keep the effort involved in completing each feature from growing over time can defer critical mass indefinitely:

Note: The cost of a rewrite is slightly less at first assuming that we are doing a little extra work to ensure that we get the infrastructure we need up and running to support sustainable change (e.g. continuous integration etc.)

This flat cost of change curve is one of the motivations of many agile practices and software craftsmanship techniques, such as continuous integration, test-driven-development, behaviour driven development and the continuous refactoring inherent in the latter two. A flat cost-of-change trend is good for the business, as they have more predictable expenditure.

The behaviour I’ve noticed with some teams is to knowingly accrue technical debt to shorten time to a near-future delivery in order to capitalise on an opportunity and then pay it back soon after:

This certainly defers reaching critical mass but it doesn’t prevent it.

Unfortunately, I see more teams taking on technical debt and not repaying it (for various reasons, often blamed on “the business” putting pressure on delivery dates).

If we had a way of estimating the point at which we’d reach critical mass, we’d be able to compare the benefit of repaying technical debt now in order to avoid or delay the cost of a rewrite… or even better, demonstrate the value of achieving a flatter cost of change.

I’m not sure that we have the data or the means of predicting it, but perhaps these illustrations of a hypothetical scenario will help you explain why sustaining constant quality, automating repeatable tests (or checking as some prefer to call it) wherever technically possible and, on those occasions when we do need to make a conscious choice to compromise quality to capitalise on an opportunity, that the debt is repaid soon after.

One company I know reached this point a couple of years ago and embarked on a department wide transformation to grow their skills in agile methods so that they not only re-wrote the software but could also avoid ever reaching critical mass again. A bold move, but one that paid off within a year. Even for them, they’ll need to avoid complacency as time goes on and not forget the lessons of the past. Let’s hope they do.

]]>
/blog/2011/06/sharks-debts-critical-mass/feed/ 0
Old Favourite – Developer Race-Tech: Continuous Testing /blog/2011/06/developer-race-tech/ /blog/2011/06/developer-race-tech/#comments Mon, 06 Jun 2011 09:36:08 +0000 /blog/?p=332 Continue reading Old Favourite – Developer Race-Tech: Continuous Testing ]]> The original version of this article appeared on my old blog on 28th April 2010. This version has had some edits…

Gearboxes in competitive motor racing are designed to shift as fast as possible. A competitive race-car has computer controlled, hydraulically activated gear shifts that change gears up or down faster than you can blink (literally)! In Formula One, each shift is so fast that the gearbox systems have been dubbed “seamless shift” gearboxes and can shift gear in around 2-4 100ths (0.02 – 0.04) of a second. Compare that to the circa 1-2 second gear-shift a competent driver takes to manually de-clutch, change gear and re-clutch on a road car. Even automatic gearboxes on road cars can’t keep pace with the rapid gear changes that a race car delivers.

Competitive Edge

The race car is only saving fractions of a second with each accelerated up-shift, but the race-driver changes gear so often per lap and there are so many laps in a race that these fractions of a second can add up to a vital and significant lead over their competitors.[1]
mclaren-mercedes

Set aside the lap-time improvements for a moment from spending at least half a second more on the power per up-shift than with a manual box… The modern F1 driver has much more to do in the cockpit too than the comparative tedium of changing gear [2].

Developer race-tech

Now, in motor racing, such gearboxes are taken for granted. No serious Formula One racing team would put their car on the track without one.

In a world where a lot of software development is for companies competing in the economical equivalent of a race, it seems that development teams aren’t taking full advantage of their own metaphorical millisecond gear-shifts.

There are tools that are a developer’s equivalent of a racing gearbox. The simplest example is background compilation. Other examples are refactoring tools that make widespread changes with a simple key-stroke. What once took minutes or hours with global find & replace or even scripting, we can complete in seconds. IDEs that automatically complete class-names and method names are another example. These are tools that many of us take for granted, like the racing driver and automated gear-shift.

Falling behind

But there are other places where we are still not taking full advantage of the technology. I am still encountering surprisingly few people using continuous testing tools, where tests are run automatically in the background every time a file is saved, and not just the test I’m working on, all my tests. There are a few tools available for this, including Infinitest and ZenTest.

Despite the availability of such tools, I still see many developers using keyboard shortcuts to execute tests. Or, worse, reaching for the mouse, right-clicking, navigating another menu level down and running the tests with a left-click, or worse still, forgetting to run them altogether. I want rapid feedback with minimum friction to obtaining it. Much like background compilation, unit tests should just run, and run often, alerting us when a problem occurs. The easier they are to run, the more likely we are to run them… How much easier could it be than it happening automagically each time we save a file?

Need for Speed

Try it for a while and, like me, even keyboard-shortcut executed tests start to feel like you’re stuck in traffic rather than being in a competitive race to the finish… Or, maybe it’s just me and my need for speed

 

The video is of me on the Silverstone Southern Circuit (part of the F1 GP circuit) taking my UK National Class B Racing License Test in a Nissan R35 GTR – approx 480+bhp, 0-62mph (0-100kmh) in 3.5secs, using it’s double-clutch, paddle-operated gear-shift providing gear changes in about 0.2 of a second. I passed… despite being very cautious on the brakes… and was noticeably quicker than the other person doing their test… which you see towards the end as I pass them 🙂

[1] At the Monaco GP, an F1 driver will change gear around 50-60 times in one lap. Over 78 laps, this adds up to as many as 4680 gear changes over the whole race (up and down-shifts).

[2] The comparative tedium of de-clutching, shifting and re-engaging the clutch is something that a race-driver should not need to worry about as they approach 200mph while adjusting the brake-balance lever, switching to a new fuel-air mixture setting, pressing the KERS boost button and/or deactivating the Drag Reduction System.

 

]]>
/blog/2011/06/developer-race-tech/feed/ 3
Cucumber – with step-free access /blog/2011/05/introducing_cukesalad/ /blog/2011/05/introducing_cukesalad/#respond Sun, 29 May 2011 09:35:58 +0000 /blog/?p=273 Continue reading Cucumber – with step-free access ]]> A while back I wrote about writing feature specs (acceptance tests) at the right level of abstraction. I explained how we want to pitch our scenarios at the “task” level…

Goal: What we’re trying to achieve which has one or more…
Tasks: The high-level work-item that we complete to fulfil the goal, each having one or more…
Actions: The specific steps or interactions we execute to complete the task.

I showed how many scenarios (acceptance tests) are pitched at too low a level. They’re often at the action level, detailing every field filled in and every button clicked. This is too low-level.

Instead, we want to express the business process… the tasks involved in fulfilling a goal. The actions should be expressed in the code (or step-definitions), not the plain-text scenarios. Pitching the scenarios at the action level makes scenarios much harder to maintain – especially when the user-interface changes. But, perhaps more importantly, they don’t express what’s of interest to the business.

There are other challenges faced by teams using cucumber:

  • Over-wordsmithing scenarios
  • Limited regular-expression expertise
  • Unmaintainably large step-definition files
  • Fragmented step-definition files
  • Coverage vs. Speed tradeoffs of running scenarios through or below the GUI (respectively)

We’ve taken many of the lessons we’ve learned using BDD tools to address these problems and begun to distill the various heuristics and design ideas (patterns) that emerged into a single open-source extension to cucumber – cukesalad.

Photo of the github page

Many of the heuristics and design ideas expressed in the project can be used on your existing projects without using cukesalad:

  • Treat each step-definition as a class of task. Like other classes, have one file per step-definition and organise them so they’re easy to find. Name each file using the text used in the scenario.
  • Screen Capture of Task folder Hierarchy

  • Abstract the API that drives your application behind something representing the role or type of role involved in the story
  • Write scenarios like a narrative for someone in the role relevant to the user-story
  • Write the actions within the task (or step-definition) as if they’re instructions on how to complete that task
  • And more…

Cukesalad is the ongoing expression of us mercilessly refactoring a ‘typical’ Cucumber project. At the moment, it is more of an illustration of the concepts and ideas… but some are already using it on their day-to-day projects. Check it out… try it out… and let us know what you think.

Go to http://cukesalad.info – for more info, or checkout the talk I gave at CukeUp, hosted at SkillsMatter.

And if you’re wondering why it’s called cukesalad… It’s cucumber, washed and ready to eat.

 

]]>
/blog/2011/05/introducing_cukesalad/feed/ 0
Putting Cucumber where it’s not supposed to go will hurt! /blog/2011/03/cucumber-pains/ /blog/2011/03/cucumber-pains/#respond Mon, 07 Mar 2011 13:24:25 +0000 /blog/?p=244 Continue reading Putting Cucumber where it’s not supposed to go will hurt! ]]> Today, I came across this post by Ryan Bigg where he talks of the pains he’s experienced with Cucumber.

Fortunately for Ryan, the outcome was a positive one, he ended up finding what appears to be a nice looking API for automating test-execution.

The experience he had with Cucumber, however, is a common one. Often teams start using Cucumber in an effort to reduce the need for programming skills when writing automated tests.

This isn’t the problem that Cucumber and other BDD tools are trying to solve and this is why so many teams who misuse it in this way experience difficulty and frustration.

BDD tools like Cucumber are designed to help teams and their customers arrive at a shared understanding of the problem they wish to solve (in terms of the user’s goals and tasks). It’s not really intended to describe the solution (i.e. step-by-step interactions with the GUI).

If your Cucumber scenarios have words such as “click” or “type” or mention field names and the like, it’s probable that you’re either:
a) Using Cucumber to automate test-execution (not what it was intended for) or
b) Trying to do BDD but writing the scenarios at too low a level of detail.

If you’re doing the latter (b)… then you may find the post I wrote over the weekend useful.

If what you’re doing is (a) then the post I wrote over the weekend might help you go down a path where automating your tests will make the transition to BDD that much easier.

If you really, really only want to automate test-execution then you might find that you’re putting Cucumber where it’s not supposed to go… and just so you know – that’s probably going to hurt 🙂

]]>
/blog/2011/03/cucumber-pains/feed/ 0
A bit of UCD for BDD & ATDD: Goals -> Tasks -> Actions /blog/2011/03/goals-tasks-action/ /blog/2011/03/goals-tasks-action/#comments Sun, 06 Mar 2011 20:01:22 +0000 /blog/?p=209 Continue reading A bit of UCD for BDD & ATDD: Goals -> Tasks -> Actions ]]> There’s something wrong with many behaviour specs (or acceptance tests). It’s been this way for some time. I’ve written about this once or twice before, referencing this post by Kevin Lawrence from 2007.

So, first things first, I want to take this opportunity to update the terminology I use…

Goals -> Tasks -> Actions
A useful technique used in User-Centred Design (UCD) and Human Computer Interface (HCI) design is Task Analysis. There are three layers of detail often talked about in Task Analysis:

Goal: What we’re trying to achieve which has one or more…
Tasks: The high-level work-item that we complete to fulfil the goal, each having one or more…
Actions: The specific steps or interactions we execute to complete the task.

Previously, the terms used by Kevin, myself (and several others) were Goal->Activities->Tasks. From now on, I’m going to use the UCD/HCI/Task Analysis terms Goal->Task->Action. It’s exactly the same model – just with different labels at the three layers of detail.

What’s wrong with your average behaviour spec?
Let’s look at a common example… The calculator. For convenience, I’m going to borrow this one from the cucumber website[1].

Scenario: Add two numbers
Given I have entered 10 into the calculator
And I have entered 5 into the calculator
When I press add
Then the result should be 15 on the screen

[1]note: I’m using this example for convenience and simplicity. The value of the example on the cucumber website is to demonstrate how easy cucumber is to use and not necessarily as an exemplar feature spec

What would you say the scenario’s name and steps are representing? Goals and Tasks or Tasks and Actions?

I’d argue that adding two numbers is a task and the steps shown above are actions.

Instead, I try to write the spec (or test) with a scenario-specific goal and the steps as tasks.

Scenario: sum of two numbers
When I add 10 and 5
Then I should see the answer 15

I.e.:
Scenario: <A scenario specific goal>
Given <Something that needs to have happened or be true>
When <Some task I must do>
Then <Some way I know I've achieved my goal>

Another Typical Example
Let’s apply this to another typical example that might be closer to what some people are used to seeing:

Scenario: Search for the cucumber homepage
Given I am at http://google.com
When I enter "cucumber" into the search field
and click "Search"
Then the top result should say "Cucumber - Making BDD fun"

Again this is talking in terms of actions. As soon as I’m talking in terms of click, enter, type or other user-action, I know I’m going into too much detail. Instead, I write this:

Scenario: Find the Cucumber home page
When I search for "Cucumber"
Then the top result should say "Cucumber - Making BDD fun"

Why does it matter?
In the calculator example, the outcome the business is interested in for the first scenario is that we get the correct sum of two numbers. The steps in the scenario should help us arrive at a shared understanding of what ‘correct’ means. How we solve the problem of getting the numbers into the calculator and choosing the operator is a separate issue. That’s detail we can defer. It may be better to explore the specifics of the workflow using, sketches, conversation, wire-frames or by seeing and using our new calculator.

So, expressing our scenarios in terms of goals and tasks helps the delivery team and the business arrive at a shared understanding of the problem we’re trying to solve in that scenario.

Expressing the scenario in terms of the clicks, presses and even fields we’re typing into is focusing on a solution, not the problem we’re trying to solve.

But there’s another benefit to doing it this way…

A Practical Concern – Maintainability
The first calculator example follows reverse-polish notation for the sequence of actions:

  1. enter the first number
  2. enter the second number
  3. press add

If we put that detail in the scenarios, that workflow will be repeated everywhere – for addition, subtraction, division, multiplication… and anywhere any calculation is described.

What happens if the workflow for this calculator (such as the UI or API) changes from a reverse-polish notation to a more conventional workflow for a calculator? Like this:

  1. enter the first number
  2. press add
  3. enter the second number
  4. press equals

The correct answer hasn’t changed – i.e. the ‘business rule’ is the same – it’s just the sequence of actions has changed.

Now we have to go through all the feature files and update all the scenarios. In the case of our calculator that may only be a few files covering add, subtract, divide, multiply. For something larger and more complex this could be a lot of work.

Instead, putting this in the code of the step-definition means that this:

When ^I (add|subtract|divide|multiply) (.*) (?:and|from|by)? (.*) do |operator, first_number, second_number|
@calc = @calc ||= Calculator.new
@calc.enter first_number
@calc.enter second_number
@calc.send operator.to_sym
end

Would have to change to this:

When ^I (add|subtract|divide|multiply) (.*) (?:and|from|by)? (.*) do |operator, first_number, second_number|
@calc = @calc ||= Calculator.new
@calc.enter first_number
@calc.send operator.to_sym #moved up from the bottom
@calc.enter second_number
@calc.calculate #new action for the conventional calculator workflow
end

Nothing else would need to change – other than the product of course. By writing the steps as tasks, all of our feature files would still accurately illustrate the business rule even though the workflow of the interface (gui or api) has changed.

Taking your scenario-steps to task
So, taking this approach helps us to reduce our maintenance overheads. Putting the Actions inside the step definition makes our tests less brittle. When the workflow changes we only need to update our specs in one place – the step-definitions.

Of, perhaps, greater importance – by capturing the user’s scenario-specific goal as the scenario name and the tasks as the steps, the team are working towards a shared understanding of the part of the problem we’re trying to solve not a solution we might be prematurely settling upon. When rolled up with the broader context (expressed in the user-story and its other scenarios) it gives us a focus on solving the wider problem rather than biasing the solution.

Sometimes, at first, it’s hard to see how to express the scenario and is easier when people start by talking of clicks, presses and what they’re entering. And that’s ok. Maybe that’s where the team needs to start the conversation. Just because that’s where you start, ask “why are we doing those actions” a few times, and it doesn’t have to be where you end up.

]]>
/blog/2011/03/goals-tasks-action/feed/ 2
You’re almost cuking it… /blog/2010/08/youre-almost-cuking-it/ /blog/2010/08/youre-almost-cuking-it/#comments Wed, 25 Aug 2010 06:15:29 +0000 /blog/?p=85 Continue reading You’re almost cuking it… ]]> In “You’re Cuking it Wrong”, Jonas Nicklas, shows several examples of bad scenarios (or acceptance tests whichever term you prefer) and demonstrates better approaches. This is an excellent post on common mistakes made when writing example scenarios with Cucumber.

I think, however, he could have gone further in one case. One of his examples of a bad scenario looks like this:

Scenario: Adding a subpage
Given I am logged in
Given a microsite with a Home page
When I click the Add Subpage button
And I fill in "Gallery" for "Title" within "#document_form_container"
And I press "Ok" within ".ui-dialog-buttonpane"
Then I should see /Gallery/ within "#documents"

(Dude – yep, seen these… I agree… not good). He goes on to suggest it should really look like this:

Scenario: Adding a subpage
Given I am logged in
Given a microsite with a home page
When I press "Add subpage"
And I fill in "Title" with "Gallery"
And I press "Ok"
Then I should see a document called "Gallery"

This is a massive improvement. It keeps the specifics that inform the reader and give them some context (like filling in the “Title” with “Gallery”) and takes them further away from the implementation. Although it gets closer to expressing customer intent, I think it could go further. At the moment, it is describing the ‘what’ and some of the ‘how’. This example makes complete sense if what we are exploring is the design of the UI. I’ve not found these scenarios to be a good place to do that, however.

Instead, in these specifications we want our examples to illustrate the customer intent. The ‘what’ not the ‘how’. There are other places we can capture the ‘how’ – i.e. in the step methods.

Instead, I would write it like this:

Scenario: Adding a subpage
Given a microsite with a home page
Given I am logged in
When I Add a Subpage with a Title of "Gallery"
Then I should see a document called "Gallery"

I’ve removed all the “Tasks” and left only “Activities”. This leaves the user experience completely open. This ensures that when there are UI changes, I only change the code that performs the tasks (clicking, pressing, etc.) and my scenarios evaluate whether the customer intent is still fulfilled – without having to go back and change a lot of files.

Otherwise – great post Jonas 🙂

]]>
/blog/2010/08/youre-almost-cuking-it/feed/ 7
Being a youDevise Developer – Week 1 /blog/2010/07/being-a-youdevise-developer-week-1/ /blog/2010/07/being-a-youdevise-developer-week-1/#respond Sun, 18 Jul 2010 10:09:24 +0000 /blog/?p=51 Continue reading Being a youDevise Developer – Week 1 ]]> In my previous post, I gave the background to me spending the next month or two as a developer on a youDevise product.

I’ve just completed my first ‘official’ week working with them. It was one of, if not, the smoothest of inductions I’ve ever experienced. I arrived and was shown a desk to work at. There was a welcome letter in front of a dual screen developer machine with Ubuntu installed. The letter told me everything I needed to get logged in, access e-mail and wiki links telling me where to find the rest of the information I needed to configure the machine. For the project I was about to work on.

Their CEO sent out an introduction e-mail telling everyone about me and others who started that day on the development team and in other non-technical departments. I also experienced a warm welcome from the team and was assigned a youDevise mentor to help me settle in.
My first few days involved several presentations – mostly demonstrative – introducing me to youDevise products and their business model. Yet I still got to work on code almost immediately.

I was very lucky to get to pair with their summer intern, Marius Cobzarenco, on a part of an all-new reporting capability for one of their products. I am so impressed with Marius. He left Cambridge University only three weeks ago and I have to say he is one of the most competent graduates that I’ve ever met! He has a level of technical competence that rivals many much more experienced developers and he has a passion and aptitude for learning that is rare. He became competent in Behaviour Driven Development after working with me for only an hour or two and fell in love with the approach. I was so impressed with him that I decided to sponsor his attendance at a TDD workshop this weekend with Jason Gorman.

Marius is a reflection of the high standards youDevise sets for itself. Whenever I’m there, I never feel like the smartest person in the room.

Speaking of smart people, other youDevisers I’ve also had the opportunity to work with include Joe Schmetzer and Stephen Siard.

Joe is a great guy – extraordinarily capable yet incredibly humble. Joe really knows his stuff! I’m looking forward to sharing with him, but mostly, learning from him. Stephen – who I have secretly, in my mind, nicknamed ‘the professor’ simply because his intellect is especially humbling for me – is another who I have been very lucky to work with. He has a way with algorithms that is tantamount to wizardry – but he is far too scientific to be called “the wizard” 🙂

These guys stand alongside other similarly impressive and diverse individuals that I’ll mention in future posts – each with their unique talents.

Next week, we start a new iteration. I’ll be seeing what it’s like working with some of their legacy code. Based on what I’ve seen so far, at least I know they recognise where they have legacy and that they are passionate about writing tests and cleaning the code up as they go.

]]>
/blog/2010/07/being-a-youdevise-developer-week-1/feed/ 0