Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cucumber BDD browser testing – handling different buttons with same name but different css?

I am trying out cucumber for browser testing and am learning about BDD testing for the first time – so i am quite a beginner to BDD. I have encountered a problem and would like to know the best-practice way of solving it.

(I am using it for a node.js webapp, so it is cucumber.js and selenium WebDriverJS, but the platform should not matter for this question)

DESCRIPTION:

In tutorials for the Gherkin syntax, you often see examples on clicking a button at a specific page, like for example:

Given (something)
When I click the submit button
Then (something)

Implementing the step-definition for this step is quite simple – just make selenium locate the element with whatever css-selector happens to match the button and then make selenium click on it.

PROBLEM:

But what if you have different buttons on different pages with the same "human readable" name (i.e. the same name in the cucumber step-text), but which must be located by different css-selectors?

It seems that you can't have step-definitions which are local to features, but that all step-definitions are shared among all features. This means that if you create a step "I click the submit button", as above, the step-definition must work for testing all pages in the entire webapp which has a submit button. I am not really sure what is the proper way to do this.

QUESTION:

What is the best practice for handling this?


EXAMPLE OF THE PROBLEM:

Let's say we have 3 pages which all have a ”next” button, which does something completely different on each page and are located completely differently in the DOM. Let's say we have one feature for each of these pages. In each feature, the scenarios involving the ”next” button looks like this:

Given I am on page xyz
And ...
And I click the next button
And ...
When ...
Then ...

The problem is that on the first page, the ”next” button is perhaps located by ”.next-button”, on the second page it could be ”#someContainer .btn.btn-primary” and on the third page”#assetButtons li:nth-child(3)”. If we had a step-definition local to each feature, they could simply look like:

this.Given(/^I click the next button$/, function(callback) {
    this.driver.findElement(this.webdriver.By.css(”.next-button”).click();
    callback();
});

this.Given(/^I click the next button$/, function(callback) {
    this.driver.findElement(this.webdriver.By.css(”#someContainer .btn.btn-primary”).click();
    callback();
});

this.Given(/^I click the next button$/, function(callback) {
    this.driver.findElement(this.webdriver.By.css(”#assetButtons li:nth-child(3)”).click();
    callback();
});

But since the step-definitions are global to all features, and you naturally can't create two step-definitions for the same regex, the step-definition for "I click the next button" need to know which page we are on or which ”next” button the scenario is referring to.


Some of my own thoughts: optional reading

  • Could make the step-names less generic and make them also refer to which page the button is on: "I click the next button on the front page". The problem with this is that we already wrote in the scenario that we are on that page, so it is redundant.
  • Could make up different names for the ”next” button on the different pages – like ”front page next” and ”search page next”.
  • Could make the step-definition detect which page you are currently on and use different css-selectors depending on the page. (It could query selenium for the current URL, for example, and lookup which css-selector to use, based on both the button-name from the step and the current page).
  • Could include the css-selector in the step-text itself. But that is not quite human readable and doesn't seem like the BDD way.
  • Choose a higher abstraction level, where you don't talk about buttons, etc, but the higher level action, such as "I go to the next page in the search results". (does not seem like a good approach in general – often the exact steps are important, since the same action can often be done in different ways, and all of those paths should of course be exercised by the test. For example, if you could also go to the next page by pressing "N" or swiping, this would only test 1 of these cases (but could of course include that in the step-text too).)

But what is the RIGHT way to do it?

like image 834
DisplayName Avatar asked Oct 02 '15 15:10

DisplayName


Video Answer


1 Answers

Saying you "click on the submit button" is bad gherkin. You want to write declarative sentence that state what you are doing, but not how you are doing it. Imperative sentences like "click on this button" should not be found in your test design. I understand you point about being able to do things in more than one way, in which case that is an important detail, but abstract away as much as possible.

You state you have three next buttons that do three completely different things, state those actions in your gherkin

When I advance the image carousel
When I go to the next news page
When I view the next page of search results

As for the different paths...

When I swipe to view the next page of search results
When I use the keyboard to view the next page of search results
When I click on the next link to view the next page of search results

now we can turn that into one stepdef that has three different actions tied to it.

The point of cucumber and gherkin isn't to dry out your scenarios, it's to make it human readable, understandable by non-programmer types and a form of living documentation. If you have a few more words in there it won't be the end of the World()

like image 53
Jeff Price Avatar answered Sep 28 '22 15:09

Jeff Price