cucumber / cucumber-expressions

Human friendly alternative to Regular Expressions
MIT License
152 stars 51 forks source link

Allow free-form text in optionals #166

Open rdeltour opened 2 years ago

rdeltour commented 2 years ago

πŸ€” What's the problem you're trying to solve?

I'd like to have optional free-form text in my steps:

For instance:

Then error 123 is reported (because reasons)

The "because reasons" string isn't fixed, the content of the parenthesis varies depending on the scenario.

✨ What's your proposed solution?

It would be nice to either:

⛏ Have you considered any alternatives or workarounds?

I tried using an anonymous parameter:

error {int} is reported( \\(){}

and ignore the related parameter in the step definition.

but this is not possible in my case, since I also have a step for:

error {int} is reported {int} times( \\(){}

which causes an ambiguous step definition.

This is why I'd need to put the anonymous part within the optional:

error {int} is reported( \\({})

But then it is an illegal expression (parameters are not allowed in optionals).

I also tried using a comment at the end of the expression:

Then error 123 is reported #(because reasons)

but comments are only allowed as a start of a new line.

The only resort is to use a regex. But the expressions then get quite ugly and unreadable (the examples above are simplified, my real expressions are more complex). Or move the free-form text to its own line, but it is definitely less concise and sort of breaks the scenario flow.

These two workarounds work, but are suboptimal as they unfortunately make for less readable code.

πŸ“š Any additional context?

I recently used cucumber v4.5.4 (cucumber-java), and the following expressions just worked for my use case:

error {int} is reported( \\(.*)`
error {int} is reported {int} time(s)( \\(.*)

This stopped working when migrating to cucumber v7.8.0!

mattwynne commented 1 year ago

Would another workaround be to use a custom parameter type for your optional text? That way you get to control the regex used for matching it.

error {int} is reported{becauseReasons}

Then just ignore that parameter when it comes through to your step function.