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

Reply via email to