大家好!
在Habré上有关于SpecFlow的出色文章。 我想深入探讨这个主题,并讨论并行运行测试,在步骤之间传递数据,辅助助手,转换,挂钩以及使用Json作为数据源。
步骤之间的并行执行和数据传输
在步骤之间传输数据的
文档中,我们找到以下示例:
此代码使用字符串键。 记住并键入它们是很乏味的。
通过创建具有必要属性的静态类可以解决此问题:
public static class ScenarioData { public static ComplexObject Complex { get => ScenarioContext.Current.Get<ComplexObject>(nameof(Complex)); set => ScenarioContext.Current.Set(value, nameof(Complex)); } }
数据传输现在看起来像这样:
不幸的是,在并行运行测试之前,我们将
无法使用ScenarioContext.Current,除非我们进行必要的注入
因此,我们解决了两个问题:摆脱了字符串键,并提供了并行运行测试的功能。 对于那些想尝试的人,我创建了一个
小项目。协助助手和转变
考虑下一步
When user starts rendering | SourceType | PageOrientation | PageMediaSizeName | | set-01-valid | Landscape | A4 |
经常这样从表中减去数据
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var sourceType = table.Rows.First()["SourceType"]; var pageOrientation = table.Rows.First()["PageOrientation"]; var pageMediaSizeName = table.Rows.First()["PageMediaSizeName"]; ... }
使用
Assist Helper,读取测试数据看起来更加优雅。 我们需要创建一个具有适当属性的模型:
public class StartRenderingRequest { public string SourceType { get; set; } public string PageMediaSizeName { get; set; } public string PageOrientation { get; set; } }
并在CreateInstance中使用它
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(Table table) { var request = table.CreateInstance<StartRenderingRequest>(); ... }
使用
Transformations ,可以进一步简化测试步骤的描述。
定义转换:
[Binding] public class Transforms { [StepArgumentTransformation] public StartRenderingRequest StartRenderingRequestTransform(Table table) { return table.CreateInstance<StartRenderingRequest>(); } }
现在,我们可以在步骤中使用所需的类型作为参数:
[When(@"user starts Rendering")] public async Task WhenUserStartsRendering(StartRenderingRequest request) {
对于那些想尝试的人-
同一项目。挂钩并使用Json作为测试数据的来源
对于简单的测试数据,SpecFlow表已绰绰有余。 但是,有些测试方案具有大量参数和/或复杂的数据结构。 为了使用这样的测试数据,同时保持脚本的可读性,我们需要
Hooks 。 我们将使用[BeforeScenario]挂钩从Json文件中读取必要的数据。 为此,请在脚本级别定义特殊
标签 @jsonDataSource @jsonDataSourcePath:DataSource\FooResponse.json Scenario: Validate Foo functionality Given user has access to the Application Service When user invokes Foo functionality | FooRequestValue | | input | Then Foo functionality should complete successfully
并将处理逻辑添加到钩子中:
[BeforeScenario("jsonDataSource")] public void BeforeScenario() { var tags = ScenarioContext.ScenarioInfo.Tags; var jsonDataSourcePathTag = tags.Single(i => i.StartsWith(TagJsonDataSourcePath)); var jsonDataSourceRelativePath = jsonDataSourcePathTag.Split(':')[1]; var jsonDataSourcePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, jsonDataSourceRelativePath); var jsonRaw = File.ReadAllText(jsonDataSourcePath); ScenarioData.JsonDataSource = jsonRaw; }
此代码将json文件的内容(文件的相对路径)减去到一个字符串变量中,并将其保存到脚本数据(ScenarioData.JsonDataSource)中。 因此,我们可以在需要时使用此数据
[Then(@"Foo functionality should complete successfully")] public void ThenFooFunctionalityShouldCompleteSuccessfully() { var actual = ScenarioData.FooResponse; var expected = JsonConvert.DeserializeObject<FooResponse>(ScenarioData.JsonDataSource); actual.FooResponseValue.Should().Be(expected.FooResponseValue); }
由于Json中可能有很多数据,因此也可以通过标签来实现测试数据的更新。 有兴趣的人可以在同一
项目中查看示例
。参考文献
1.
黄瓜2.
小黄瓜3.
SpecFlow文档4.
SpecFlow Wiki5.
可执行规范:SpecFlow A至Z6.
数据驱动测试和SpecFlow