I love it.
I presented a BDD session at the recent Software Architecture Workshop
in Switzerland and got a) lots of positive feedback (like, lots - really
lots - I think it's going somewhere), and b) a request that I write more
of it down rather than just explaining it to small groups of people.
The immediate fix for b) is to get this kind of documentation on
jbehave.org and to start blogging some mini-articles about BDD. The
first one is called "What's in a story?" and will be published some time
this week. It's come in at about 1500-2000 words, so it's a bit of an
experiment in terms of how much people will bother to read. I'll tune
the subsequent ones based on feedback.
Also, someone pointed me to a thread on an XP newsgroup about stories in
BDD <http://tinyurl.com/2vbykf>, which I replied to, so feel free to
chime in there too.
Cheers,
Dan
Elizabeth Keogh wrote:
Hi all,
I don't care if we go to 1.0 before documentation, really - anyone who
really wants to know how to use JBehave can get hold of the examples.
However, I think we should update it soon. Below is a first draft of
some Story documentation, based on my next breakable toy. When I move
it to a web page I will of course provide links to all the various
APIs, Ant home page, etc.
I'm particularly pleased with the way you can use JBehave's APIs in
English sentences; eg: A Renderer can renderAny(Object).
On that note, I would like to rename Run to BehaviourRunner, and all
the JBehave<whatever> tasks to BehaviourTask, StoryTask,
StoryPrintingTask, etc. They don't need the JBehave qualifiers, IMHO.
Cheers,
Liz.
--
How to use JBehave's Story Framework
------------------------------------
<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: <story name>, eg:
- Title: Reduces potentials when definite in same row or column
<The Narrative>
Then, write down your role, what you want and the value you'd like to
get from it, using the form:
- As a <role>
- I want <some feature>
- So that <some benefit>
eg:
- As a <frustrated sudoku solver>
- 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: <Scenario name>. 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 <some context>, when <some
events happen>, then <some outcome should result>.
Write them down in the form
- Given <some context>
- When <some event happens>
- Then <some outcome should result>
eg:
- Given the grid looks like
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.
When you have enough scenarios, write them all down and give the story
to your developer.
<DEVELOPER>
If the text file that your customer has given you is of the form <some
name>.story, then you can use the JBehave
Eclipse plugin to help you generate your empty code. Just ctrl-click
on the story title, the scenario name,
the givens, events, outcomes, etc.
If you can't or don't want to use the plugin, the code can be manually
generated.
<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"
));
These should match the steps which your customer has provided you.
<Scenario steps>
Each scenario step can be a Given, Event or Outcome. We suggest they
should be <step>UsingMiniMock.
As the story runs, Givens will 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 JBehaveStoryTask for Ant.
<Printing a story>
The StoryPrinter prints stories.
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.
--
Elizabeth Keogh
[EMAIL PROTECTED]
http://www.livejournal.com/users/sirenian