ttutisani / Xunit.Gherkin.Quick

BDD in .NET Core - using Xunit and Gherkin (compatible with both .NET Core and .NET)
MIT License
205 stars 29 forks source link

'And' step keyword add to more constraint #144

Open midoriiro opened 1 year ago

midoriiro commented 1 year ago

The following feature tests does not works as expected:

Feature: HostName

  Scenario: Non wild carded Localhost hostname 
    Given a hostname with name 'localhost'
    And its not wild carded
    When I verify if its equals to localhost
    Then name should be equals to localhost  
    And representation string should be 'localhost'

  Scenario: Wild carded localhost hostname 
    Given a hostname with name 'localhost'
    And its wild carded 
    Then representation string should be '*.localhost'

The issue is with the step And its not wild carded if I decorated it with 'Given' attribute the test runner will not recognized it as is. I should be able to define all my 'Given/And' steps with the 'Given' attribute in my C# code. I'm using pytest-bdd for other projects and the 'And' step does not exists as is. You can define any 'Given' step you want and the two below scenario will work as expected.

EDIT: Just adding that step 'representation string should be 'localhost'' related C# method need to be decorated with 'Then' and 'And' attribute, I should be able to decorate that method once with 'Then' attribute.

Do I missing something with this library ?

dalee-bis commented 5 months ago

I also find this somewhat unintuitive.

Given, When and Then have clear definitions of what their purpose is. From the cucumber documentation:

Having And as it's own keyword can cause issues if the text is identical. For example:

Given something is set
And no items are on the queue
When something runs
Then something is true
And no items are on the queue

In the above, And no items are on the queue could be either a setup or an assertion depending on where it is placed. At the moment, I believe this requires re-wording the text to differentiate, or avoiding And by using multiple Given or Then statements.

From the cucumber documentation, I would expect And (or *) to replicate the previously used keyword.

https://cucumber.io/docs/gherkin/reference/

ttutisani commented 5 months ago

I don't follow what's not working. Please provide the Gherkin and C# code both.

dalee-bis commented 5 months ago

@ttutisani It's not that it's not working. It is functioning exactly according to the documentation for this project and there is a simple workaround so it's only a minor issue.

To be fair, the cucumber documentation is also rather ambiguous about how it should function. I'm not sure how other projects handle this.

If you have successive Given’s or Then’s, you could write:

Example: Multiple Givens Given one thing Given another thing Given yet another thing When I open my eyes Then I should see something Then I shouldn't see something else

Or, you could make the example more fluidly structured by replacing the successive Given’s or Then’s with And’s and But’s:

Example: Multiple Givens Given one thing And another thing And yet another thing When I open my eyes Then I should see something But I shouldn't see something else

Source: https://cucumber.io/docs/gherkin/reference/

I would read this as the And should replicate the previous keyword. So an And after a Given would be interpreted as a Given.

With the current implementation, there can be conflicting And statements. So using the same style as the excerpt above to explain...

The Gherkin text from my example could be written as:

Given something is set
Given no items are on the queue
When something runs
Then something is true
Then no items are on the queue

Which would result in C# code something like:

[Given("no items are on the queue")]
public void GivenNoItemsAreOnTheQueue()
{
    queue.Clear();
    Assert.Empty(queue.Items);
}

[Then("no items are on the queue")]
public void ThenNoItemsAreOnTheQueue()
{
    Assert.Empty(queue.Items);
}

But if you introduce And into this:

Given something is set
And no items are on the queue
When something runs
Then something is true
And no items are on the queue
[Given("no items are on the queue")]
[And("no items are on the queue")]
public void GivenNoItemsAreOnTheQueue()
{
    queue.Clear();
    Assert.Empty(queue.Items);
}

[Then("no items are on the queue")]
[And("no items are on the queue")]
public void ThenNoItemsAreOnTheQueue()
{
    Assert.Empty(queue.Items);
}

There are now two And attributes with the same text. I've not checked this but I expect it would throw an exception not knowing which method to use.

The workaround at the moment would be to avoid using And, or change the text so that it doesn't match:

Given something is set
And no items are on the queue
When something runs
Then something is true
And the queue is empty
ttutisani commented 5 months ago

Understood, thanks for clarifying!

I agree that it would be better if the And is treated as the last-found given/when/then, that would make it more intuitive.

To be clear, Gherkin is not strict on such rules at all, and the framework's current state reflects that.