Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When writing a BDD feature, should I put previous user interaction into a Given step, or a When step?

Tags:

bdd

gherkin

I am trying to write requirements for a multi-step business process (via a wizard). I have many scenarios where user interactions with one screen will change whether you are allowed to pick options on another screen.

For example (I've obscured the actual business, but the process and form of the steps is nearly identical):

Feature: Personal Diagnostic Search Filter
  In order to select a Technician who offers Personal Diagnostics,
    when I've asked for a Personal Diagnostic
  As a Business Customer
  I want to limit my search to Technicians who offer Personal Diagnostics

  Background:
    Given a Business named "Big Al's Auto Supply"
      And a Customer named "Bob Test" at the "Big Al's Auto Supply" Business
      And an Account named "[email protected]" owned by "Bob Test"
      And the "[email protected]" Account has the "Repair Order Creator"
        permission
      And you log in as "[email protected]"
      And you start scheduling a new Repair Order

  Scenario: Enter the Select Technician page when Use PD is selected
    Given you select Use PD
    When you enter the Select Technician page
    Then the PD Filter should be visible
      And the PD Filter should be selected

  Scenario: Basic Search for Technicians when PD Filter is selected
    Given a Technician named "PD Technician"
      And the Technician named "PD Technician" supports PD
      And a Technician named "Non-PD Technician"
      And the Technician named "Non-PD Technician" does not support PD
      And you select Use PD
      And you enter the Select Technician page
      And you select the PD Filter
      And you select Basic Search
    When you search for Technicians with the name "Technician"
    Then your search results should contain "PD Technician"
      And your search results should not contain "Non-PD Technician"

But on the Gherkin wiki, it is recommended that you:

Avoid talking about user interaction in givens

They go on to make an exception, though:

Log in a user (An exception to the no-interaction recommendation. Things that “happened earlier” are ok).

It also is said on that page that:

The purpose of When steps is to describe the key action the user performs

What belongs in a Given and what belongs in a When if you have a lot of UI interaction?

In my first scenario, select Use PD requires UI interaction, as it is part of the wizard for creating a new Repair Order. However it is a precondition for PD Filter to be visible, and is triggered when the user enters the Select Technician page.

The first scenario might not be so bad, but the second scenario exacerbates the problem. The search is triggered when you hit Search but there are a lot of UI interactions that must be done to navigate to that page. Some of those interactions can't be glossed over, either, as Use PD must be selected for the search filter to even appear. But those UI interactions aren't the key action of the scenario.

like image 356
Merlyn Morgan-Graham Avatar asked Feb 27 '12 20:02

Merlyn Morgan-Graham


People also ask

How do you write a good BDD scenario?

The cardinal rule of BDD The cardinal rule of BDD is a one-to-one rule: One scenario should cover exactly one single, independent behavior. Focusing on one behavior at a time has several benefits: Collaboration: More focus and less confusion. Automation: Each test failure points to a unique problem.

Can we use and with given in BDD?

There's nothing preventing you from using just the keyword Given for every step in your scenario.

Do we need to follow given-when-then sequence in Cucumber?

Each step starts with Given , When , Then , And , or But . Cucumber executes each step in a scenario one at a time, in the sequence you've written them in. When Cucumber tries to execute a step, it looks for a matching step definition to execute. Keywords are not taken into account when looking for a step definition.


1 Answers

As a general rule, try as much as possible to phrase the scenario as if you're having a conversation about it, and exclude as much irrelevant information as possible.

For instance, I would love your scenarios above to read something like:

Given our customer Bob Test is scheduling a repair order
And we have two technicians: "Fred Technician" and "George Nontechnician"
When Bob Test decides he wants a Personal Diagnostic
And he selects a technician
Then the search results should only contain "Fred Technician"

Then do whatever is necessary to make those steps work - be they logging in or otherwise. Notice I haven't talked about "pages", or taken the actual steps - they should be intuitive for the user. BDD isn't about testing. It's about coming up with examples of how people are going to use the system, so that you can have conversations around those examples and explore them, find exceptions and different scenarios, etc.

Checking that the filter is visible is not valuable. The user doesn't care that the filter is visible. He cares that he can use the filter to get his results, so just do that.

In the code, I usually pass a "World" object between my steps. That can get a lot of the gubbins out of the way. I haven't used Gherkin much but I imagine it provides for a similar ability. You can store all the user details in there, which technicians you've created so that you can check it doesn't bring back "George Nontechnician" in the results, etc.

Using friendly names for roles is useful too, because people can then imagine what Fred and George look like.

Get rid of anything which isn't going to make a difference in the scenario and isn't going to help people imagine it happening. You know that Bob has permission to schedule an order because that's what he's doing - just add the necessary stuff to that step.

The "When" is the behavior you're interested in describing. In this case, you're interested in the ability to filter for Personal Diagnostics, so all the user interaction associated with behavior should be in the "When", and all previous interaction should be in the "Givens". I find it useful to try and think of a context in which the outcome is different - for instance, what happens if there are no PD technicians available? That tells me what the difference is; we'll be setting up a different context but performing the same event. Context goes in the Given, events go in the When. (This used to be much simpler before "Background" was introduced).

In general, if your eyes glaze over when you look at a scenario, you're doing something wrong.

Hope this helps.

like image 150
Lunivore Avatar answered Sep 25 '22 16:09

Lunivore