CUSTOMER
As a customer, you are someone with a stake or interest in the outcome of the project. Maybe you’re in charge of the money, or you’re an end user. Lots of articles have been written about Agile Customers. Go read them.
For the examples in this story, the customer is a Frustrated Sudoku Solver. If the project is successful then he will be able to quickly solve any sudoku just by typing it into a web interface. That’s his interest in the project.
The Story
First, think of a story which gives you something you want. Think of a name which encapsulates it and write it down as Title: , eg:
The Narrative
Then, write down your role, what you want and the value you’d like to get from it, using the form:
I want …
So that …
eg:
I want a digit to be removed from potential digits in a cell when that digit definitely exists in the same row or column
So that I can get closer to the solution.
The Scenarios
Now think of scenarios which will help you to determine whether you’ve got the system behaviour you want. The scenarios should be specific. They don’t need to fully cover the behaviour you’re looking for, but they should give you a reasonable certainty that the system works as you expect. If you ever find out that it isn’t giving you what you want, you can add more scenarios later.
Your QAs – and maybe even the devs – can help with this.
Think of a name which encapsulates each scenario, and write it down as Scenario: . eg:
Scenario: A three appears in the last cell when the square has threes in two rows and two columns.
The scenarios should be of the form: given , when , then .
Write them down in the form
When…
Then…
eg:
3..|…|…
…|…|…
…|…|…
———–
..3|…|…
…|…|…
…|…|…
———–
…|3..|…
…|…|…
…|…|..3
When the next step is taken
Then the grid should look like
3..|…|…
…|…|…
…|…|…
———–
..3|…|…
…|…|…
…|…|…
———–
…|3..|…
.3.|…|…
…|…|..3
Reusing scenarios
You can use previously created scenarios as the context for new ones. Think carefully about the scenario name if you
do this, because it will have to make sense in the context of the new scenario too:
- Given a three appears in the last cell when the square has threes in two rows and two columns
- Given I have three black sheep therefore three balls of black wool
- Given I buy a bike and have £250 less in my bank account
Usually expressing both the event and the outcome in the scenario name helps with this.
DEVELOPER
The Story
Your class name should be a camel-cased version of the story name, eg: ReducesPotentialsWhenDefiniteInSameRowOrColumn.java
The class must be a Story – we suggest it should be a ScenarioDrivenStory. You’ll notice that you need to provide a Narrative, and you must specify() your scenarios. addScenario() for each scenario your customer’s asked for, creating a new class for each Scenario.
Each scenario will be run or printed along with the story.
The Scenarios
Each scenario has a series of steps, which are Givens, Events and Outcomes. specifySteps() by providing a new instance of each
step in the order in which they happen. For instance:
String NL = System.getProperty("line.separator");
given(new TheGridLooksLike(
"3..|…|…" + NL +
"…|…|…" + NL +
"…|…|…" + NL +
"———–" + NL +
"..3|…|…" + NL +
"…|…|…" + NL +
"…|…|…" + NL +
"———–" + NL +
"…|3..|…" + NL +
"…|…|…" + NL +
"…|…|..3"
));
when(new TheNextStepIsTaken());
then(new TheGridShouldLookLike(
"3..|…|…" + NL +
"…|…|…" + NL +
"…|…|…" + NL +
"———–" + NL +
"..3|…|…" + NL +
"…|…|…" + NL +
"…|…|…" + NL +
"———–" + NL +
"…|3..|…" + NL +
".3.|…|…" + NL + //<– new digit
"…|…|..3"
));
Scenario steps
Each scenario step can be a Given, Event or Outcome. We suggest they should be UsingMiniMock.
setUp() the world, Events will occurIn() the world and Outcomes will verify() the world. The implementation of each step is up to you. The World in which these steps take place is the same for all the steps in a Story, so anything you put() into the World, you can get() out later.
Running a story
The StoryRunner runs stories. So does the StoryRunnerTask for Ant.
Printing a story
The StoryPrinter prints stories. The StoryPrinterTask will print the stories as to the given directory.
If you’re passing parameters to your steps, scenarios or stories, we suggest that you narrateTo(Renderer) yourself. A Renderer can renderAny(Object). For instance:
public class TheGridShouldLookLike extends OutcomeUsingMiniMock {
private final String asciiGrid;
public TheGridShouldLookLike(String asciiGrid) {
this.asciiGrid = asciiGrid;
}
// …
public void narrateTo(Renderer renderer) {
super.narrateTo(renderer);
renderer.renderAny(asciiGrid);
}
}
));
If your customer hasn’t provided you with the text of a story, printing a Story will give you that text.
If the customer has provided you with story text, then hopefully printing the Story will look just the same.
Changing the World
The Story will createWorld for you. This will be a HashMapWorld. If you want to, you can createWorld of your own in your own Story.
