Showing posts with label JBehave. Show all posts
Showing posts with label JBehave. Show all posts

2011-12-03

Choice between Given, When, Then

Writing your first Stories for Behavior Driven Development (BDD) you will soon come to the point when it is about to consider if a step is Given, if it is When or if it is Then. So what’s better:

Given Application A is running
When I log in

or is it better to write:

Given Application A is running
Given I logged in

Mind that the second Given could be replaced by And. I just wanted to emphasize that it is now a Given statement.

My answer: It depends. Derived from one of my previous posts Given, When, Then – Which Tense? my conclusion is:

  • Given: Should summarize which is not actually in focus of the story but required to understand the context of the test or state of the system under test.
  • When: Describes the steps required to reach the state you want to test. If steps cannot be taken your applications behavior might have changed but your story is not necessarily broken. Thus if When statements are written with help of JUnit you should consider to user org.junit.Assume to validate the state.
  • Then: This is the state you want to test. If this fails your story is for sure broken. Thus again if you are using JUnit you would use org.junit.Assert in here.

Considering this here are the three stories which deal with log in:

Given Application A is running
When I log in as user with username N
Then I will see the UI of Application A
And I will see username N somewhere on the screen

So here the log in process is part of the steps to reach the state to test, which is to have access to the application’s UI.

Given Application A is running
And I am logged in as user N
When I change my password to password P
Then I will receive a notification email
And my credentials change to username N with password P

Thus log is only required to understand the context/state of the system. And finally:

Given Application A is running
And there is a registered user N
When the login screen appears
Then I am able to log in with valid credentials for user N

This time the log in process is in focus of the scenario we want to test.

Is this guidance of any help for you? Or do you have another pattern when to choose When, when to choose Given and when to choose Then?

2011-11-25

BDD Steps: Free your mind!

I just started to implement the steps for something like the following story:

It started to get complicate as I was in need of a parameter converter (JBehave) which converts “Article” into an object representing the document type. After some time I realized that the story was again written by someone who knows the product in too much detail.

I stopped work on the converter and rewrote the story – and now the story tells what the customer really wants:

where “rendered property” (we are editing web-contents here) is another learning to specify cleanly what you want – here: If you want to show the text in the preview later on you first should ensure to choose a property which will become a visible part of the web page.

And suddenly there was no need for a parameter converter anylonger.

I don’t vote against parameter converters – I just have to repeat to myself again and again: Write what you (as customer) really want! – and don’t try to incorporate the knowledge about the test environment (here: document type of type Article exists) into the story.

Doing so will keep your tests more robust over time (perhaps one day there is no “Article” anylonger) and sometimes (as it was here) it will even ease your test code.

For how to handle the references in the stories above you might want to read my blog post “BDD Design Patterns: Reference Tracker”.

2011-11-22

BDD Design Patterns: Reference Tracker

Writing BDD stories and implementing the steps you will soon come to the point to deal with references between steps, like:

Given I have a document A on disk
When I open document A
And I change the content of document A
And I save document A
Then document A on disk will be updated
And document A will contain the new content

Reading this you will find two references to be tracked:

  • the document itself
  • the content which got changed

I found many implemented solutions for this pattern, each of them a little different. Some using global variables and a central class to hold all steps, others using singletons.

Summarizing the solutions I found I introduced a new pattern which got quite positive feedback: the Reference Tracker.

The basic idea is that you will have three items to track:

  1. the type of the reference (here: document or content)
  2. the reference name (here: A once, unnamed the other)
  3. the actual reference value

Having this you just need two methods to feed the tracker and to retrieve values from it:

The cleanup() method should ensure that you don’t collide with new scenarios. In JBehave context you should call it in @AfterScenario.

For the example above you would implement the interface with:

  • Key-Type: String (“document”, “content”)
  • Value-Type: Object (once file, once String, XML or whatever)

The complete Gist contains another implementation called TypedReferenceTracker which assumes that the value-type is the same as the key, so that there is a class for documents and one for contents. It makes the getter a little easier to use.

Find the complete Gist at GitHub.

2011-11-08

BDD Steps: Be specifically unspecific

I just participated in an interesting sprint retrospective meeting where the problem came up that step definitions are sometimes very ambiguous as well as for the human reader as for the JBehave parser.
Here is one typical though virtual example:

Problems of the steps above:
  • The Given statement contains information with no value for the customer. The customer is not interested about the username and the password. Thus even with this start it will be hard to understand the complete scenario.
  • The first When statement misses important information. Is this a valid or invalid login? When implementing this step developers might as side effect create a new user with these credentials. The next one re-using this step in a story might not know about this side effect.
  • The second When statement collides with the first one if you parse parameters. If you are unlucky you even might have two step definitions in your code:

    with the effect that it is up to JBehave if the user logs in as "named qwert" or "qwert" depending on which step it has chosen to take.
What we can learn from it is to be specifically unspecific... or to be more precise, apply these rules to your stories:
  1. Give every step a value (if not even every single phrase).
    In the first statement it might be better to state either that I logged in as normal user or that I logged in as a specific user I want to reference later in the test.
  2. Never specify field values explicitly.
    Actually this refers to the first rule as most of the time the real content of a field is not important. It might be important of what type the input is (alphabetical, numeric, valid login) but most of the time the real input is not important.
  3. Be as specific as needed and as unspecific as possible.
    Perhaps the rule with the most problems to decide what is the best approach. It means that you should not be too specific for example by stating "When I fill the username field with username qwert" as perhaps some day your username field disappears and is replaced by a fingerprint scanner. But you should state if the login is valid or invalid and if it is invalid: if it is because the user doesn't exist or because the password is wrong.
So the following steps will be easier to understand... even without the context of prior or subsequent steps. And they never state any field value:

2011-11-07

Then vs. Period–Writing JBehave Stories

Writing stories/scenarios which get automatically executed as in JBehave is sometimes a special art – at least if you want to re-use existing step definitions. Sticking to some rules will help to make your steps re-usable, one is for example to agree on the tense to use in your stories as I mentioned earlier.

I stumbled across another rule when I was writing steps and then implementing them. Here an example:

Implementing the @Then step might look like this:

Referring to the title of this post you might guess the problem: For some yet unknown reason the first scenario marked the @Then step as pending. Solution after hours of debugging (just kidding): The period at the end of the sentence is missing in the step definition!

So you could add an @Alias for this (no, really, you don't want that). Next time you will stumble across parameterized steps where the parameter is at the end of the sentence. Suddenly the parameter will get a period at the end. And suddenly usernames for example don’t match.

The solution is quite simple. I found it in some existing stories of a team:

Don’t use periods!

Really, I hate this approach as from my point of view every new rule will prevent stories to be written. But I think this rule helps so much, that you should stick to it.

2011-11-01

Behavior Driven What? BDA Waiting...

This is the start of a small series about BDA - Behavior Driven Antipatterns. I am currently reading through a bunch of JBehave stories at my company to give tips how to optimize them. While doing so I got some insights on antipatterns in writing these stories and I would like to share them with you. My first issue of this series is about Waiting. Waiting is especially an issue when testing AJAX applications.

First lets have a look of an example close to one I found at some locations:


Why do we have to wait anyway? Because we have to deal with asynchronous events - especially when dealing with Web User Interfaces. If we press a button there will be an unpredictable roundtrip until we get the response which we want to validate.

Why is the given approach an antipattern? Because stories (at first glance) should be stories written by customers or their representatives like the product owner (Scrum). And guess what? Customers don't want to wait. Never! So they would never state anything about waiting. at first glance is a lookahead on an idea I am developing about different flavors of stories. I hope to come to that later in this series.

So what are the alternatives? Giving a reason... If you have many places in your story files which look like this I recommend to extend the step a little:


What's the advantage? When you added the pause to your tests you knew the reason why you did that. When other developers read the same line sometimes later they won't. So giving a hint why you decided to wait will help others to understand your thoughts and perhaps speed up the tests because they reduce the time to wait or they find some better solution. Will come to that one later.

Alternative: Hide waiting... This solution comes closer to what the customer really wants which is not to wait. Just remove the wait step. Now you need to add some Thread.sleep() to your step definition instead. You just have to decide if to add it to the @Given or @Then step. To decide keep in mind if you will reuse the step and if perhaps in other contexts waiting will just slow down the test for no reason.

Recommended Alternative: Busy waiting... The best alternative to any sleep approach is to do busy waiting. I would recommend to add busy waiting to the step which requires a precondition before it can start. This would be the @Then step in the given scenario. To do busy waiting there are several alternatives out there and many implementations in your company, I bet. But if you are already using Selenium and/or WebDriver you might want to use one of these examples:


Both examples use the same trick which fits the basic principle of busy waiting which is:

  • Check if condition is met.
  • If it is met stop waiting.
  • If it isn't met wait a little and try again.
  • If the condition isn't met within a given total time (timeout) abort with a failure.

The advantages are:

  • The step clearly fails with a precondition not met if there is a problem. Otherwise the step will fail later on with no real hint what happened.
  • If the precondition is met fast the test will continue fast.
  • Your tests are more robust because you may even raise the time to wait without many headaches.
  • The story is cleaned from any waiting issues.