问题
I trying to experiment with Specflow. So I am writing functional tests for a REST API and have created a couple of step definitions, say CreatePersonStepDefinitions
and GetPeopleStepDefinition
Those extend CommonStepDefinition
, which provides things like:
[Given(@"a valid API key is given")]
public void AValidApiKeyIsGiven()
{
ApiKey = "Some Api Key";
}
[Then(@"the response HTTP code should be (.*)")]
public void ThenTheStatusCodeShouldBe(int statusCode)
{
Assert.AreEqual (statusCode, (int)Response.StatusCode);
}
This is to be able to run scenarios like
Given I am retrieving all people
And an invalid API key is given
When I make the call
Then the response HTTP code should be 200
And the API response code is 104
And the API call didn't take more than 200 milliseconds
So there are several common steps between step definitions. I understand that I cannot do this as Steps are global. What I wanted to ask is whats the best way (i.e. best practise) to achieve this without duplicating the same steps in every step definition.
Thanks
回答1:
Because steps are global you don't need to duplicate them in every step definition, you can just use them in ALL features, and specflow will call them.
If your real question is how do I share the ApiKey and Response between my features steps and my common steps there are a few ways but what I would recommend is to use the context injection approqach from the link. I would create context objects and pass these to your step classes. Specflow has a simple DI framework which will do this automatically (most of the time) for you.
I would create something like this:
public class SecurityContext
{
public string ApiKey {get;set;}
}
public class ResponseContext
{
public IHttpResponse Response{get;set;}
}
[Binding]
public class CommonSteps
{
private SecurityContext securityContext;
private ResponseContext responseContext;
public CommonSteps(SecurityContext securityContext,ResponseContext responseContext)
{
this.securityContext = securityContext;
this.responseContext = responseContext;
}
[Given(@"a valid API key is given")]
public void AValidApiKeyIsGiven()
{
securityContext.ApiKey = "Some Api Key";
}
[Then(@"the response HTTP code should be (.*)")]
public void ThenTheStatusCodeShouldBe(int statusCode)
{
Assert.AreEqual (statusCode, (int)responseContext.Response.StatusCode);
}
}
public class MyFeatureSteps
{
private SecurityContext securityContext;
private ResponseContext responseContext;
public MyFeatureSteps(SecurityContext securityContext,ResponseContext responseContext)
{
this.securityContext = securityContext;
this.responseContext = responseContext;
}
///Then in your feature steps you can use the Api key you set and set the response
}
you might even consider not having Common
steps as this get just be a big bucket for everything that is not feature specific, but what we usually do is to break the step classes into something like SecuritySteps
which would just take the SecurityContext
and ResponseSteps
which would just take the ResponseContext
来源:https://stackoverflow.com/questions/32671707/extending-stepdefinitions-in-specflow