Tyler-Keith-Thompson / CucumberSwift

A lightweight swift Cucumber implementation
https://tyler-keith-thompson.github.io/CucumberSwift/documentation/cucumberswift/
MIT License
74 stars 19 forks source link

Usage of symbols < and > in data table produce errors in non Outline Scenarios. #82

Closed Hsilgos closed 1 year ago

Hsilgos commented 1 year ago

I have several tests where I use symbols < and >, for example

  Scenario: Scenario description
    Given Something
    When Something is done
    Then I should receive data with the following properties:
      | position | <1400.0, 1600.0> |

  Scenario: Scenario description
    Given Something
    When Something is done
    Then the data looks like:
      | speed   |  <9000 |
      | size       | >12000 |

It's quite descriptive sometimes to use symbols < and > and there is no any sense to forbid them in simple, not Outline Scenarios, but CucumberSwift generates errors

Assertions: Assertion Failure at CucumberTest.swift:99: XCTAssertTrue failed - Gherkin language errors found:
File: foo.feature, table header not closed in table cell
File: bar.feature, table header <9000> not found

Cucumber-jvm is ok with such scenarios (sorry that I constantly refers to it, but I reuse the same scenarios in Java and Swift and I'd like to make them as much compatible as possible).

It doesn't look like complex issue, unless Lexer is again involved here :-)

Tyler-Keith-Thompson commented 1 year ago

Yeah, the lexer is responsible for discovering and sharing that error. I don't think a fix will be too bad, though. I've been debating pulling in https://github.com/pointfreeco/swift-parsing as a replacement to the current Lexer implementation. It'll make some of these fixes trivial, but it'll also mean a slower lexer and a 3rd party dependency.

Hsilgos commented 1 year ago

@Tyler-Keith-Thompson , I tried to fix this issue, it indeed doesn't look complicated, but I'm frustrated with tests now. For example:

func testTableHeaderNotFound() {
        Cucumber.shared.parseIntoFeatures("""
        Feature: Sample

        Scenario: minimalistic
            Given a simple data table
            | <foo> | <bar> |
        """, uri: "table_header_not_found.feature")
        XCTAssert(Gherkin.errors.contains("File: table_header_not_found.feature, table header <foo> not found"))
        XCTAssert(Gherkin.errors.contains("File: table_header_not_found.feature, table header <bar> not found"))
    }

I didn't find any Gherkin related documentation where headers are used in simple scenario. Only in Outline Scenarios. So when I do my fix and change Scenario -> Outline Scenario in this test then this test fails, because related code just never executed (i.e. symbols "<" and ">" are treated just as simple text in simple Scenario)

Another example of similar test in: Tests/CucumberSwiftTests/testdata/good/ScenarioOutline/scenario_outline.feature:

Feature: Minimal Scenario Outline

  Scenario: minimalistic
    Given the <what>

    Examples:
      | what       |
      | minimalism |

But it doesn't fail.

Could you point me to Gherkin language documentation which you used when you made headers available in simple Scenarios?

Tyler-Keith-Thompson commented 1 year ago

I used https://github.com/cucumber/gherkin

Specifically their good/bad test data for most everything. https://github.com/cucumber/gherkin/tree/main/testdata/good

Pretty sure this is in there. Anything with "minimalistic" or "minimal" or "minimalism" generally comes from there.

Hsilgos commented 1 year ago

@Tyler-Keith-Thompson I went through tests which you mentioned and I haven't found any special cases about usage of "<" and ">". Then I decided to experiment and I found that at least Java Cucumber doesn't care about "<" and ">". All the following examples work:

# Feature
  Scenario: playground
    When I do <playground> setup

#Java
@When("I do <playground> setup")
public void iDoPlygroundSetup()
{}
# Feature
  Scenario: playground
    When I do <playground> setup

#Java
@When("I do (.*) setup")
public void iDoPlygroundSetup(String text)
{
    assertEquals(text, "<playground");
}

@When("I do <playground setup")
public void iDoPlygroundSetup()
{}
# Feature
Scenario Outline: playground
    When I do <playground> setup

    Examples:
    |setup|
    |setup|

#Java
@When("I do (.*) setup")
public void iDoPlygroundSetup(String text)
{
    assertEquals(text, "<playground>");
}
# Feature
Scenario Outline: playground
    When I do <playground setup

    Examples:
    |setup|
    |setup|

#Java
@When("I do (.*) setup")
public void iDoPlygroundSetup(String text)
{
    assertEquals(text, "<playground");
}

And so on. I didn't see any errors, and only when <header> matched the same header in examples then cucumber replaced the <header> with proper value from column:

# Feature
Scenario Outline: playground
    When I do <playground> setup

    Examples:
    |playground|
    |test|

#Java
@When("I do (.*) setup")
public void iDoPlygroundSetup(String text)
{
    assertEquals(text, "test");
}

I conclude that there normally no any errors. How about to make existing related errors optional and configure with an option strictHeadersCheck?

Tyler-Keith-Thompson commented 1 year ago

Oh weird, maybe I got overzealous with trying to be helpful regarding errors around table headers? If it's not in that official gherkin repo then yeah, we can totally make a configuration for it.

Tyler-Keith-Thompson commented 1 year ago

This should be resolved in CucumberSwift v4.2.2