【如何高效开发 ? 】测试驱动开发 | 3 大法则 + 5 大好处

撰写单元测试,速度更快 !

大纲

  • 除错的日常
  • 测试驱动开发
  • 三大法则
  • 五大好处
  • JUnit 示范
  • 违反直觉的力量

除错的日常

工程师的日常,是不断的与程序错误(Bug) 进行搏斗

「谨慎」

是工程师的「美德」,也是工程师的痛苦来源 :

  • 「修正」 只花不到 10 分钟
  • 「测试」 却花 10 倍以上时间

如此情况,你可以...

撰写「单元测试」- 使用程序来测试程序,只是要多花了一点时间。

你知道吗?

如果正确使用「单元测试」的方法 :

甚至会比不写测试的开发流程,开发的更加快速 !

测试驱动开发

传统的单元测试流程

传统开发上的单元测试流程,会先写产品程序,在写测试程序。

  • 好处: 都有测过 BUG 比较少
  • 坏处: 比较花时间,相对麻烦

大概率会被省略

如果产品程序已经完成了,在 UI 介面上都没有测出问题来。

怠惰之心,人皆有之。

工程师,可能会直接略过这一段。

即便是团队要求,当任务时程紧急的时候,还是会有很大的概率,会被省略。


书中的知识

  • Clean Code 无瑕的程序码 - 敏捷软件开发技巧守则
  • The Clean Coder 无瑕的程序码 番外篇 - 专业程序设计师的生存之道

这两本书籍,相同作者,但不同主题。

书中都提到 :

测试驱动开发 (Test Driven Development , TDD)

藉由先撰写「测试」的程序码 ,「驱动」产品程序的「开发」。


「先写测试的程序设计方式」

因为有各种的优点,章节的结论就是直接认定 :

「 TDD 是专业人士的选择 」

不使用 TDD 的程序设计师,只能代表:

可能还「 不够专业 」
 

001.pro


三大法则

测试驱动开发,有三大法则 :

TDD

第一法则

在撰写一个单元测试前,不可撰写任何产品程序

要先从测试程序开始撰写,绝对不要先撰写产品程序。

「顺序」非常重要

第二法则

只撰写刚好无法通过的单元测试,不能编译也算无法通过

撰写的测试程序,结果必须是失败的,而且是「刚好」失败的。

「不要一次完成所有的测试程序」

第三法则

只撰写刚好能通过当前测试失败的产品程序

撰写的产品程序,结果必须是成功的,而且是「刚好」成功的。

「先完成一个小目标」

循环动作

然後,依据这个法则,大约 每 30 秒就会执行一次程序码:

  • 无法通过的单元测试: 会驱动你,完善产品程序
  • 通过的单元测试: 会告诉你,产品程序,没有问题。可以继续撰写 下一个测试程序。

如此就会构成一个循环,不断重复。测试的程序码与产品的程序码就会同步增长并且互相匹配。

相比於传统开发上的单元测试流程,割裂的两个动作就会合而为一 :

测试就是开发,开发就是测试。
  • 不会有所谓「麻烦」的问题
  • 更不会出现,时程紧急时,省略单元测试的问题

快速的原因

因为两个动作,是在同一时间被撰写出的,速度肯定是比分开两步骤执行的更快 !

但为什麽会比不写单元测试的开发流程,还要更快 ?

关键点在於 :

「极短的程序码执行周期」

「trial and error」 (尝试错误的方法),在极短的时间内,以极高的频率,高速运作。

002.music

修正与反馈组合成的节奏,就像钢琴乐谱一样 ,优美且流畅的弹奏出来。


五大好处

依据 TDD 三大法则开发的程序,就会带来五大好处 :

003.good

  • 确定性
  • 缺陷注入率
  • 勇气
  • 文件
  • 设计

确定性

依据这个法则,就会撰写非常多的测试程序,并且测试程序相比於产品程序,只会多不会少。

003-1.good

程序修改後,执行「单元测试」的绿灯,会非常的确定,程序与当初开发的预期结果

 是一致的

缺陷注入率

「缺陷注入率」指的是出现错误缺陷的比率,原因相似於「确定性」。

003-2.good

越低的错误率,维护程序的成本就会越小,也会是每个开发者追求的目标。


勇气

「勇气」指的是面对糟糕程序码的「勇气」

面对糟糕的程序码,你会想要改它,但又怕会把它改坏。

但若这个程序 有遵循 TDD 的法则,你随时都会有个安全机制 :

提醒你程序改坏,还是程序改好

003-3.good

因为你不在害怕,你就会开始动手整理,而不会:

「放任程序码劣化而视若无睹」

文件

在使用第三方的框架时,可以使用 TDD 来测试程序的行为

003-4.good

这种用「单元测试」堆砌起来的范例,就会是一种比「使用手册」,更好的「文件」。

003-5.good

因为,这个「文件」,是用程序码实际描述的,你会更加清楚,每一个涵式与参数的用途。

当有新的版本时:

执行一次单元测试,能很快地发现不一样的地方。

设计

由於 TDD 的流程,使得「产品程序」不会制约「测试程序」

003-6.good

但「测试程序」却能制约「产品程序」

003-7.good

它会逼迫你在撰写「产品程序」时,必须要将函式与其它函式进行解耦合,才能通过测试的要求。

无形中,会让你去思考:

「如何设计」

JUnit 示范

Intellij + JUnit

这边使用 IntelliJ 加上 Java 单元测试的 JUnit 框架简单示范

004-1.demo

需求

现在假定,要开发 Domain 层的一个服务 :

服务名称叫 AppInfoService

实作的功能 :

判定应用程序的版本,是不是最新的

第一法则: 在撰写一个单元测试前,不可撰写任何产品程序

依据这个法则,稍微变通一下。先创建「服务介面」与「实作类别」:

AppInfoService
004-2.demo
interface

AppInfoServiceImpl
004-3.demo
class


先命名功能方法

AppInfoService
004-4.demo

AppInfoServiceImpl
004-5.demo
implements

只做这些,应该还不会偏离法则太远

创建完类别後,创建单元测试类别

004-6.demo

(IntelliJ 快捷键 : cmd + shift + T )

IDE 会自动依据 package 名称,放置在 test/ 资料夹中

004-7.demo

第二法则: 只撰写刚好无法通过的单元测试,不能编译也算无法通过

004-8.demo
单元测试失败

(IntelliJ 快捷键 : control + shift + R )

第三法则: 只撰写刚好能通过当前测试失败的产品程序

004-9.demo
撰写产品程序


004-10.demo
单元测试成功

(IntelliJ 快捷键 : control + shift + R )

如此,就完成了一个循环,後续如果还有更复杂的功能。也是透过这种循环快速开发。


测试框架

JUnit 是 Java 的 单元测试框架,其他的程序语言也有各自的测试框架。

例如:

  • 网页的 JavaScript 有 QUnit
  • iOS 的 Swift 有 XCTest

这三个是我有用过,并且稍微整理成一个专案的:


违反直觉的力量

测试驱动开发的三大法则,是不是觉得字有点多难以记住。

你可以简单的精简为 :

先测试,後程序
  • 顺序颠倒 : 第一个重点
  • 频繁执行 : 快速的原因

顺序颠倒

这个思维模式,让我想到 「文件」(开发文件),也是一个很重要的东西。

那麽,程序开发的流程是不是也可以变成 :

文件 > 测试 > 程序 

如此的顺序执行呢? (我还在研究的问题...)


违反直觉

测试驱动开发,只是个简单的思维转变,就能够带来如此巨大的力量。

当你的主管发现你,开发的速度超快,错误率又超低的时候。

你可以跟他说 :

这个就是「违反直觉」的力量

其他还有更多「违反直觉」的事情 :

「休息是为了走更长远的路」(需要更多的放风时间 !)
「安静是种力量」(PM/SA 没事,不要那麽常跑来找我 | 你说越多,我可能会开发的越慢 !)

语录

工程师经验

拆墙容易,砌墙难
	
     -- Gamma Ray Studio

参考资料

  • Clean Code 无瑕的程序码 - 敏捷软件开发技巧守则
  • The Clean Coder 无瑕的程序码 番外篇 - 专业程序设计师的生存之道

<<:  强型闯入DenoLand[36] - Deno 1.6 释出!

>>:  Week39 - 各种安全性演算法的应用 - 窃听、电子欺骗实作 [高智能方程序系列]

Day28 传播链程序实作

今天要来设计一种算法来查找从一个人到另一个人的病毒链,可以算是复习前面的for回圈,及swap的应用...

色码转换器再进化

前言 今天来优化 Day24 做的色码挑战器,主要增加的功能如下: 新增转换成RGBA 点选色码可以...

数据中台(Data Middle Office)

过去我们可以透过建立资料仓储系统来统一储存和处理资料: • 阶段一: 关联资料库与资料仓储,以及商业...

[Pytorch] torchvision.transforms()

torchvision.transforms() Transforms are common im...

ServiceNow CIS-SIR Exam - The Real World Experience

ServiceNow CIS-SIR Exam - The Real World Experienc...