I think the following is a problem which falls firmly between two stools, so please forgive me if this is the wrong place, but I think it's more of a linguistic question than a computer question.
Gherkin is a natural language specification of what a computer system should do. It is intended to read properly for English speakers, and it looks something like this:
Scenario: A user without permission may not contact another user. Given a user called Robin Given a user called Jack Given Robin has no permission to talk to Jack When Robin tries to contact Jack Then Robin will see an error message
The phrases that appear after 'Given', 'When', or 'Then' are chosen by whoever's implementing the system, and become stock phrases for use in many different scenarios, but each must always appear after an initial 'Given', 'When', or 'Then'.
The 'Given' 'When' or 'Then' do not form part of the phrase-action definition; in fact, they can all be replaced by 'And' or 'But' to semantically repeat the previous line's initial word, but I don't think that changes things in terms of the answers I'd be after here.
The problem is this: because the workings behind the Gherkin code do not distinguish between 'Given', 'When', or 'Then' there is ambiguity in some of the lines above if you change the first word.
Given Robin has no permission to talk to Jack When Robin has no permission to talk to Jack Then Robin has no permission to talk to Jack
The 'Given' line would be understood to be telling the computer to set the system we're trying to test up in such a way that Robin has no permission to talk to Jack.
The 'When' line could be understood to tell the computer to wait until some operation has made it so that Robin has no permission to talk to Jack.
The 'Then' line would be understood to be asking the computer to check that - right now - Robin has no permission to talk to Jack, and to fail the test if that isn't so.
...but we can only implement one of those three, and then we have the two remaining phrases which won't do what they look like they should be doing, were someone to accidentally write them with the wrong leading word.
Even if the system did take the first word into account, having a test that repeated the same phrase for the different leading word would be confusing - especially since we use the 'And' or 'But' words so tests read more pleasingly.
The question is: is there a useful way to choose the phrase so the Given, When, and Then senses cannot clash? Ideally, it would be a cookie-cutter sort of solution, because the people writing these scripts aren't necessarily native speakers.
For instance: in the example, it's fine to have
Given no permission for Robin to talk to Jack
because you can't substitute 'When' or 'Then' for 'Given'.
It's also fine to have
Then Robin will see an error message
because substituting 'Given' or 'When' for these would read strangely in context (particularly if we get into the habit of 'Given' only taking a noun-phrase like 'a user called Robin').
One solution would be that:
- Given always has a past tense,
- When has a present tense, and
- Then has a future tense.
... but that's a bit nuanced, particularly for people whose native languages don't have those sorts of tense.
Another would be that
- Given only takes noun-phrases, possibly with qualifiers like 'which' or 'who',
- Then is always followed by 'verify', and
- When just has a present tense SVO,
... but that leaves all 'When' phrases able to fit with both 'Given' and 'Then'.
Is there a good way to write these phrases so they read badly if preceded with the wrong one of 'Given' or 'When' or 'Then'?
Disambiguation: 'Given' 'When' and 'Then' are not considered distinct (as I myself originally expected): by way of hastily crafted example:
Given(/^I authenticate as the original user$/) do device.navigate_to('Login').enter('jane').enter('passwd').submit end
is exercised by any of
Given I authenticate as the original user When I authenticate as the original user Then I authenticate as the original user
But conventionally, 'Then' clauses should not do things, so this last should be as follows:
Then(/^verify I am authenticated as the original user$/) do unless (device.navigate_to('Profile').get_user == 'Jane') fail "Wrong user found!" end end Then verify I am authenticated as the original user
That definition would also be exercised by these unnatural versions, but hopefully no English speaker (native or otherwise) would write or accept:
Given verify I am authenticated as the original user When verify I am authenticated as the original user
(If we were testing the password reset system, I imagine we could have 'Then verify I CAN authenticate as the original user' navigating to login, trying to authenticate with the new password, and then navigating to the profile to check the current user.)
In fact, we have many steps defined as 'And(/.../)' for no earthly reason I can think of. Some implementations of Cucumber might care about the Gherkin verb, but the Ruby version we use certainly doesn't.
'Given' 'When' and 'Then' can even be replaced by '*' - perhaps so implementations can explicitly require the 'Given' 'When' or 'Then' at the start of the phrase - but then you have a potential clash if you want to use 'And' or 'But' with two otherwise identical phrases.
We actually use the '*' form for our 'tests' which walk through the application taking screenshots for our design team, product managers, and translators to see how those screens look in other languages:
Scenario Outline: Gallery Upload * I launch the app in <locale> * I do some navigation and screenshot stuff here Examples |locale| |en-gb| |es|