So, I get some funny looks when I write Cucumber scenarios.
Normally what I see a lot of is scenarios written up like business specifications, like this:
Given I log into the Intergalactic Wholesale Parts shop When I add 1 Fusion Chamber to my shopping cart And I pay for it Then I should get a confirmation message
Here’s how I do it:
Given I log into the Intergalactic Wholesale Parts shop When I enter "Fusion Chamber" into the search box And I click the search button And I click the 1st view button And I click on the Add to Cart button And I click the Payments link And I enter "Zaphod" into the first name field And I enter "Beeblebrox" into the last name field And I enter my intergalactic credit card number into the credit card number field And I click on the Purchase button Then I verify that the confirmation message says "Thank you for your purchase, Zaphod! Your delivery will arrive in 3-6 Earth weeks."
Here’s why I write them this way:
It’s Actually a Lot Simpler
The first example uses 3 different steps. Each one will have some code written for the step definitions.
The second example can be written with just 4 step definitions: one for logging in, one for clicking elements, one for entering text into textfields, and one for verifying an element’s contents.
But these can be applied across all of your scenarios that you’ll ever write.
And it’s not magic. The click step for example basically does this:
- (if you’re using page objects) figure out what page you’re on
- Call up that page object dynamically
- Take the element part of the step (ex: Search, View, Add to Cart, Payments) and normalize it to what it would look like in the page object (ex: search, view, add_to_cart, payments)
- Extract the locator that’s defined for that element in the page object
- Wrap a reasonable time-limited loop around clicking on the element at that locator
Regexes Work Better
With more complex steps like in the first example above, there are a lot of ways to say the same thing. No two people will describe the process in exactly the same way.
With simpler steps like in the second example, the number of possibilities is greatly decreased.
How many different ways can you say that you’re going to click on something?
- I click the search button
- I click the search element
- I click on the search button
- I have clicked on the search element
- The user clicks the search button
A regex that can cover all combinations for the first example would be horrendous if not impossible.
But one that can cover all of the above would look like this:
/(?:I|The user) (?:clicks|have clicked|click) (?:on the|the|on) (.*) (?:button|element)$/
Regular expressions are a powerful feature of any BDD tool. If your steps are granular enough, and your regexes cover enough combinations, you can write scenarios without writing any new code. (Read more here)
We Can’t Read Peoples’ Minds
When I write a scenario, I know what’s in there because I wrote it. When you write one, it’s the same way.
If someone is getting ready to write a new test step, they have a decision to make: do I look for one that’s already made, or write one myself?
If we take time to search through the other scenarios, it takes time away from writing the test. Plus, we might think we didn’t find one and write a duplicate one. Bad for maintenance.
But: when our test steps are written based on the actions we’re doing instead of the intended results, we have a much higher chance of finding the right step, and not having to write any new code.
Shorter Tests Mask Complexity
If all of your scenarios are 3-5 lines long, it can be difficult to tell how much activity is really going on. All of the stuff in the second example is happening in the first, but it’s hidden by the more complex steps.
This makes detecting complex tests tricky. Unless you’re willing to dip into each step definition and see where the culprits are, you might have trouble seeing where there’s an unnecessarily complex test that could use refactoring.
But when all of the steps are broken out into their single actions, you can easily see when a test could maybe be broken into separate pieces. If each step makes up one action, and you find a step that does 500 things, guess what? Time to refactor.
They Shorten Your Reach
With scenarios written as in the first example: Yes anybody can write those. It’s pretty much freeform thought.
The problem is: the only people who can actually back those scenarios with runnable code are developers or automators. The audience reach for these types of tests is very short.
When writing scenarios as in the second example, yes anybody can still write those, but there’s a pretty good chance that little to no code needs to be written to get the test going.
The reach is much higher–more contributors to test scenarios (and a much faster turnaround)
They Help With Bug Reproduction
One great thing about Cucumber is that it helps with bug reproduction. If a test fails, you’ll get a colorful output of exactly where it bonked, and what was done up to that point.
If test steps are more complex, they can sometimes be ambiguous. It might not be obvious what was meant and what the test was supposed to be testing–which leads to having to ask people for clarification.
But if test steps are really granular, such as in the second example, there’s no ambiguity. The message the test is trying to convey to us, the users, is much clearer.
Much Less Code Needs Written
As said earlier: when we can boil down tests into discrete actions, we don’t need to write near as much code. The same algorithm can be applied when clicking any element on the screen–what page am I on, what element am I looking for, what’s the locator for that element, click().
And, as I wrote in an earlier post, although it’s fun to write code that tests software for you, technically we’re not paid to code. It’s perfectly valid (and encouraged!) (by me at least!) to write automation in such a way that you don’t need to write much code later.
My mutant superpower is: I see patterns in things. One pattern I see is: we make test automation out to be harder than it is.
I’ve turned that same pattern recognition skill onto test automation itself, and learned some crazy stuff in the past years. Shoot, I’m even learning breakthrough stuff every WEEK lately.
If you’re not able to release quality software as fast as you want, there’s probably something in that space that I could help you with. Let’s connect and discuss. I’d be happy to make your acquaintance.