• BDD - SpecFlow BDD 测试实践


    引言

    BDD Automation Framwork 自动化框架 文章有介绍好几种 BDD 框架,SpecFlow 就是其中一种,它源于 Cucumber,是基于 .NET 平台的 BDD 测试框架。本文将通过一个简单的例子来实践一把 SpecFlow BDD 测试,运用 SpecFlow 模板。

    安装 SpecFlow’s Visual Studio 插件

    1. 打开 Visual Studio
    2. 打开菜单 “Extensions ➡ Manage Extensions ➡ Online “ 在搜索框中输入 “SpecFlow” 并搜索
    3. 点击 Download 开始安装,安装结束后需要重启 Visula Studio,我这截图是已经安装过了。
      在这里插入图片描述
      在这里插入图片描述

    创建被测程序

    创建一个被测程序,也叫作 System Under Test (SUT),这个程序是一个简单的计算器,是一个 C# 类库。

    1. 打开 Visual Studio,创建一个新的 C# class library
      在这里插入图片描述

    2. 输入项目名 SpecFlowCalculator 并选择一个目录保存
      在这里插入图片描述
      在这里插入图片描述
      注意:项目名不要用任何特殊的符号,例如括号 (),将会导致 SpecFlow 生成的代码产生编译错误。

    3. 重命名 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();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 通过菜单 “Build ➡ Build Solution” 进行编译,在 output window 看到 “Build : 1 Succeeded”
      在这里插入图片描述

    创建 SpecFlow 项目

    将创建一个 SpecFlow 项目并添加到已经存在的 SpecFlow Calculator solution。

    1. 右键 “Solution ‘SpecFlowCalculator’,并选择 “Add ➡ New Project…” 菜单
      在这里插入图片描述

    2. 搜索 “SpecFlow”, 选择 “SpecFlow Project” template 并点击 Next.
      在这里插入图片描述

    3. 输入项目名 “SpecFlowCalculator.Specs”. 保留建议的地址并点击 Create
      在这里插入图片描述
      注意:项目名不要用任何特殊的符号,例如括号 (),将会导致 SpecFlow 生成的代码产生编译错误。

    4. 配置 Test Framework (Runner). 这里我们选择 xUnit, 当然你也可以选择自己偏好的 Runner
      在这里插入图片描述

    5. Visual Studio 创建了一个新的 SpecFlow 项目,并且在幕后解决了 NuGet 依赖包
      在这里插入图片描述

    6. 添加被测程序的项目依赖
      因为我们要测试 “Calculator” 类的实现,所以需要添加一个项目引用指向 “SpecFlowCalculator” class library 到新创建的 SpecFlow 项目中
      右键 “Dependencies” 并选择 “Add Project Reference…” 菜单
      在这里插入图片描述
      在 “Reference Manager” dialog 选择 “SpecFlowCalculator” class library
      在这里插入图片描述

    7. Build 整个 Solution
      现在这个 solution 已经创建起来了,一个 class library 包含 calculator 的实现,一个 SpecFlow 项目包括对 calculator 的实现。
      在这里插入图片描述

    8. 通过菜单 “Tests ➡ Test Explorer” 打开 Test Explorer
      看到测试用例已经添加到 SpecFlow 项目了,这是因为 SpecFlow 项目模板默认添加的。注意 Outcome 部分测试用例是 “Not Run”,因为还没有执行测试用例。
      在这里插入图片描述

    绑定实现第一个 step

    当我们运行所有的测试用例时,发现结果是失败的,很多 steps 被 Skip 了,是因为我们还没有实现这些 Scenario steps。
    在这里插入图片描述

    1. 打开 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 实际应该做什么。

    2. 右键第一个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。

    3. 添加下面字段到 step class 来实例化 calculator 类,这是我们前面创建的 SUT 需要测试的程序。

    private readonly Calculator _calculator = new Calculator();
    
    • 1
    1. 用下面的代码替换第一个 step definition 方法的实现,用来设置 calculator 的第一个数.
    [Given("the first number is (.*)")]
    public void GivenTheFirstNumberIs(int number)
    {
        _calculator.FirstNumber = number;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    1. 在 Test Explorer 中再次执行测试,并看看执行结果
      在这里插入图片描述
      第一个 step “Given the first number is 50” 匹配到 step definition 方法 “CalculatorStepDefinitions.GivenTheFirstNumberIs”,step 执行状态 done 表明这个 step 已经成功执行。接下来的 step 因为没有实现,处理 pending 状态。

    绑定实现剩余的 steps

    1. 跟前面类似,右建 feature 文件中的第二个 step “And the second number is 70” ,选择 “Go To Definition” 直接定位到 step definition。当然你也可以直接打开 CalculatorStepDefinitions.cs 文件定位到 step definition 方法。
    2. 绑定实现第二个 step “And the second number is 70” ,将下面代码替换 GivenTheSecondNumberIs 方法的代码:
    [Given("the second number is (.*)")]
    public void GivenTheSecondNumberIs(int number)
    {
        _calculator.SecondNumber = number;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    我们在 Gherkin Scenario 中用 “And” 关键字是为了可读性更好。 “And” 关键字会根据前面的 steps 被解析成 “Given”, “When” or “Then”。因为第一个 step 是一个 “Given” step,所以第二个 step “And the second number is 70” 会被解析成一个 “Given” step。

    1. 接下来绑定实现第三个 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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述
    这个实现是调用 calculator 的 Add 方法,注意这个 Add 方法的结果没有存储在 calculator 的字段或属性中。一个好的实践就是将方法返回值存储 step definition 类的一个字段中,方便后续的重用。

    1. 实现绑定最后一个 step “Then the result should be 120”, 替换ThenTheResultShouldBe 方法的代码. 这个方法必须有一个 Then 属性, 因为在 Scenario 中该 step 是一个 “Then” step.
      在文件最上面 添加一个 namespace:
    using FluentAssertions;
    
    • 1

    利用 FluentAssertions 类库,验证 Add 方法的结果是否匹配期望的值。

    [Then("the result should be (.*)")]
    public void ThenTheResultShouldBe(int result)
    {
        _result.Should().Be(result);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    实现了所有的 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);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    1. 编译整个 solution 应该是成功的
    2. 在 Test Explore 中再次运行测试
      在这里插入图片描述
      可以看到前两个 “Given” steps 执行成功了,而 “When the two numbers are added” step 执行失败. 这是因为 calculator 类中 Add 方法还没有实现。

    实现被测程序

    1. 打开 SpecFlowCalculator class library 中的 Calculator.cs ,替换 Add 方法中的代码:
       public int Add()
        {
            return FirstNumber + SecondNumber;
        }
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    1. 编译整个 solution 应该是成功的
    2. 在 Test Explore 中再次运行测试
      现在所有的 steps 成功执行
      在这里插入图片描述

    测试报告

    为了方便共享测试结果,我们需要生成一个测试报告。

    1. 打开 一个 commnd 命令
      在这里插入图片描述

    2. 安装 LivingDoc CLI 作为一个全局的 dotnet tool

    dotnet tool install --global SpecFlow.Plus.LivingDoc.CLI
    
    • 1

    在这里插入图片描述

    1. 导航到 SpecFlow 项目的输出目录:
    cd C:\Work\SpecFlowCalculator\SpecFlowCalculator.Specs\bin\Debug\net6.0
    
    • 1
    1. 运行 LivingDoc CLI 来生成 HTML report
    livingdoc test-assembly SpecFlowCalculator.Specs.dll -t TestExecution.json
    
    • 1

    有必要请重现打开 Command 命令执行
    在这里插入图片描述

    1. 生成 HTML 文件存储在 SpecFlow 项目输出目录下,可以用你偏好的浏览器打开它.
    C:\Work\SpecFlowCalculator\SpecFlowCalculator.Specs\bin\Debug\net6.0\LivingDoc.html
    
    • 1

    注意,如果你的 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.

  • 相关阅读:
    一个基于C#开发的轻量级OCR文字识别开源工具
    c++学习记录(一)
    说说Selenium的几个痛处
    5. 标准库类型string
    go实现自定义rpc框架 (核心:服务端&客户端、自定义io流、编解码、服务发现、负载均衡、支持多语言网关等)
    深度学习--LSTM网络、使用方法、实战情感分类问题
    node封装mysql
    回归预测 | MATLAB实现GLM广义线性模型数据回归预测
    鼠标移入显示下拉框
    零基础安装分布式数据服务注册系统
  • 原文地址:https://blog.csdn.net/wumingxiaoyao/article/details/126678068