I need advice on how to write scenarios. First I have to explain that we have a CQRS architecture where commands and queries are separated APIs. We specify the commands with Gherkin scenarios that are used in Specflow to create tests.
In the scenarios below the domain is that of Expenses. An expense bundle is a collection of expenses. With this scenario I want to specify and test that I can't create an expense for an expense bundle that someone else created. I can only create expenses for an expenses bundle that I created.
The following approach is that I try to reuse as many steps as possible:
Background:
Given I am declarant 'Marieke'
Scenario: Not allowed to create expense for a bundle that was created by another declarant
Given the following expense bundles exist
| declarant | name | administration | status |
| Lucy | Trip to New York | Company B.V. | not submitted |
When I create an expense for the following expense bundle
| declarant | name | administration | status |
| Lucy | Trip to New York | Company B.V. | not submitted |
Then the expense is not created for the expense bundle
The name, administration and status is maybe not relevant in above example. But in other scenario's I can reuse the 'given the following expense bundles exist' step. This saves time for the developer.
In the following approach I try to write a scenario that is better readable and more specific:
Background:
Given I am declarant 'Marieke'
Scenario: Not allowed to create expense for a bundle that was created by another declarant
When I create an expense for an expense bundle that was created by another declarant
Then the expense is not created for the expense bundle
In this case the developer has to write a When step that will probably never be used again. Is this a problem?
I'm struggling with both options a lot in my scenarios. Any advice?
The way to write scenarios is too explain the WHAT and WHY and have nothing about HOW things are done. The WHAT is about claiming expense bundles and in particular that you can't claim expenses for someone else. You haven't really explained WHY that is important, you could do that in the features preamble. The scenario shouldn't give a damn about HOW expense bundles are. Other problems with the scenarios are that the language seems a bit clumsy. Again you could use the preamble to explain what an expense bundle is. So I would write something like
Feature: Claiming an expense on an expense bundle
Explain what an expense bundle is, including the concept of ownership
Explain what an expense is
Explain why Fred should not be able to claim an expense on Susan's expense bundle
Background:
Given users Fred and Susan
And Susan has an expense bundle
Scenario: Susan claims an expense
When Susan claims an expense on her bundle
Then the expense should be approved
Scenario: Fred claims an expense on Susan's bundle
When Fred claims an expense on Susan's expense bunlde
Then the expense should be rejected
This would be my starting point, and I would be using this to prompt questions like
When cuking step definition reuse is irrelevant IF you write your step definitions correctly. The correct way to write a step definitions is to make each one a single call to a helper method. In this way step definitions are reduced to performing one single function - to translate business language into a call. So it doesn't matter if a step is only used once (most aren't) because writing it is trivial.
Re-using code in helper methods is an entirely different problem, but now that we are fully in code (rather than being half way there in a step def) we can use all our normal code tools and skills to solve that problem.