TDD in .NET Core - 简介
本文很多内容来自选自TDD实例一书。
预备知识
最好有一些预备知识,例如xUnit,Moq,如何编写易于测试的代码,这些内容我都写了文章:https://www.cnblogs.com/cgzl/p/9178672.html#test。
Test Driven Development
什么是TDD(Test Driven Development)?
TDD是一个软件开发过程,这个过程依赖于重复性的小开发周期:需求被转化为具体的测试用例,然后改进程序以便通过测试。
在TDD里有两条规则:
- 只在有未通过的自动化测试的情况下,你才会去写新的代码
- 消灭重复
这两条规则在技术上的含义是:
- 你必须进行良好的设计,运行的代码可在决策之间提供反馈
- 开发人员得写自己的测试
- 开发环境可以针对微小的变化需要提供快速的响应
- 您的设计必须由众多高内聚、低耦合的组件组成,这样测试会更简单。
这两条规则也意味着编程的三个任务:
- Red - 先写一个不能工作/通过的小测试,甚至根本无法编译
- Green - 快速让这个测试通过,无论代码有多烂
- Refactor - 消除上个步骤中的代码重复。
Red,Green,Refactor,这就是TDD的咒语。
如果TDD可以很好的执行,那么它就会大幅度减少代码缺陷的密度,也使工作的主题对于相关人员来说更加清晰。所以,TDD也具有社会含义:
- 如果缺陷密度可以降低到足够的程度,那么QA就会从被动变为主动的工作。
- 如果那些“让人讨厌的惊喜”可以减少到足够的程度,那么项目经理就可以精确的评估以便让客户参与到每日的开发工作中。
- 如果技术会议的主题足够清晰,那么程序员就会按分钟去工作而不是按天或周来安排和进行工作。
- 如果缺陷密度可以降低到足够的程度,那么我们每天都可以交付出具有新功能的软件,这就会与客户建立新的业务关系。
这些概念都很简单,但是动机是什么?为什么开发人员要去写自动测试代码?为什么开发人员在他们的思维能够大幅飙升的设计时,却只进行小步工作? 勇气。
勇气
TDD是编程过程中管理恐惧的一种办法。
这个恐惧不是坏事,它是一种合理的恐惧,例如:”这个问题确实很难,我从开始的感觉看不到尽头“。
如果疼痛是喊停的自然表达,那么恐惧就是告诉你要“小心”。
小心是很好的,但是恐惧还有一些其它的影响:
- 让你不得不进行更多试探性操作
- 让你交流的更少
- 让你羞于反馈
- 让你脾气暴躁
这些影响在开发的时候对你都没有任何帮助,尤其是遇到困难问题的时候。那么你如何面对困难处境并且:
- 取代尝试/试探,而是尽快进行具体学习
- 取代争吵,而是进行更清楚的沟通
- 取代避免反馈,而是寻求帮助,和具体的反馈
- 控制你自己的脾气
TDD会管理这些事情。
为什么要TDD
从业务角度:
- 提供了需求的确认。通过编写测试以及RGR周期,需求确认很自然的在软件开发的过程中就完成了。
- 捕获回归问题。回归问题就是指随着软件新功能的发布,以前的某些功能却不好用了。TDD可以很早的发现回归问题。
- 综上两点,TDD也降低了维护成本。
从开发人员角度讲,TDD还有以下好处:
- 设计为先的心态。写测试的时候,我们就得考虑与软件的交互应该如何实现,以便把这些功能需求编程可能。
- 防止过度工程。关注于如何让测试通过和满足客户的期待,就会让我们保持正轨,而不是迷失于架构设计和幻想那么无法提供很多价值的最佳抽像设计中。
- 增加开发人员的动力。取代了花费几天时间想尽办法来实现某个功能这样的操作,TDD把需求分解成一些测试,并结合RGR流程,这就允许你可以持续快速的进展并建立成功循环。
- 收获自信。通过大量的测试结果,你感动支配的力量,无论修改、重构、增加功能都变得很简单。
第一个实例
在本例中,您将会看到TDD的如下步骤:
- 快速添加一个测试
- 运行所有的测试(包括以前写的),可以看到新添加的测试Fail了
- 修改一点代码
- 运行所有测试,都成功了
- 重构,移除重复
建立.NET Core 项目
这个很简单,首先建立一个Console App:
然后再添加一个xUnit项目:
这个测试项目需要引用Console项目。
需求
有这样一份报表:
现在想要做成支持多币种的:
这里还提供了汇率:
目标就是产生第二张图那样的报表。
开始操作
我们需要做哪些工作?
- 让两种币种的钱数可以进行加法操作,并通过给定的汇率算出结果。
- 让股票单价可以乘以股票数并得出总额。
上面是一个待办问题列表(To-Do List)。我们就关注于这个待办列表即可。
列表里的问题应该是逐个解决的,解决完一个划掉一个;如果有新问题,就在后边加上一条。
编写测试
下面我们开始,先不建立对象,先写测试:
让编译通过
这里有很多问题,编译也无法通过,这些问题我们也是一个一个来解决。
1. 首先,没有Dollar这个类,那就建立Dollar这个类:
第一个问题解决了。
2. 没有相应的构造函数,那就建立构造函数:
又解决了一个问题!
3. 没有Times()这个方法,那就建立该方法:
又解决了一个问题!
4. 没有Amount属性,建立该属性:
编译问题都解决了!!
看一下测试方法:
编译错误肯定是没有了。
测试Fail
然后跑测试:
不出意料肯定会Fail。
让测试通过
现在有了具体的这个Fail的测试,我们现在的任务就是让该测试变成Pass,而不是实现多币种报表,先让这个测试通过,再慢慢让其它测试通过。
您可能不喜欢这样,但是现在的目标不是做出完美的解决方案,目标就是让这个测试通过,所以这时候代码可能很烂:
我写死了数字10。
然后再跑测试:
测试Pass了!!
重构,移除重复
别着急,周期还没结束。
现在,我们需要移除重复。但是重复在哪?
通常你看到的重复是指代码的重复,这里是指测试中的数据和代码中数据的重复。
这个10是哪来的? 它实际上是:
是通过5乘以2得来的。
所以代码中的5*2和测试中的5*2是重复的。 我们需要移除这个重复,但是可能需要不止一步来实现。
先把乘法移动到Times方法里试试:
这样的话,测试仍然会pass:
这是一小步。
那么5是哪里来的?
应该是从构造函数传递进来的,我们可以把它存到Amount属性里:
所以我们可以在Times方法里使用它:
现在处理这个2,它应该可以使用参数multiplier代替:
OK!
此外,我们可以对代码的语法进行一些优化:
其实某些优化也应该通过TDD的RGR周期来实现。
第一篇文章就简单介绍这些。
TDD in .NET Core - 简介的更多相关文章
- 酷学习笔记——ASP.NET Core 简介
ASP.NET Core 简介 其实就是说酷好,不好好学,不学好,没饭吃. 新词汇:IoT,Internet of Things,网联网,微软物联网英文网站.微软物联网中文网站
- NET Core 简介
1. 前言 .NET发行至今已经过了十四个年头.随着版本的不断迭代更新,.NET在Windows平台上的表现也是越来越好,可以说Windows平台上所有的应用类型.NET几乎都能完成. 只是成也Win ...
- [翻译] ASP.NET Core 简介
ASP.NET Core 简介 原文地址:Introduction to ASP.NET Core 译文地址:asp.net core 简介 翻译:ganqiyin ...
- ASP.NET Core 简介 - ASP.NET Core 基础教程 - 简单教程,简单编程
原文:ASP.NET Core 简介 - ASP.NET Core 基础教程 - 简单教程,简单编程 ← ASP.NET Core 基础教程 ASP.NET Core Windows 环境配置 → A ...
- 第一节:EF Core简介和CodeFirst和DBFirst两种映射模式(以SQLite和SQLServer为例)
一. EF简介 1. 定义 Entity Framework (EF) Core 是轻量化.可扩展.开源和跨平台的数据访问技术,它还是一种对象关系映射器(ORM),它使.NET 开发人员能够使用面向对 ...
- [.net core]简介(转)
原文地址:https://docs.microsoft.com/zh-cn/dotnet/articles/core/ NET Core 是一个通用开发平台,由 Microsoft 和 GitHub ...
- ASP.Net Core简介
定义:一个经过精简的.模块化的.NET Framework子集,目的是为了跨平台..NET Core的类库叫做“CoreFX”,更精简的版本叫做“CoreCLR”. ASP.NET Core 是微软的 ...
- .NET Core简介
内容主要来源 https://docs.asp.net/en/latest/conceptual-overview/dotnetcore.html 什么是.NET Core .NET Core 5 包 ...
- ASP.NET Core系列(一): .NET Core简介及安装开发环境
大家都知道Java是跨平台的,.NET因为不具有跨平台的特性,被越来越多的开发者诟病,之前有各种间接的跨平台的方案,比如mono.但是由于各种兼容问题,最终 .NET Core出现了,它可以让程序在W ...
随机推荐
- MAC Undefined symbols for architecture x86_64 cv::imwrite
因为homebrew安装opencv时用的是clang,而CLion中使用的是gcc编译器. 将clion中的编译器改回默认的clang就行了.
- Entity Framework Core(EF Core) 最简单的入门示例
目录 概述 基于 .NET Core 的 EF Core 入门 创建新项目 更改当前目录 安装 Entity Framework Core 创建模型 创建数据库 使用模型 基于 ASP.NET Cor ...
- UOJ#440. 【NOIP2018】填数游戏 动态规划
原文链接www.cnblogs.com/zhouzhendong/p/UOJ440.html 前言 菜鸡选手到省选了才做联赛题. 题解 首先我们分析一下性质: 1. 假如一个格子是 0,那么它的右上角 ...
- 分红包算法Java实现
需要考虑几个点: 红包形成的队列不应该是从小到大或者从大到小,需要有大小的随机性. 红包这种金钱类的需要用Decimal保证精确度. 考虑红包分到每个人手上的最小的最大的情况. 下面是利用线段分割算法 ...
- gitlab使用过程中的需求与解决
序言 在git使用过程中发现指令实在太多,就算记忆后不长用的话很快也会忘记掉,所以编写本文的初衷是为了记录在使用git指令的过程中所遇到的需求与解决方法,毕竟使用git的需求也就那么一些,范围不大,所 ...
- Python获取当前日期和日期差计算
在Python中获取日期和时间很简单,主要使用time和datetime包 1.获取当前时间并格式化 from dateutil import rrule from datetime import d ...
- itunes 备份导致C盘空间不足问题解决办法
首先,itunes备份的默认路径是 C:\users\你的用户名\Appdata\Roaming\Apple computer 备份的主要存放文件在C:\Users\David_lu\AppData\ ...
- DRAM的原理设计
在一个电子系统中,CPU.内存.物理存储.IO这些单元必不可少,只不过有的集成在CPU内部,有的分离出来. 这里就针对系统中的内存,此处选用DRAM来进行说明,讲述下基本的原理设计,主要分为以下几个部 ...
- BZOJ2640 : 可见区域
设$base$表示直接能看到的面积,$f[i]$表示仅去掉线段$i$后新增的面积,$g[i][j]$表示仅去掉线段$i$和$j$后新增的面积. 删除一条线段的答案为$base+\max(f[i])$. ...
- 在Centos中安装mysql
下载mysql 这里是通过安装Yum源rpm包的方式安装,所以第一步是先下载rpm包 1.打开Mysql官网 https://www.mysql.com/, 点击如图选中的按钮 点击如图框选的按钮 把 ...