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.