SpecFlow scoped bindings

Some background: on the site I’m currently working with searching is a key part and a search might exist in many different context and differ somewhat depending on the context. When writing a feature file I’d typically end up with something like this

Feature: Main search

Scenario: ...
  Given I search for "bla"
  And I select search result 1
  Then...
Feature: Search widget

Scenario: ...
  Given I search for "bla"
  And I select search result 1
  Then...

Duplicated steps

When running these scenarios SpecFlow will execute the same method for the steps defined above. This is a good thing since it allows us reuse steps defined in other features and thus avoid duplication. However, in this case it causes a bit of a pickle since while the scenarios are similar in a natural language sort of way what will be executed in the actual step differs quite heavily. For instance, the html structure might be different and the widget could have some additional ajax functionality to take into consideration. The bottom line is that the code we want executed in the Given I search… step differs between the two features.

A less than optimal solution

One way to make sure we can execute different methods depending on the context is to make sure the step name are unique.

Feature: Search widget

Scenario: ...
  Given I search for "bla" on the search widget
  And I select search result 1 on the search widget
  Then...

While this solves the problem of making the steps unique, this just adds a lot of noise to the steps. The feature is already called search widget and including this part in most of the steps feels very redundant since we already know we are in the context of describing the search widget.

Anti-patterns to the rescue!

SpecFlow comes with a concept of scoping bindings to either feature, scenario or tags. This allows us to inform SpecFlow that certain steps should only be associated with the scope in question. For the examples used above I scoped the step definitions to the feature since that seemed the most appropriate.

[Binding]
[Scope(Feature = "Search widget")] 
public class SearchWidgetSteps

Keep in mind that coupling your step definitions to features is considered a gherkin anti-pattern but in this case it felt like a good enough compromise. But perhaps there is a better solution?