It seems that your question was misunderstood several times and not even your comments fixed this situation. I think at least I got your question right - at least I find it quite clear: It's not about the DSL, it's about the annotations for test steps.
Unfortunately, I can't answer why cucumber actually has different annotations for step definitions, but I know why I would have designed the API with those different annotations if I had designed it.
I'm not at all an expert for cucumber but I find the way the semantics of
Given, as described in cucumber's Gherkin specification quite contradictory. It starts sensibly:
Given steps are used to describe the initial context of the system - the scene of the scenario. It is typically something that happened in the past.
Perfect! Clearly a precondition, right? Could mean if this precondition isn't fulfilled, the scenario simply doesn't apply.
The next sentence of the same description destroys this hope:
When Cucumber executes a Given step, it will configure the system to be in a well-defined state, such as creating and configuring objects or adding data to a test database.
That's definitely not what we call separation of concerns - I'd rather call it messing up concerns.
For configuring a system to be in a well-defined state we usually have setup tasks with
@Before annotations or whatever.
In natural English (I'm not a native speaker so I might be slightly wrong)
Given introduces a precondition. And that's exactly where we COULD benefit from a specific
@Given annotation (cucumber seems to have missed this chance): it could (and I think should) annotate a boolean function that indicates whether or not the test (all the
Thens as well as further
Given conditions) are applied or not.
In simpler words: ideally, tests would never fail if a precondition isn't fulfilled. This would introduce significantly enhanced flexibility regarding test data.
Back to natural language (well, somewhat semi-natural):
"Given you accepted the meeting. When the meeting starts, Then I expect you to be in the meeting room."
Here I'm saying that all the rest only applies if you accepted the meeting. If you didn't the meeting might not start and even if it starts I won't expect you to be in the meeting room.
And this is where the value of a specific
@Given annotation could come in: a test runner could ignore all tests or all outline records that don't match the precondition. In a similar manner as
JUnit deals with
I could imagine that the designers of the API had something like this in mind. Maybe after the API design was finished, there wasn't enough time to implement it like this, or the people implementing the solution had a different opinion.
Since the test runner obviously isn't implemented in the way the different annotations suggest, I suppose it is what you seem to be perceiving: a design flaw.
Even worse this flaw leaks into the DSL. Because it means that the keywords have no specific semantics either.
And obviously enhanced semantics for the existing DSL and API can't be introduced without potentially breaking existing tests - or even more probable and even worse: hiding errors that existing tests now cover by abusive
Sorry for having wasted so many words for again not answering your question. But at least now you have an answer that addresses your question - and you have found a fellow sufferer.