Snippets
Multiple shouters​
Let’s make sure that our system can handle more than one person shouting.
Add this scenario to the feature file:
# ...
Scenario: Multiple shouters
Given Lucy is at 0, 0
And Sean is at 0, 500
And Oscar is at 1100, 0
When Sean shouts
And Oscar shouts
Then Lucy should not hear Oscar
But Lucy should hear Sean
When you run SpecFlow you’ll see some errors. Look in the console output and you’ll see that SpecFlow has generated some template code for you - look for the text:
- C#
- JavaScript
- Go
No matching step definition found for one or more steps.
Undefined. Implement with the following snippet:
You can implement step definitions for undefined steps with these snippets:
- What is SpecFlow telling us?
- Should you always copy the generated snippet into your step definition file?
- Can you think of any reasons why you might have to edit the generated snippet?
Snippets​
When SpecFlow comes across a step that doesn’t match any existing step definitions it signals that there is an undefined step and the scenario containing that step is also marked as skipped or inconclusive . For each undefined step SpecFlow prints out some skeleton code (called a snippet) that you can use in your step definition code.
- C#
- JavaScript
- Go
SpecFlow also allows you to generate step definitions for undefined steps from the feature file. Use the Define steps... (or Generate Step Definitions) command from the context menu. You can either generate a new step definitions class, or you can copy the snippets to your clipboard, to paste into an existing class.
The snippet is only a suggestion. You should edit the regular expression and the method’s parameters so that they make sense in the context of your scenario.
Copy the snippets and paste them into your step definition file and run SpecFlow again. Edit the method name as well.
PendingStepException​
The default implementation of a snippet is to throw a PendingStepException. What do you think will happen when you run SpecFlow now?
You’ll see that the error has changed from undefined to pending (shown as skipped or inconclusive). The PendingStepException is treated as a special case by SpecFlow. It shows that the development team is still working on the step definition.
Signalling an error​
Comment out the line that is throwing the PendingStepException and run SpecFlow again.
The snippet that Cucumber.js prints for an undefined step is only a starting point. You should edit both the Cucumber expression and the function parameters so they make sense in the context of your scenario.
For example, Cucumber might generate something like:
Then('Lucy should not hear Oscar', function () {
// Write code here that turns the phrase above into concrete actions
return 'pending';
})
Copy the snippets into your step definition file and tidy them up (rename the function, adjust the parameter list, etc.), then run Cucumber again.
Pending steps​
The default implementation of a snippet is to return 'pending'. What do you think will happen when you run Cucumber now?
You’ll see that the status changes from undefined to pending. Returning 'pending' is treated as a special case by Cucumber: it marks the step as “not implemented yet” and still causes the build to fail, so the team can’t accidentally forget about it.
Signalling an error​
Comment out the line that returns 'pending' and run Cucumber again.
The snippet is only a suggestion. You should edit the regular expression and the method’s parameters so that they make sense in the context of your scenario. Copy the snippets and paste them into your step definition file and run godog again. You may want to edit the function name as well.
ErrPending​
The default implementation of a snippet is to return ErrPending. What do you think will happen when you run godog now?
You’ll see that the error has changed from skipped to pending. ErrPending is treated as a special case by godog. It shows that the development team is still working on the step definition.
Signalling an error​
Comment out the line returning ErrPending and run godog again. You may need to remove the return type from the function signature.
What happened this time and why?
SpecFlow considers that any step definition that doesn’t throw an exception has passed. By commenting out the "pending" statement we’ve changed this step from pending to passed.
If you now replace the commented out line with:
- C#
- JavaScript
- Go
throw new System.InvalidOperationException("bad step")
throw new Error("bad step")
return errors.New("bad step")
Run SpecFlow, you’ll see the step has gone from passed to failed.
Step Definition Lifecycle​
- C#
- JavaScript
- Go
When SpecFlow runs, it first loads all available step definitions.
Then, for each step in a scenario, it searches for matching step definitions.
- 0 matches → Undefined step → scenario fails and a snippet is emitted
- 1 match → The step definition is executed
- More than 1 match → Ambiguous step definition → scenario fails
SpecFlow will stop execution and clearly report ambiguous matches so you can fix them.
When Cucumber.js runs, it loads all step definitions from your features/step_definitions and features/support folders.
For each Gherkin step, it evaluates them in the following way:
- 0 matches → Undefined step → scenario fails and Cucumber.js prints a snippet
- 1 match → The step definition is executed
- More than 1 match → Ambiguous step definition → scenario fails
Cucumber.js throws an explicit Ambiguous Step Definitions error to prevent bad test design.
Godog follows the same general lifecycle as other Cucumber implementations when loading steps, but with one important difference:
- 0 matches → Undefined step → snippet emitted
- 1 match → The step is executed
- More than 1 match → Godog does not detect ambiguity
Instead of failing, Godog simply executes the first matching step definition it finds.
This is a divergence from the rest of the Cucumber family.
If you accidentally create two step definitions that match the same step, Godog provides no warning — it silently picks the first one.
This makes it especially important in Go to keep your step definitions well-organized and avoid overly broad regex patterns.
Get to green​
Now implement the new step definitions so that all the scenarios pass. You didn’t have to write any production code to make this scenario pass.
Is this healthy? What problems might this show?
Refactor your step definitions​
Take a look at your Step definitions. Do you notice anything you don’t like? If you do, refactor them and run SpecFlow between each change so you know you haven’t broken anything.