我目前在一个功能文件中有大约 15 个场景,并且希望在它们之间共享数据。我认为上下文注入可以工作,并且它可以在单个场景中的步骤之间工作,但我无法让它将数据从一个场景传递到另一个场景。其他人如何实现这一目标?
简短回答:
没有人这样做,因为这是一个坏主意™
长答案:
如果您有对整个功能有效的数据,请将其放入功能上下文中。但这些数据无法在一种场景中修改并在另一种场景中访问。
测试将按照测试运行者确定的顺序执行。不同的跑者可能会选择不同的顺序。执行顺序可能会从运行程序的一个版本更改为下一个版本。测试之间的时间耦合或隐式依赖也会导致其他问题,例如如果我想单独运行测试会发生什么?现在它将失败,因为之前的测试尚未首先运行。如果我想并行运行测试怎么办?现在我不能,因为测试具有需要首先运行的依赖项。
那我能做什么?
我的建议是使用后台步骤(或给定中的明确步骤)来设置您的个人场景所需的数据。 Specflow 使重用这些步骤或让这些步骤重用其他步骤变得相当简单。因此,如果您需要客户和产品来创建订单,并且您有这样的场景:
Scenario: Creating a customer
Given a create a new customer called 'bob'
When I query for customers called 'bob'
Then I should get back a customer
Scenario: Creating a product
Given a create a new product called 'foo'
And 'foo' has a price of £100
When I query for products called 'foo'
Then I should get back a product
And the price should be £100
Scenario: customer places an order
Given I have a customer called 'bob'
And I have a product called 'foo' with a price £100
When 'bob' places an order for a 'foo'
Then an order for 1 'foo' should be created
最后一个场景创建了它需要的所有数据。它可以重复使用与
Given
相同的步骤(具有不同的 Given a create a new customer called 'bob'
属性),并且可以有一个新步骤 And I have a product called 'foo' with a price £100
,它只调用两个现有步骤 Given a create a new product called 'foo'
And 'foo' has a price of £100
这确保了测试是隔离的并且没有任何依赖性。
您可以在另一个类中创建一个变量
static IDictionary<String, Object> globalData
,比如Global.cs
现在,在场景 1 中:保存任何对象
Globle.globalData.Set("Key", Object);
在场景 2 中:通过对象的键检索对象并将其转换为之前的类型
var dataFromScen1 = Global.globalData.Get("Key");
通过这种方式,您可以将场景 1 中的数据使用到场景 2 中,但是在并行执行期间您将遇到问题
您可以使用FeatureContext和ScenarioContext在功能的场景和场景的步骤之间共享数据:
功能上下文从该功能中的第一个场景开始,一直到最后一个场景,同样,场景上下文从该场景中的第一步开始,一直到最后一步
private readonly FeatureContext _featureContext;
private readonly ScenarioContext _scenarioContext;
private readonly IIranMyCreditApiService _iranMyCreditApiService;
public IranMyCreditApiStepDefinitions(
FeatureContext featureContext,
ScenarioContext scenarioContext,
IIranMyCreditApiService iranMyCreditApiService)
{
_featureContext = featureContext;
_scenarioContext = scenarioContext;
_iranMyCreditApiService = iranMyCreditApiService;
}
[Given(@"User credentials are as follow")]
public void GivenUserCredentialsAreAsFollow(Table table)
{
var credentials = table.CreateInstance<UserCredentials>();
_featureContext.Add("credentials", credentials);
}
[When(@"requests access token")]
public void WhenRequestsAccessToken()
{
var credentials = _featureContext.Get<UserCredentials>("credentials");
var accessToken = _iranMyCreditApiService.GetAccessTokenAsync(new IranMyCreditApiGetAccessTokenRequestDto
{
Username = credentials.Username,
Password = credentials.Password
});
_scenarioContext.Add("access-token", accessToken);
}
[Then(@"receives a credentials")]
public void ThenReceivesACredentials(Table table)
{
// ScenarioContext.StepIsPending();
}
[When(@"refresh the Token")]
public void WhenRefreshTheToken()
{
var accessToken = _scenarioContext.Get<IranMyCreditApiGetAccessTokenResponseDto>("access-token");
// ScenarioContext.StepIsPending();
}