What am I doing wrong in bdd / gherkin?

55 Views Asked by At

I'm learning about BDD, Behavior-Driven Development, and while I caught the "idea" of having examples of the system's behavior, which we can execute and through which we can develop it, I'm stuck in how to write the scenarios correctly (using gherkin) intended to ease the transition between natural language to steps...

Let's see it. I'm working currently in a Sign Up service.

My current problem is in this piece:

  Scenario: Successful registration
      Given that a user wants to register
      And is not registered
      When he enters his credentials
      And they are correct
      Then the system should register him

what is broken down in steps as the following...

   @Dado("that a user wants to register")
    public void que_un_usuario_desea_registrarse() {
        name = "Marcos";
        surname = "Perez";
        email = "[email protected]";
        cardId = "23432423";
        marcos = new User(name,surname,email,cardId);
    }

    @Dado("is not registered")
    public void no_esta_registrado() {
        fakeDB.removeIfExists(marcos);
    }

    @Cuando("he enters his credentials")
    public void introduzca_sus_credenciales() {
// This is an empty space because i have no idea of what should be in
    }

    @Cuando("they are correct")
    public void estas_sean_correctas() {
        logUpService.logUp(name, surname, email, cardId, fakeDB);
    }

    @Entonces("the system should register him")
    public void el_sistema_deberia_registrarlo() {
        assertEquals(marcos.hashCode(), fakeDB.persisted.hashCode());
    }

I've tried to change how the requirement is expressed, but i'm still stucked with

  1. How is a no-software thing like "User wants to register" supposed to be implemented in a step?

  2. Although I'm using a kind of test double (called "fakeDB") which returns the same User instance that the log up service (called "logUpService") is sending to its "Storage" component, I'm not pretty sure if that is the best way to assert on the "Then" clause.

I'm strongly interested in learn about this, so I will very happy to read your suggestions.

2

There are 2 best solutions below

3
Lunivore On

I find it useful to think about the capability being exercised. What is a user able to do in this scenario?

A user is able to register.

Exercising that capability (or trying to, for unhappy paths) gives us the When. Usually there is only one When in a scenario. So now we can write that:

When Marco registers with details <details go here>

The outcome should ideally be something valuable. Why are they registering? What happens once they've registered?

Then Marco should see the home page
And Marco should be logged in to his account.

(That last step would check the relevant icons etc. that show someone is logged in.)

Now we can go back to the context: what needs to be true for this scenario to take place? It might be things like:

Given Marco is not already registered
And Marco has a valid email address at [email protected]

You'll notice that I haven't included anything about what the user wants. From a system perspective, it doesn't matter. Maybe someone is forcing Marco to log in and he doesn't actually want to at all! It doesn't change the system behaviour.

You can certainly include that step if you find it useful, but I would leave it blank and not put any automation in there if you do.

Here's the scenario in total:

Given Marco is not already registered
And Marco has a valid email address at [email protected]
When Marco registers with 
    email: [email protected], 
    name: Marco Perez, 
    card id: 23432423
Then Marco should see the home page
And Marco should be logged in to his account.

If your BDD tool doesn't allow multi-line steps, you can put Marco's information into a background table or into Givens, then shorten the When to "Marco registers with his details". There should still only be one When in this case.

I wouldn't use the FakeDB as a way of verifying the outcome; certainly not alone. You're looking at the system from the user's perspective, so look for their desired outcome too.

0
Barnaby Golden On

Typically the "User wants to register" step would be implemented by a UI action such as clicking on a register button.

For the test I would be looking for two separate things:

  • Is the user registered? Typically this would be checked using an isRegistered() method. The important part of this is for you to identify what is the unique information that determines if they are registered. Perhaps their card id? isRegistered(cardId).

  • Is the stored data for the user the same as the data they submitted during registration.