Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds scenario for the ambiguous step reporting #1132

86 changes: 86 additions & 0 deletions features/docs/defining_steps/ambiguous_steps.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
Feature: Ambiguous Steps
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you tag this feature as @wip then (I think) it will be expected to fail in CI, so your branch will stay green. Once we have it passing we can remove the @wip tag.


When Cucumber searches for a step definition for a step, it might find multiple step
definitions that could match. In that case, it will give you an error that the step
definitions are ambiguous.

You can also use a `--guess` mode, where it uses magic powers to try and figure
out which of those two step definitions is most likely to be the one you meant it
to use. Use it with caution!


@wip
Scenario: Ambiguous steps

Given a file named "features/ambiguous.feature" with:
"""
Feature:

Scenario:
When a step
Then an ambiguous step

"""
And a file named "features/step_definitions.rb" with:
"""
When(/^a.*step$/) do
'foo'
end

Then(/^an ambiguous step$/) do
'bar'
end

"""
When I run `cucumber`
Then it should fail with:
"""
Ambiguous match of "an ambiguous step":

features/step_definitions.rb:1:in `/^a.*step$/'
features/step_definitions.rb:5:in `/^an ambiguous step$/'

You can run again with --guess to make Cucumber be more smart about it
(Cucumber::Ambiguous)

1 scenario (1 failed)
2 steps (1 failed, 1 passed)
0m0.012s

"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the other thing that's important for this scenario is to see the summary report:

1 scenario (1 failed)
2 steps (1 failed, 1 passed)
0m0.012s

I think we see an error like this in the current behaviour, but it also drops out of the running cucumber process and doesn't print the summary report?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tooky right now, when we have an ambiguous step and we execute it without the guess mode the summary report is not displayed. I can add it as an expected behaviour :)
Is there anything else we should take into consideration for this scenario? Thx!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MadameSheema I think we should. The issue that we based this PR on #1113 was reported because the current behaviour is wrong. When we are running without --guess we want to report this as a failed step, and continue the run as normal. So we should see the summary.

Thanks for sticking with this!



Scenario: Ambiguous steps with guess mode

Given a file named "features/ambiguous.feature" with:
"""
Feature:

Scenario:
When a step
Then an ambiguous step
"""
And a file named "features/step_definitions.rb" with:
"""
When(/^a.*step$/) do
'foo'
end

Then(/^an ambiguous step$/) do
'bar'
end
"""
When I run `cucumber -g`
Then it should pass with exactly:
"""
Feature:

Scenario: # features/ambiguous.feature:3
When a step # features/step_definitions.rb:1
Then an ambiguous step # features/step_definitions.rb:5

1 scenario (1 passed)
2 steps (2 passed)
0m0.012s

"""
7 changes: 6 additions & 1 deletion lib/cucumber/filters/activate_steps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ def initialize(step_match_search, configuration, test_step)
end

def result
return NoStepMatch.new(test_step.source.last, test_step.name) unless matches.any?
begin
return NoStepMatch.new(test_step.source.last, test_step.name) unless matches.any?
rescue Cucumber::Ambiguous => e
return AmbiguousStepMatch.new(e)
end

configuration.notify :step_activated, test_step, match
return SkippingStepMatch.new if configuration.dry_run?
match
Expand Down
13 changes: 13 additions & 0 deletions lib/cucumber/step_match.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,17 @@ def activate(test_step)
return test_step
end
end

class AmbiguousStepMatch

def initialize(error)
@error = error
end

def activate(test_step)
return test_step.with_action { raise Core::Test::Result::Ambiguous.new(@error.message) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the return keyword doing anything here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that return value of a Ruby method is the last thing evaluated? No, it's just there because that's how someone wrote the code that I am basing this code on.

I don't necessarily understand why established patterns are there, but I can at least follow them as I attempt to fix code that I am entirely unfamiliar with. :)

end

end

end