0

I have read about the Cardinal Rule of BDD from various places when writing Gherkin files.

In many of these examples, they have the following scenarios in a feature file:

Feature: Google Searching
 
  Scenario: Search from the search bar
    Given a web browser is at the Google home page
    When the user enters "panda" into the search bar
    Then links related to "panda" are shown on the results page
 
  Scenario: Image search
    Given Google search results for "panda" are shown
    When the user clicks on the "Images" link at the top of the results page
    Then images related to "panda" are shown on the results page

In the example above, it appears that the second scenario is dependent on the first scenario's state. The second scenario needs to have searched for "panda" as in the Given step, which is essentially the first 2 steps in the first scenario. So, should the Given step in the second scenario repeat the first 2 steps in the first scenario, or should the second scenario just continue from where the first scenario left off?

Assuming, if they should be run as independent scenarios, does that mean that Given step in Google search results for "panda" are shown has to have another step_definition just to repeat all the steps that were taken in the first scenario?

For example, in the step definitions, should I have something like this?

Given('a web browser is at the Google home page', () => {
   // Do a web browser is at the Google home page
}

When('the user enters "panda" into the search bar', () => {
   // Do the user enters "panda" into the search bar
}

Then('links related to "panda" are shown on the results page', () => {
   // Do links related to "panda" are shown on the results page
}

Given('Google search results for "panda" are shown', () => {
   // ** REPEAT the codes in the first 2 steps above for this step?? **
   // Do a web browser is at the Google home page
   // Do the user enters "panda" into the search bar
}

It feels a little weird to me that I have to repeat all the steps that were already made in the previous scenario to re-establish the state of the app that is already there. Also, in some occasions, going through the same steps may change the state again in the application, giving things more troublesome.

So, should the Given step in the second scenario repeat the first 2 steps in the first scenario, or should the second scenario just continue from where the first scenario left off?

Did I understand correctly that I should repeat the steps in the previous scenario when my following scenario depends on it?

1

The two ways to avoid duplication are using:

  1. Background
  2. Using page object and creating wrapper function with all prerequisite
Given('a web browser is at the Google home page', () => {
   homepage.goto()
}

When('the user enters "panda" into the search bar', () => {
   homepage.enter("panda")
}

Then('links related to "panda" are shown on the results page', () => {
  assert(a).toBe(b)
}

Given('Google search results for "panda" are shown', () => {
   homePage.searchForPanda();
}

WHere , homePage.searchForPanda(); is:

searchFOrPanda(){
    this.goto();
    this.enter("panda");
}
| improve this answer | |
-1

They are not dependant on each other. Actually, I would even argue they are not even talking about the same feature.

The first scenario is talking about the link search feature from the main page. The second one is talking about the image search feature.

These are completely unrelated, probably developed by different teams at different times (or in parallel). The image search could even come before the main page search.

To make it more clear, try to describe your features more declaratively rather than imperatively. Example:

Scenario: Links
    When I search for links with the "panda" query
    Then I receive a list of links related to "panda"
 
Scenario: Image search
    When I search for images with the "panda" query
    Then I receive a list of images related to "panda"

(You could parameterize the "list" and "image", but it can be overkill)

Tip: Generally, overusing the Given is generally an anti-pattern of imperative scenarios.

Now your scenarios are unrelated. The first one can be implemented simply by making an HTTP call to /search?q={query} and the second one to /images?q={query}.

For the UI, you can then create also declarative scenarios:

Scenario: Home page
  When I navigate to the home page
  Then I can see the links search bar


Scenario: Links page
  When I navigate to the search page
  Then I can see the image search link

(Although these probably are overkill, since (good) UI doesn't carry business logic it can be more simply described by unit tests)

| improve this answer | |
  • In terms of test scenario, they aren't dependent on each other. But in terms of the state of the application, the second scenario does depend on the first scenario. The second scenario needs to have the searched for "panda" as in its Given step, which is essentially the first 2 steps in the first scenario. So, should the 'Given` step in the second scenario repeat the first steps in the first scenario, or should the second scenario just continue from where the first scenario left off? – xenon Jun 24 at 7:03
  • There is no state machine that couples the image search to a previous link search. Look into your browser network activity and see which endpoints are called for the links and images search. Now try to call the image search with different queries: Google won't block you anyhow, it will give you image results for queries that you've search for links before. An user using a web browser interface has this coupling, but web browsers are not the only interface to Google. Google's business logic for links and images are not coupled - some UIs are limiting. UIs -> are not <- business logic. – João Farias Jun 24 at 7:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.