I am trying to reuse SpecFlow steps for testing two similar UI components. Currently my solution has a generic base class which contains the shared steps and two child classes to contain all the remaining steps, like this:
[Binding]
public class ChildSteps1 : BaseSteps<MyType1>
{
...
[When(@"I do action one")]
public void WhenIDoActionOne()
{
...
}
...
}
public class BaseSteps<T>
where T : ...
{
...
[When(@"I do action two")]
public void WhenIDoActionTwo()
{
...
}
...
}
The problem I run into is that the steps in the generic class (e.g. "action two" in this example) is not highlighted or navigatable from the .feature files (the text is purple and I cannot jump to definition by pressing F12). Normally this could be fixed by adding the "[Binding]" attribute to the base class but my base class is generic and adding this attribute will cause a run-time exception. Is there a clean remedy to this problem?
If you are simply trying to group common Step Definitions into a single class (or assembly, or whatever), then you don't need to use a base class. It is enough to put your steps in a standard class that has the [Binding] attribute - SpecFlow will pick up those steps and allow navigation from the .feature files.
If this class is in another assembly then you can tell SpecFlow where to look by editing your config file - see the <stepAssemblies> entry here: http://www.specflow.org/documentation/Configuration/
If that doesn't answer your question, as Fresh asks in his comment, it might help if you explained why you need to use a Generic base class.
Edit:
Based on your comments I can think of two possible additions to my answer:
1) Your steps are too generic and probably shouldn't be shared. As an example, if you had a step along the lines of 'When I submit the form', then this is probably too vague - which form? how do you submit it? this could be different depending on what page/control you are interacting with. Instead of re-using the step for different forms, a better approach might be to be more explicit in your steps - 'when I submit the sales form'. You have more steps but you don't have this problem of re-use that you are struggling with.
2) Perhaps the use of tags combined with Scenario/Feature Context is the answer. You say that you are using generic base classes in order to decide which driver classes to use. Another way to get this behaviour could be to use [BeforeFeature] or [BeforeScenario] setup methods, check the existence of specific tags, and then inject your specific driver into the Context. Your steps (which no longer need any base classes or generics) can grab the driver from the Context and call the appropriate methods.
See http://www.specflow.org/documentation/ScenarioContext.Current/ for details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With