BDD Discovery and OOPSI
Before we get good at delivering continuously, we need to get good at breaking our business goals down into smaller goals and horizons of value.
I like to think of these like value waypoints. We need to expertly navigate to these waypoints as quickly as we can. At each waypoint we’ll check our surroundings and make sure we’re still on track.
We only get value out of iterative delivery practices if we are always working on the most important thing.
BDD addresses this, as it is an outside-in practice. That means we must start with the Outcome (the value)
I’d like to introduce The OOPSI Model, its an extension of Chris Matt’s Feature injection, put together by me and @PeteBuckney. We’ve added Scenarios to make it OOPSI rather than OOPI. We thought this helped put our BDD practices in context.
To get to our value waypoints as quickly as we can, we need to be able to defer detailed examination of stuff that isn’t important until later. We want to find the highest value outcomes, then the highest value outputs that achieve those outcomes, then the highest value processes that deliver those outputs, then the highest value scenarios and examples that help clarify the required implementation. OOPSI is a useful technique to help add more convergent thinking to our software delivery practices. Convergent thinking techniques help us align to the next value waypoint and start small.
If you do it the other way round it ISPOO 😉
You can watch a video of me & Pete talking about BDD Analysis and OOPSI at BDDX 2015
Before we explore OOPSI in detail, let’s take a step back and think about BDD discovery and what we are trying to achieve.
Why do we use examples in our specifications?
Our goal is to reduce rework, by basically removing defects early, all kinds of defects – those that occur as a result of getting the requirements wrong, those that result from misunderstandings, ambiguities, handoffs.
Our practice of SBE helps us do this by exploring examples. Not this.
We have to do the analysis and exploration to get these benefits. There is craftsmanship and skill associated with these activities.
We need to do the analysis and synthesis to turn requirements into specifications, there is discussion and exploration required to do this. It takes skill and practice to come up with the cleanest, leanest and most elegant set of examples you need. The examples don’t just pop out of the domain expert’s mouth in Given When Then Syntax.
If we jump in too early, we’re likely to end up with a lack of context and masses of duplication in our scenarios
We talk a lot at conferences about ‘when cukes go bad’ or ‘how to get the most out of cukes’. This is normally approached as rationalisation and refinement in cucumber. Normally the rationalisation removes duplication by using tables of examples, tables of data conditions, or tables to define pre-conditions.
If we used more of the Specification by Example practice and collaborated around these tables of examples before we turned them into feature files I think we’d save time.
Tables help us focus on the what and not the how. If we jump into GWT to eagerly we can end up putting the emphaaaaasis on the steps (the how) and lose the value of the what.
It’s hard to spot gaps in a long page of text. It’s much easier to see what’s what by reviewing the tables of data themselves.
The OOPSI mapping technique can be used to help structure the discovery process, to help ensure that we’re always focusing on the most important thing and to avoid analysis paralysis.
Similar to Matt Wynne’s Example Mapping, this technique can be done collaboratively using post-it notes in small teams. The 3 Amigos (domain expert, test expert and technical expert) follow the OOPSI process using different coloured post-it notes to explore the business requirements and work towards some implementation examples.
OOPSI helps bring together BDD automation with the analysis practices of ATDD and Gojko Adzic’sSpecification by Example
Starting with the Outcomes, Outputs, Process etc helps us rationalise in advance. We spot shared processes and relationships between outputs and scenarios, and we organise our examples around them. The examples rationalise themselves.
A worked example might look like this:
A good starting point for the outcome might be the ‘how’ level of an Impact Map. Or if you work with User Stories you might start with something like this… a well known BDD starting point…
We know that the value normally lies in the outputs of a process, so let’s think about them first. What outputs might we get from our withdraw cash story?
Crikey, quite a lot.
Cash, receipts, returned bank cards, an updated balance on a bank statement, updated database values, and even some error messages.
Some of these outputs might be well understood, but some might benefit from a bit more exploration.
It’s really helpful to illustrate outputs with examples. Draw them. Understand the data attributes that appear on the outputs. Use real world examples wherever possible. I go into this in a bit more detail in my data personas blog. In this example we might choose to draw the receipt, or mock up the error messages. This helps drive conversations and get to the important stuff.
We might identify some high level examples here that are just focused on recognising the different outputs that can get generated. It’s important to recognise that we are often working with examples at different levels of detail. We always want to look for the most useful format which helps open up conversations.
Now let’s choose our most important output so we don’t get becalmed by analysis paralysis. Our most important output is cash.
Some of the outputs might naturally go together. In this case when we get cash we normally get a receipt, updated database tables, our card returned and an updated statement.
Now we’re onto process.
What process and interactions are required to generate cash? We might come up with something like this.
We might do a bit of general exploration at the process level and see how our processes and interactions change to support the different outputs.
Making sure we include the process in our discovery activities (as pointed out in Jeff’s User Story Mapping Book) helps bring in the UX and interaction designers, so that everyone can be working to the same vision.
Depending on our problem domain and its complexities, we might also consider other techniques that help open up conversations. Swim-lane diagrams are particularly useful if you want to explore interfaces and APIs between different systems.
Now we have some context to start brainstorming some scenarios that are relevant to this process. They might be paths through the process to generate the outputs, or just rules. There might not even be a process. (Get 200 points per mile as a business class traveller and 100 points per mile as an economy class traveller doesn’t have a process and is just a rule).
For our ATM scenario we might come up with these key scenarios initially.
Let’s take the first one.
If we decided to write this up in Gherkin at this stage it might look like this:
Let’s just think about our use of examples. What do we mean by an example? To me it’s only an example if it actually clarifies the rule, if it is a representative case.
The reason that we used to find loads of defects in the testing phase of waterfall projects is that it was the first time that our implementation got tested with real world data.
The value of the example is in the data used to drive the example
In fact the data is so useful, we might not even need the words to help us understand. This is where the practice of Specification by Example comes in.
5. Inputs (& Preconditions)
Using our OOPSI model, before we dive into Given, When, Then, we would illustrate our scenario using a table of examples.
Ooooh look!, We can illustrate the other two scenarios using the same table. This supports a Gherkin Scenario Outline (only we haven’t written it yet). And we realise that the Valid Card and Card Returned Columns aren’t important for the scenarios, so we can take them out.
What’s interesting to note here is that the scenario outline name has resolved to customer requests cash. Notice request cash matches an activity box in our process.
We might find a pattern where high level and happy path scenarios are grouped around important outputs, and lower level examples support the different activity boxes – illustrated by tables of data where necessary. We could structure our living documentation that way if we wanted.
Collaborating around the data in the table helps us know when we have found new scenarios, and we add them to our OOPSI map. But since we’re only concerned about the cash output at the moment we’ll park the Invalid Card scenario to worry about later.
When we get to that one, it’ll be a slightly different process & we’ll need a table of examples to help us understand more about valid and invalid cards. They’ll probably resolve themselves around the activity box ‘check card’. Interesting.
Liz Keogh wrote a sonnet about deliberate discovery. I love this excerpt
As we explore our examples with real world data, we’re looking for dragons.
The thing that makes one scenario different from another is normally the context. The preconditions, the GIVENs, everything we need to arrange the test.
Liz Keogh also did a blog called Conversational Patterns in BDD where she talks about context questioning. In the ATM example if we were focusing on the cash card returned output we might have asked ‘Is there any scenario where you wouldn’t get your card back?’ And the answer might be ‘Yes, when there is a fraud flag live on the account’ …. Ahhh a fraud flag… what does that look like?
So if we explore the context we find the dragons. Back to our ATM example.
Ooooh look there’s a dragon
We didn’t think about overdraft facility. We could use the same table and add these examples like this:
Using the table helps us notice that if our scenario introduces new columns, we introduce unnecessary permutations of preconditions and we have probably seen a new rule.
And we might spot some more dragons like these:
Using the table to collaborate around helps us notice that we’ve identified 2 new preconditions that we’re interested in. The preconditions, the GIVENs are a good thing to collaborate on an agree on.
Get to know your pre-conditions and test input data. Use real world data. Give your data a personality. How many different data personas to you need to define to cover all the examples?
A data persona is a profile of data conditions with a name. They help you drive conversations around examples from discovery through to delivery. And they become ubiquitous examples. You can re-use your data personas all over the place.
So in summary:
- Don’t dive in to Gherkin too early
- Do deliberate discovery using OOPSI
- Value the practice of Specification by Example
- Slay the dragons using data personas
And use whatever tools and techniques that help find dragons at all different levels of OOPSI.