Easier JBehave steps with variants

4 Comments

In an earlier post we offered an introduction to the JBehave project for automatic acceptance testing. While that article focused on setup and general use of the framework, this time I will concentrate on a recent addition I wrote and contributed to the upstream library that makes it easier to maintain a more natural language style in the test stories.

Previously on LOST JBehave

To recap quickly, in JBehave tests are written as natural language stories that will be matched to implementation methods at runtime. Which method gets called for each step of a test is determined by method annotations. For example, take this partial story, taken from the JBehave documentation:

@When("the item price is $price")
@Aliases(values={"the item price becomes $price",
             "the item price equals $price"}) // multiple aliases
public void theItemPriceIs(double price) {
    // ...
}

This method would be called if the story contained either of these lines:

  • When the item price is 10
  • When the item price becomes 10
  • When the item price equals 10

Offering these different ways to express the same technical behavior can be very important for test authors for several reasons. First, they do not have to remember or look up the exact wording to make sure the test gets executed correctly. This could be alleviated with smarter editors, like the JBehave Eclipse Plugin.

Second, and in my opinion even more importantly, it helps make tests easier to read and write naturally. Being limited one exact wording for any given test step will often rip testers out of their “flow” when writing tests.

Looking at this example it is very obvious that they all start with the same phrase the item price and all end with the actual value to be used, which is written as $price in the annotations.

This adds a lot of clutter to the Java source files, duplicating many string fragments. Apart from being inconvient to write, this is also a great source of copy/paste errors which are hard to track later on.

The all new variants feature

To solve this problem, I approached the JBehave authors with an idea and a simple first patch that would demonstrate my initial thoughts. After a short discussion – which made me realize that first approach was far from ideal – the idea of a pattern language came up. I implemented and contributed this and it will be part of JBehave 3.6, allowing the example above to be written as follows:

@When("the item price {is|becomes|equals} $price")
publc void theItemPriceIs(double price) {
    // ...
}

Looking at the value of the @When annotation reveals a pair of curly braces, encapsulating alternatives that are valid at that point. Internally JBehave will create all permutations and basically treat them as if they had all been put in explicitly as aliases. Of course, variants can be used in “regular” aliases, too.

You can have any number of these option blocks in any of the @Given, @When and @Then annotations. This is a more complex example:

@Then("A {must |has to |is to |}be $x unless {it's|it is} {part of|contained in} {list |}$y")

If you do the math, this has 32 permutations (or variants, as we decided to call them in JBehave):

  • Four possible values for the first pair of braces (including the empty string)
  • Two values for the second (“it’s” or “it is”)
  • Two for the third (“part of” or “contained in”)
  • Two for the last pair (again, including the empty string, making the word “list” effectively optional)

Writing them all down explicitly would be completely impractical both initially and from a maintenance perspective. This very concise notation on the other hand makes it both easy to grasp for developers and gives test authors a great deal of flexibility.

The Eclipse Plugin

Together with Arnauld, the author of the JBehave Eclipse Plugin (source here), we also made sure it contains a variant-enabled JBehave snapshot version and can be used to try out how it feels to write and use the new syntax. Be aware, however, that in order to actually execute tests written with this new syntax currently requires you to check out JBehave from GitHub and compile a snapshot yourself, until version 3.6 is released.

Should you have tried to compile JBehave under Windows before, note that there used to be problems up until recently, that might have stopped you, but those should should now be fixed.

Ready for action

I have been using this new feature for a customer project for several weeks now without any problems, so I consider it production ready. Of course, as with any snapshot version, your mileage may vary, and depending on your personal or corporate policies you might want to wait for JBehave 3.6 to be released officially.

In any event, I hope you will find this as useful as I have and would appreciate any feedback.

Update: Just a few days after this post went live the 3.6 release was made generally available. So now there shouldn’t be anything keeping you from using this new feature :-)

Author

Daniel Schneller

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentare

  • April 11, 2012 von Mauro Talevi

    Hi Daniel, nice writeup.

    JBehave 3.6.x releases are out. Perhaps it’s be useful to update the post to this effect.

  • September 4, 2013 von Madhup Kumar

    While this is a definite improvement over repeated strings, it does hamper readability of the string. Does JBehave still support having one extra string to serve as an “easy on the eyes” readable example i.e.


    @When("the item price {is|becomes|equals|hits|rises to|} $price", "the item price equals $price")

Comment

Your email address will not be published. Required fields are marked *