65.9K
CodeProject 正在变化。 阅读更多。
Home

SpecFlow 高级用法:正确处理参数的 4 种方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (3投票s)

2016年11月14日

Ms-PL

4分钟阅读

viewsIcon

18369

了解如何处理需要多个参数的更复杂场景。使用方案大纲示例表创建数据驱动的测试。

  

引言

Specflow 系列 的文章部分,您可以了解如何遵循 BDD 范例编写可被业务用户理解的验收测试。在这篇文章中,我将与您分享在功能文件中处理参数的四种方法。

1. 创建带有可选参数的步骤

用例

Convert Kilowatt Hours to Newton Meters Different Format

之前的示例 中,我们编写了将千瓦时转换为牛顿米的测试。输入 kWh 的步骤如下:“And type "30" kWh”。在转换器应用程序中,有一个新功能 - 更改答案的格式,我们需要对其进行测试。我们希望能够用一个参数来扩展之前的步骤,该参数用于选择格式 - “And type 30 kWh in Fractions format”。我们希望同时支持这两种步骤。

功能方案

Scenario: Successfully Convert Kilowatt-hours to Newton-meters
	When I navigate to Metric Conversions
	And navigate to Energy and power section
	And navigate to Kilowatt-hours
	And choose conversions to Newton-meters
	And type "30" kWh
	Then assert that 1.080000e+8 Nm are displayed as answer

Scenario: Successfully Convert Kilowatt-hours to Newton-meters in Fractions format
	When I navigate to Metric Conversions
	And navigate to Energy and power section
	And navigate to Kilowatt-hours
	And choose conversions to Newton-meters
	And type 30 kWh in Fractions format
	Then assert that 1079999999⁄64 Nm are displayed as answer

测试几乎相同,只是“Type”步骤有细微差别。

绑定方法

[When(@"type (.*) kWh")]
public void WhenTypeKWh(double kWh)
{
    this.kilowattHoursPage.ConvertKilowattHoursToNewtonMeters(kWh);
}

[When(@"type (.*) kWh in (.*) format")]
public void WhenTypeKWhInFormat(double kWh, Format format)
{
    this.kilowattHoursPage.ConvertKilowattHoursToNewtonMeters(kWh, format);
}

为了同时支持这两种步骤,您需要创建两个独立的绑定方法。第一个方法接受一个参数,第二个方法接受两个参数。

public void ConvertKilowattHoursToNewtonMeters(
    double kWh,
    Format format = CelsiusFahrenheitPage.Format.Decimal)
{
    this.CelsiusInput.SendKeys(kWh.ToString());
    if (format != CelsiusFahrenheitPage.Format.Decimal)
    {
        string formatText =
            Enum.GetName(typeof(CelsiusFahrenheitPage.Format), format);
        new SelectElement(this.Format).SelectByText(formatText);
    }
    this.driverWait.Until(drv => this.Answer != null);
}

第一个绑定方法将调用不带可选参数的新方法。如果我们选择“Fractions”格式,该方法将从下拉列表中选择它并转换答案。

2. 通过 ArgumentTransformation 实现可选参数

用例

Convert Seconds to Minutes

在这里,我们想将秒转换为分钟。但是,我们希望支持如下输入:

  • 1 天,1 小时,1 分钟,1 秒
  • 4 小时,3 分钟,2 秒
  • 5 天,3 分钟
  • 3 分钟,2 秒
  • 4 小时

该步骤应将输入转换为秒,然后将其输出。

功能方案

场景将如下所示。如您所见,我们传递了不同的天、小时、分钟和秒的组合。

Scenario: Successfully Convert Seconds to Minutes
	When I navigate to Seconds to Minutes Page
	And type seconds for 1 day, 1 hour, 1 minute, 1 second
	Then assert that 1501 minutes are displayed as answer

Scenario: Successfully Convert Seconds to Minutes No Minutes
	When I navigate to Seconds to Minutes Page
	And type seconds for 1 day, 1 hour, 1 second
	Then assert that 1500 minutes are displayed as answer

绑定方法

正如您所见,“type seconds”绑定不包含关于这些输入的任何特殊内容。所有魔力都发生在 StepArgumentTransformation 步骤中,该步骤具有自定义的正则表达式模式。基本上,它只将日期时间输入的部分转换为 TimeSpan,然后我们将其转换为秒。我将不详细解释正则表达式,因为这不是本文的主要主题。您可以在 官方 SpecFlow 文档 中找到更多信息。

[When(@"type seconds for (.*)")]
public void WhenTypeSeconds(TimeSpan seconds)
{
    this.secondsToMinutesPage.ConvertSecondsToMintes(seconds.TotalSeconds);
}

[Then(@"assert that (.*) minutes are displayed as answer")]
public void ThenAssertThatSecondsAreDisplayedAsAnswer(int expectedMinutes)
{
    this.secondsToMinutesPage.AssertMinutes(expectedMinutes.ToString());
}

[StepArgumentTransformation(@"(?:(\d*) day(?:s)?(?:, )?)?(?:(\d*) hour(?:s)?(?:, )?)?
(?:(\d*) minute(?:s)?(?:, )?)?(?:(\d*) second(?:s)?(?:, )?)?")]
public TimeSpan TimeSpanTransform(string days, string hours, string minutes, string seconds)
{
    int daysParsed;
    int hoursParsed;
    int minutesParsed;
    int secondsParsed;

    int.TryParse(days, out daysParsed);
    int.TryParse(hours, out hoursParsed);
    int.TryParse(minutes, out minutesParsed);
    int.TryParse(seconds, out secondsParsed);

    return new TimeSpan(daysParsed, hoursParsed, minutesParsed, secondsParsed);
}

3. 数据驱动测试 - 示例表

用例

Generated Data Driven Tests Specflow

我们不想复制粘贴方案,而是想指定秒的输入和预期的结果,并为所有指定的数据运行测试。上面,我们为四个数据集生成了测试。

功能方案

我们可以使用场景大纲示例表来完成此用例。首先,我们不再使用“Scenario:”而是将其更改为“Scenario Outline:”在步骤下方,我们在“Examples”表中指定所有数据集。您可以通过“Examples:”行标记表的开始,然后表的第一个行包含参数名称。然后您可以使用以下语法 <yourparameter> 在场景中使用这些名称。

Scenario Outline: Successfully Convert Seconds to Minutes Table
	When I navigate to Seconds to Minutes Page
	And type seconds for <seconds>
	Then assert that <minutes> minutes are displayed as answer
Examples:
| seconds						            | minutes   | 
| 1 day, 1 hour, 1 second       | 1500	   	| 
| 5 days, 3 minutes 			      | 7203		  | 
| 4 hours					            	| 240		    | 
| 180 seconds     				      | 3			    | 

格式数据表

之后,您用“|”符号分隔数据。如果您手动输入分隔符,Visual Studio 会为您格式化表格,但如果您粘贴数据,则需要手动操作。

测试名称

对于每一行,Specflow 将生成一个单独的测试。请记住,名称基于表格的第一个参数(您可以在用例图片中看到)。因此,如果您的第一列数据不是唯一的,您的测试名称将使用数字生成。在这种情况下,您可以添加一个新的第一列,自己指定测试名称的后缀。

4. 将对象列表传递给步骤

用例

Add Product with Affiliate Code Amazon

我们想在一个测试中将多个包含联盟代码的商品添加到购物车。我们需要将 URL 和联盟代码对的列表传递给我们的步骤。

功能方案

Scenario: Add Amazon Products with Affiliate Codes
	When add products
	| Url                                      | AffilicateCode |
	| /dp/B00TSUGXKE/ref=ods_gw_d_h1_tab_fd_c3 | affiliate3     |
	| /dp/B00KC6I06S/ref=fs_ods_fs_tab_al      | affiliate4     |
	| /dp/B0189XYY0Q/ref=fs_ods_fs_tab_ts      | affiliate5     |
	| /dp/B018Y22C2Y/ref=fs_ods_fs_tab_fk      | affiliate6     |

您可以使用上述语法传递参数表。测试将打开每个 URL,将指定的联盟代码作为查询参数添加到 URL,然后单击“Buy Now”按钮。

绑定方法

您需要安装 SpecFlow.Assist.Dynamic NuGet 包并添加 using 语句到 TechTalk.SpecFlow.Assist。您的步骤应该接受一个 Table 类型的参数。您可以在没有上述 NuGet 包的帮助下迭代表的项。但是,我认为这并不好。我认为这种方法更清晰。在传递表后,您使用 CreateDynamicSet 扩展方法,它返回一个动态对象集合。您可以像属性一样访问返回对象的表的不同列,但您需要确保没有拼写错误,因为在此模式下,Visual Studio 不会警告您。您可以在 此处 阅读更多关于 dynamic 类型的信息。

[When(@"add products")]
public void NavigateToItemUrl(Table productsTable)
{
    var itemPage = UnityContainerFactory.GetContainer().Resolve<ItemPage>();
    IEnumerable<dynamic> products = productsTable.CreateDynamicSet();
    foreach (var product in products)
    {
        itemPage.Navigate(string.Concat(product.Url, "?", product.AffilicateCode));
        itemPage.ClickBuyNowButton();
    }
}

Specflow 系列

参考文献

文章 高级 SpecFlow:处理参数的 4 种方法 首次出现在 Automate The Planet

© . All rights reserved.