D-04-开始测试 ? mstest ? specflow

撰写测试

相信很多人会想要增加系统的稳定度,但是这该如何做则是个问题,相信很多人看过91 TDD的文章,也相信希望能从单元测试增加系统的稳定度以及正确性,不过在dotnetcore内要如何写测试案例呢,今天就让我们来研究一下vscode怎麽用specflow来写测试案例。

本文同步放置於此

测试案例

「前辈,为什麽我们常常会写出很多bug」
今天小光跟大头请教怎麽增加程序稳定度及正确性的问题,不过听到这问题後大头也只是歪着头思考着,也没有正面回应小光的疑问。
「其实这也是苦恼我好久的问题」
「还是我们两个一起去问老K前辈呢」
「这好像是不错的解决方式。」
所以他们两个就一起来寻问老K该如何处理这问题,不过当他们问老K之後确得到这样的答案。
「这问题可能只能问上帝了,因为人非圣贤孰能无过。」
听了这个答案後两个人都倒抽了一口气,而且整个像是泄气的皮球,不过大头立刻意会到他们问错问题了,所以大头又换个方式问了一次。
「前辈,我们该如何减少bug的产生呢。」
听了大头问的问题後老K哈哈大笑,并且这麽说。
「孺子可教也,我们没办法不写出bug,但是我们能想办法减少写出bug的状况,以及检查有没有写出bug。」
说完了这句话後老K喝了杯水,并且起身走了几步後示意大头跟小光跟上来。所以小光跟大头就跟着老K往办公室外面走去。走到外面公园後老K开始说起来了。
「系统、需求跟程序都是人设计的,所以依据理解力及细心程度不同所做出来的东西完成度也会不同。」
这时老K走到树下的座椅上坐了下来,并且继续说。
「不过还是可以透过人与人之间的配合来检验出系统有没有问题,所以这时除了整合测试之外也可以透过单元测试及早知道元件的正确性。」
说到这里大头似乎有点疑问,所以问了一个问题。
「但是要怎麽让QA或是企划来配合检验系统呢,一定要等到系统完成後再来检验吗?」
这时老K点点头,因为大头问了一个好问题。
「这时可以RD跟QA还有企划一起进行BDD」

BDD

所以重点来了,什麽是BDD呢,BDD是Behavior-driven development的简称,他鼓励RD跟QA还有非技术人员协作开发,不过这怎麽做到,非技术人员对於程序码的撰写应该不清楚。所以这时候就是让非技术人员透过自然语言写出测试案例,并且说明其重点所在,如此程序开发人员可以更着重於系统的开发以符合测试案例的检验。这样可以大大的减少程序人员与非技术人员之间的沟通成本,除此之外也可以有一份程序的说明文件可以提供给相关人员了解内容。

BDD 如何撰写

所以要怎麽撰写才可以让人了解程序的作用以及其价值呢,因此要遵循一个大家公认的规则来写这份文件,所以就BDD的范例来说这份文件要包含下列内容。

段落 内容说明 包含资讯
Title 说明此程序的商业价值 简述这段程序做什麽的
Narrative 简短的介绍这章节 As a 某种身份 I want 做某件事情 so that 会得到什麽结果
Acceptance criteria 说明情境以及如何应对 Scenario Given And When Then

specflow

说了那麽多BDD得概念,不过如何把程序开发跟BDD和在一起呢,这时我们就需要一个Specflow的工具,这工具就是帮我们刚刚说的BDD所写下来的自然语言产生程序结构,透过实作Step来达成测试我们程序正确性的工具。在Visual Studio跟Rider有较好的支援,不过我们目前使用的是VSCode,所以今天就来认识如何用VSCode来撰写测试案例以及验证程序的正确性。

环境设定

这里我们需要产生一个新的专案,但是在产生专案之前要先安装些东西,所以先要完成的是环境设定,这边先参考安装Specflow的内容来安装VSCode的扩充元件Awesome DotNetCore PackCucumber (Gherkin) Full Support。在安装完成後再设定档指定Specflow中放置Step的程序码的资料夹以及档案名称的模式,路径为档案->喜好设定->设定後在搜寻栏筛选Cucumber之後找到Cucumberautocomplete.Steps按下编辑後输入以下内容。

"cucumberautocomplete.steps": ["/**/Steps/**/*.cs"]

这样设定完之後我们可以在feature档案上透过ctrl+click立刻连结到Step的程序码上,如此VSCode的设定告一段落。不过要重头写feature是一件麻烦的事,而且建立空专案也是一样,所以接下来要针对dotnet cli加以设定,这边参考新增Specflow范本的步骤来新增specflow的范本。所以首先先在命令列输入以下内容。

dotnet new -i SpecFlow.Templates.DotNet

透过上述指令可以新增Specflow的范本到donet cli内,当新增完之後我们就可以使用范本来产生专案以及feature范本,所以我们先产生一个空的专案。

dotnet new specflowproject --unittestprovider mstest --framework net5.0 -o Tests

如此我们就可以产生一个空的specflow的专案,接下来我们可以产生一个空的函式库只要输入一下内容。

dotnet new classlib --framework net5.0 -o Libs

接下来再将相依的套件都先加入进来,输入以下指令。

dotnet add package MSTest.TestFramework -v 2.2.7
dotnet add package MSTest.TestAdapter -v2.2.7

当空专案产生好了之後,这时只要在测试专案中参考函式库就可以针对函式库的内容撰写测试案例了,这里参考的指令如下。

dotnet add reference ../Libs/Libs.csproj

所以先在函式库中写一个要测试的方法,如下所示。

public class Calculator
{
    public int Add(int first, int second)
    {
        return 0;
    }
}

所以接下来我们要开始写测试案例了。

测试案例撰写

如果透过前面的步骤产生specflow专案的话我们应该可以看到内部已经有些些范例档案了,例如Calculator.feature,我们就以这档案来开始说明。

Feature: Calculator # 表头,以下说明该程序的功用,Feature: 後面接的可以用来设定特定Step才能绑定该feature
![Calculator](https://specflow.org/wp-content/uploads/2020/09/calculator.png)
Simple calculator for adding **two** numbers

Link to a feature: [Calculator]($projectname$/Features/Calculator.feature)
***Further read***: **[Learn more about how to generate Living Documentation](https://docs.specflow.org/projects/specflow-livingdoc/en/latest/LivingDocGenerator/Generating-Documentation.html)**

@mytag # tag
Scenario: Add two numbers # 情境的名称,不能重复
	Given the first number is 50 # Give 给予参数
	And the second number is 70 # And 接续上一个的指令,在这是Given
	When the two numbers are added # When 执行动作
	Then the result should be 120 # Then 检查结果

Step实作

由於透过Cucumber (Gherkin) Full Support插件我们可以看到那些feature的语句没有绑订到Step上面,所以这边可以看一下范例中的CalculatorStepDefinitions.cs

[Given("the first number is (.*)")]
public void GivenTheFirstNumberIs(int number)
{
    //TODO: implement arrange (precondition) logic
    _scenarioContext.Add("First", number);
}

[Given("the second number is (.*)")]
public void GivenTheSecondNumberIs(int number)
{
    //TODO: implement arrange (precondition) logic
     _scenarioContext.Add("Second", number);
 }
 
[When("the two numbers are added")]
public void WhenTheTwoNumbersAreAdded()
{
    //TODO: implement act (action) logic
     var first = _scenarioContext.Get<int>("First");
     var second = _scenarioContext.Get<int>("Second");
     var target = new Libs.Calculator();
    _scenarioContext.Add("Result", target.Add(first, second));
}

[Then("the result should be (.*)")]
public void ThenTheResultShouldBe(int result)
{
    //TODO: implement assert (verification) logic
     var expect = _scenarioContext.Get<int>("Result");
     Assert.AreEqual(result, expect);
}

不过就算这补完後执行测试也是收到错误,因为我们原来的方法本来就是错的,所以接下来再把函式库的方法修正如下。

    public int Add(int first, int second)
    {
        return first + second;
    }

如此执行完後应该会有测试成功的讯息,最後在说明一下如果需要绑定某个feature的话,只要在class上面设定这个attribute即可。

[Scope(Feature = "Calculator")]
    [Binding]
    public class CalculatorStepDefinitions

後记

今天跟大头还有小光了解了要怎麽透过测试案例来增加程序的正确性,并且学习到如何透过vscode来撰写specflow的features。希望对大家减少bug有所帮助。


<<:  Day41 ( 电子元件 ) 电流急急棒

>>:  Day 26 - 实战演练 — Notifier 、Notification

虾皮串接实作笔记-串接 API 虾皮物流标签

前言 目标:串接虾皮订单、标签资讯,目前串接虾皮 OpenAPI 2.0 版本,串接手册 串接步骤:...

2.建立unity专案、页面简介、建立角色

建立专案 1.点击新专案来建立一个新专案:D 2.选择要使用的样板,这次要做2DRPG雏形,因此选择...

Day 09:遍历资料好便利-v-for

目前为止,我们成功引入了 BootstrapVue 的元件 Navbar,也调整了样式和内容。 突然...

【Day 1】前言、时程规划

嗨大家! 在大二升大三的这个暑假,系上很多同学申请了实习、规划了 project 实作,却因为疫情升...

WhatsApp Business 商业帐号的独特功能

WhatsApp是世界上最多人使用的即时通讯软件,每月有20亿活跃用户,用户透过WhatsApp每天...