BDD - SpecFlow BDD 测试实践 SpecFlow 模板
引言
BDD Automation Framwork 自动化框架 文章有介绍好几种 BDD 框架,SpecFlow
就是其中一种,它源于 Cucumber
,是基于 .NET 平台的 BDD 测试框架。本文将通过一个简单的例子来实践一把 SpecFlow BDD 测试,运用 SpecFlow 模板。
安装 SpecFlow’s Visual Studio 插件
- 打开 Visual Studio
- 打开菜单 “Extensions ➡ Manage Extensions ➡ Online “ 在搜索框中输入 “SpecFlow” 并搜索
- 点击 Download 开始安装,安装结束后需要重启 Visula Studio,我这截图是已经安装过了。
创建被测程序
创建一个被测程序,也叫作 System Under Test (SUT),这个程序是一个简单的计算器,是一个 C# 类库。
-
打开 Visual Studio,创建一个新的 C# class library
-
输入项目名 SpecFlowCalculator 并选择一个目录保存
注意:
项目名不要用任何特殊的符号,例如括号 (),将会导致 SpecFlow 生成的代码产生编译错误。 -
重命名 Class1.cs 成 Calculator.cs 并用下面代码覆盖,并编译成功
using System;
namespace SpecFlowCalculator
{
public class Calculator
{
public int FirstNumber { get; set; }
public int SecondNumber { get; set; }
public int Add()
{
throw new NotImplementedException();
}
}
}
- 通过菜单 “Build ➡ Build Solution” 进行编译,在 output window 看到 “Build : 1 Succeeded”
创建 SpecFlow 项目
将创建一个 SpecFlow 项目并添加到已经存在的 SpecFlow Calculator solution。
-
右键 “Solution ‘SpecFlowCalculator’,并选择 “Add ➡ New Project…” 菜单
-
搜索 “SpecFlow”, 选择 “SpecFlow Project” template 并点击 Next.
-
输入项目名 “SpecFlowCalculator.Specs”. 保留建议的地址并点击 Create
注意:
项目名不要用任何特殊的符号,例如括号 (),将会导致 SpecFlow 生成的代码产生编译错误。 -
配置 Test Framework (Runner). 这里我们选择 xUnit, 当然你也可以选择自己偏好的 Runner
-
Visual Studio 创建了一个新的 SpecFlow 项目,并且在幕后解决了 NuGet 依赖包
-
添加被测程序的项目依赖
因为我们要测试 “Calculator” 类的实现,所以需要添加一个项目引用指向 “SpecFlowCalculator” class library 到新创建的 SpecFlow 项目中
右键 “Dependencies” 并选择 “Add Project Reference…” 菜单
在 “Reference Manager” dialog 选择 “SpecFlowCalculator” class library
-
Build 整个 Solution
现在这个 solution 已经创建起来了,一个 class library 包含 calculator 的实现,一个 SpecFlow 项目包括对 calculator 的实现。
-
通过菜单 “Tests ➡ Test Explorer” 打开 Test Explorer
看到测试用例已经添加到 SpecFlow 项目了,这是因为 SpecFlow 项目模板默认添加的。注意 Outcome 部分测试用例是 “Not Run”,因为还没有执行测试用例。
绑定实现第一个 step
当我们运行所有的测试用例时,发现结果是失败的,很多 steps 被 Skip 了,是因为我们还没有实现这些 Scenario steps。
-
打开 Calculator.feature 文件 (SpecFlowCalculator.Specs ➡ Features ➡ Calculator.feature)
Feature 文件的目的就是以人类可读的并且可自动化测试的方式记录计算器期望的行为。SpecFlow 用 Gherkin 语言来用 Given/When/Then steps 描述 Scenarios,具体可参考 BDD - Gherkin Language,当前只有一个 Scenario(SpecFlow 项目模板自动添加的),用来描述两个数字相加,计算器应该正常工作。
基于 Scenario 文本,SpecFlow 生成一个自动化测试来执行这个 Scenario,只是目前还没有定义 Scenario steps 实际应该做什么。 -
右键第一个Given step “Given the first number is 50” 并选择 “Go To Definition”
Visual Studio 会定位到该 Step 绑定的 step definition (binding) 处. 它会打开 CalculatorStepDefinitions 类文件,并跳转到 GivenTheFirstNumberIs 方法.
step definition 被定位到,基于 类的[Binding]
属性 和 方法的[Given]
属性。Given 属性的正则表达式正好匹配 feature 文件中 Scenario 的 step。 -
添加下面字段到 step class 来实例化 calculator 类,这是我们前面创建的 SUT 需要测试的程序。
private readonly Calculator _calculator = new Calculator();
- 用下面的代码替换第一个 step definition 方法的实现,用来设置 calculator 的第一个数.
[Given("the first number is (.*)")]
public void GivenTheFirstNumberIs(int number)
{
_calculator.FirstNumber = number;
}
- 在 Test Explorer 中再次执行测试,并看看执行结果
第一个 step “Given the first number is 50” 匹配到 step definition 方法 “CalculatorStepDefinitions.GivenTheFirstNumberIs”,step 执行状态 done 表明这个 step 已经成功执行。接下来的 step 因为没有实现,处理 pending 状态。
绑定实现剩余的 steps
- 跟前面类似,右建 feature 文件中的第二个 step “And the second number is 70” ,选择 “Go To Definition” 直接定位到 step definition。当然你也可以直接打开 CalculatorStepDefinitions.cs 文件定位到 step definition 方法。
- 绑定实现第二个 step “And the second number is 70” ,将下面代码替换 GivenTheSecondNumberIs 方法的代码:
[Given("the second number is (.*)")]
public void GivenTheSecondNumberIs(int number)
{
_calculator.SecondNumber = number;
}
我们在 Gherkin Scenario 中用 “And” 关键字是为了可读性更好。 “And” 关键字会根据前面的 steps 被解析成 “Given”, “When” or “Then”。因为第一个 step 是一个 “Given” step,所以第二个 step “And the second number is 70” 会被解析成一个 “Given” step。
- 接下来绑定实现第三个 step, “When the two numbers are added”, 将下面代码替换 WhenTheTwoNumbersAreAdded 方法中的代码. 这个就去必须有一个
When
属性, 因为在 feature 文件中,该 step 是属于 “When” step.
private int _result;
[When("the two numbers are added")]
public void WhenTheTwoNumbersAreAdded()
{
_result = _calculator.Add();
}
这个实现是调用 calculator 的 Add 方法,注意这个 Add 方法的结果没有存储在 calculator 的字段或属性中。一个好的实践就是将方法返回值存储 step definition 类的一个字段中,方便后续的重用。
- 实现绑定最后一个 step “Then the result should be 120”, 替换ThenTheResultShouldBe 方法的代码. 这个方法必须有一个
Then
属性, 因为在 Scenario 中该 step 是一个 “Then” step.
在文件最上面 添加一个 namespace:
using FluentAssertions;
利用 FluentAssertions
类库,验证 Add 方法的结果是否匹配期望的值。
[Then("the result should be (.*)")]
public void ThenTheResultShouldBe(int result)
{
_result.Should().Be(result);
}
实现了所有的 step definitions,代码如下:
using FluentAssertions;
using TechTalk.SpecFlow;
namespace SpecFlowCalculator.Specs.Steps
{
[Binding]
public sealed class CalculatorStepDefinitions
{
// For additional details on SpecFlow step definitions see https://go.specflow.org/doc-stepdef
private readonly ScenarioContext _scenarioContext;
private readonly Calculator _calculator = new Calculator();
private int _result;
public CalculatorStepDefinitions(ScenarioContext scenarioContext)
{
_scenarioContext = scenarioContext;
}
[Given("the first number is (.*)")]
public void GivenTheFirstNumberIs(int number)
{
_calculator.FirstNumber = number;
}
[Given("the second number is (.*)")]
public void GivenTheSecondNumberIs(int number)
{
_calculator.SecondNumber = number;
}
[When("the two numbers are added")]
public void WhenTheTwoNumbersAreAdded()
{
_result = _calculator.Add();
}
[Then("the result should be (.*)")]
public void ThenTheResultShouldBe(int result)
{
_result.Should().Be(result);
}
}
}
- 编译整个 solution 应该是成功的
- 在 Test Explore 中再次运行测试
可以看到前两个 “Given” steps 执行成功了,而 “When the two numbers are added” step 执行失败. 这是因为 calculator 类中 Add 方法还没有实现。
实现被测程序
- 打开 SpecFlowCalculator class library 中的 Calculator.cs ,替换 Add 方法中的代码:
public int Add()
{
return FirstNumber + SecondNumber;
}
- 编译整个 solution 应该是成功的
- 在 Test Explore 中再次运行测试
现在所有的 steps 成功执行
测试报告
为了方便共享测试结果,我们需要生成一个测试报告。
-
打开 一个 commnd 命令
-
安装 LivingDoc CLI 作为一个全局的 dotnet tool
dotnet tool install --global SpecFlow.Plus.LivingDoc.CLI
- 导航到 SpecFlow 项目的输出目录:
cd C:\Work\SpecFlowCalculator\SpecFlowCalculator.Specs\bin\Debug\net6.0
- 运行 LivingDoc CLI 来生成 HTML report
livingdoc test-assembly SpecFlowCalculator.Specs.dll -t TestExecution.json
有必要请重现打开 Command 命令执行
- 生成 HTML 文件存储在 SpecFlow 项目输出目录下,可以用你偏好的浏览器打开它.
C:\Work\SpecFlowCalculator\SpecFlowCalculator.Specs\bin\Debug\net6.0\LivingDoc.html
注意
,如果你的 JSON 文件名字是 FeatureData.JSON,而不是 TestExecution.JSON,这表明你的 CLI tool 是老版本的,最好升级到最新版本。
查看 calculator feature 的执行文档,可以看到 Scenarios 和 steps 的执行结果。
点击 “Analytics” tab 来查看 test result summary :
有关更多 SpecFlow+LivingDoc 信息,请参考 SpecFlow+ LivingDoc’s documentation
最后
我们实践了 SpecFlow 的模板项目,从 Scenaro steps 的绑定实现,运行测试,到生成测试报告整个过程,现在你也可以根据自己的项目需要开展 SpecFlow BDD 测试了,创建自己项目的 Feature 文件,设计 Gherkin Senario Steps,并用代码实现对应的 step definition.