原文:5 steps of test-driven development
https://developer.ibm.com/articles/5-steps-of-test-driven-development/

作者 Grant Steinfeld

发表于 2020年2月6日

在这篇文章中,我将向你介绍TDD的基础概念,如果你是敏捷开发实践者,那么TDD将是你开发生涯中的最佳实践。学习TDD是什么,理解TDD的基本流程并且知道怎么用单元测试实现TDD。你将会理解为什么在开发过程中需要使用TDD。

什么是TDD

TDD颠覆了传统的开发和测试。TDD不是先写业务代码,而是先写测试代码,写业务代码来反向满足测试代码的校验。TDD规定你先写测试代码,然后实现代码直到刚刚写的测试代码通过。

在TDD中,你先写测试,观察其失败,然后实现代码直到测试通过,听起来很倒退是吧?但是,当你使用这种测试方法时,你生成的代码会更整洁,从长远来看更不容易出错。

一个单元测试要是简单的,只涵盖一小部分逻辑的测试,例如算法。单元测试应该是确定性的。这里的“确定性”的意思是单元测试不应该有副作用,比如调用提供随机或变化数据的外部 API。同理,你将使用模拟数据代替可能随时间变化的数据。

TDD的五个步骤

TDD流程中有以下五个步骤:

  • 阅读、理解和处理功能或错误请求。
  • 通过编写单元测试来实现需求。如果你设置了热重载,因为尚未实现任何代码,所以此时单元测试是失败的。
  • 编写并实现满足要求的代码。运行所有测试,它们应该通过,如果没有通过则重复此步骤。
  • 通过重构来整理你的代码。
  • 重复。

下图展示了这些步骤及其敏捷、循环和迭代特征:

该工作流程有时也被称为红-绿-重构 (Red-Green-Refactoring),这个称呼来自周期内测试的状态。

  • 红色阶段表示代码不起作用。
  • 绿色阶段表示代码都能正常工作,但不是以最佳的方式进行。
  • 蓝色阶段表示开发人员正在重构代码,但他们确信代码已被测试覆盖,这使开发人员有信心修改和改进代码。

测试驱动开发和持续集成/持续交付

(CI) 是一种开发实践,需要开发人员每天多次将代码集成到共享存储库中。然后通过自动构建验证每次嵌入,从而使团队能够及早发现问题。通过定期集成,你可以快速发现错误,并更轻松地定位它们。

TDD 产生的单元测试也是持续集成/持续交付 (CI/CD) 过程中不可或缺的一部分。

TDD 的单元测试和持续集成/持续交付管道,如 CircleCI、GoCD 或 Travis CI,它们在提交时运行所有单元测试。

测试在部署管道中运行。如果所有测试都通过,就会进行集成和部署。但是,如果任何测试失败,该过程就会停止,从而确保构建不会被破坏。

首先设置你的工具、工具链和IDE

为了进行测试驱动的开发,你需要先设置你的工具、工具链和 IDE。在我们的项目 [code pattern] 中,我们正在开发一个 Node.js 示例,这里是我们设置的关键工具:

  • 用于 Node.js 和 NPM 的 nvm(Node版本管理器):NVM 允许你运行所需的 Node.js 版本并对其进行更改,而不会影响系统node。
  • 用于开发的 npm 库:

如何编写失败的单元测试

以下是几种不同的方法来编写失败的单元测试。

  1. 编写一个测试,引用代码中尚不存在的函数,这将导致测试失败并出现未找到的错误(例如,404 错误)。

  2. 更改断言(assert)语句以使其失败。断言语句表示被测试的代码预期返回什么值;这种语句是单元测试的关键。断言语句应反映功能或错误请求的响应。

因此,要使单元测试失败,你需要编写一个断言语句,该断言会在你想要丰富的数据结构中返回一个暂时没有的值。例如,你的 JSON 返回一个人的姓名,但你的新需求需要包含该人的手机号码。你将首先编写断言语句来包含该人的手机号码,这将导致它失败。然后,你将添加业务代码来增加该人的电话号码。

或者,在现实的编码中:你的断言语句可能是:assert actualResult == {'track':'foo fighters'}。一旦生产代码(函数)被创建,编译错误被解决,404 就会消失,但实际 actualResult 返回的结果可能是像 {} 这样的空对象。接着再将函数中的返回结果硬编码为 {‘track’:‘foo fighters’}。

测试现在将通过(绿色!)。代码现在显然只是临时的,但你可以得到基本的理解。测试已正确连接到生产代码中的某个点。从那里你可以实现实际的业务逻辑,例如,读取文件/db/调用外部 API

决定何时编写单元测试

一般来说,编写单元测试有两种情况:

案例 A:你为代表简明故事的请求编写单元测试。例如,请求可能是计算特定货币兑换所支持的国家/地区数量。我做的第一件事是编写一个单元测试并看到它失败。然后,我迭代地更改代码,直到单元测试通过。

案例 B:生产中发现的一段错误代码。此错误触发的问题需要实施修复/补丁。回到货币兑换示例,代码运行时,用户期望在许多国家/地区使用 $USD,但该行为是错误的,目前只有一个国家/地区返回。

我做的第一件事是编写一个单元测试并看到它失败。然后,更正我的实现代码,直到测试通过。这不仅修复了代码并消除了错误,而且还为我提供了一个可以重复使用的单元测试,以确保这段代码保持完整。

总结

大多数程序员不使用测试驱动开发来编写代码,但他们应该这样做。测试驱动的开发可以创建更好的容错性代码。希望你从这篇博文中了解 TDD 的理念,并将其融入你的软件开发实践中。

下一步

请继续关注有关如何在 Node.js、Java 和 Python 中进行测试驱动开发的新博客文章。

资源

非常有帮助的书与文章

Using Test-Driven Development for Microservices, Bill Doerrfeld

Test-driven Java development: Invoke TDD principles for end-to-end application developmnet, 2nd Edition by Farcic, Viktor

Unit testing principles, practices, and patterns, Vladimir Khorikov

(译)TDD(测试驱动开发)的5个步骤的更多相关文章

  1. TDD(测试驱动开发)学习一:初识TDD

    首先说一下名词解释,TDD,英文名称Test-Driven Development,中文名称测试驱动开发,简单的断下句“测试/驱动/开发”,简单的理解一下,就是测试驱动着开发,大白话就是说用一边测试一 ...

  2. TDD(测试驱动开发)培训录

    2014年我一直从事在敏捷实践咨询项目,这也是我颇有收获的一年,特别是咨询项目的每一点改变,不管是代码质量的提高,还是自组织团队的建设,都能让我们感到欣慰.涉及人的问题都是复杂问题,改变人,改变一个组 ...

  3. TDD(测试驱动开发)培训录(转)

    本文转载自:http://www.cnblogs.com/whitewolf/p/4205761.html 最近也在了解TDD,发现这篇文章不错,特此转载一下. TDD(测试驱动开发)培训录 2015 ...

  4. TDD(测试驱动开发)

    TDD(测试驱动开发)培训录 2014年我一直从事在敏捷实践咨询项目,这也是我颇有收获的一年,特别是咨询项目的每一点改变,不管是代码质量的提高,还是自组织团队的建设,都能让我们感到欣慰.涉及人的问题都 ...

  5. TDD(测试驱动开发)学习二:创建第一个TDD程序

    本节我们将学习一些测试驱动开发环境的搭建,测试驱动开发概念和流程.所涉及的内容全部会以截图的形式贴出来,如果你也感兴趣,可以一步一步的跟着来做,如果你有任何问题,可以进行留言,我也会很高兴的为你答疑. ...

  6. 基于SOA架构的TDD测试驱动开发模式

    以需求用例为基,Case&Coding两条线并行,服务(M)&消费(VC)分离,单元.接口.功能.集成四层质量管理,自动化集成.测试.交付全程支持. 3个大阶段(需求分析阶段.研发准备 ...

  7. TDD(测试驱动开发)的推广方法论

  8. 测试驱动开发(TDD)的思考

    极限编程 敏捷开发是一种思想,极限编程也是一种思想,它与敏捷开发某些目标是一致的.只是实现方式不同.测试驱动开发是极限编程的一部分. 1.极限编程这个思路的来源 Kent Beck先生最早在其极限编程 ...

  9. 测试驱动开发 TDD

    一.详解TDD 1.1.TDD概念 :Test Drived Develop 测试驱动开发是敏捷开发中的一项核心实践和技术,也是一种方法论.TDD的原理是在开发功能代码之前,编写单元测试用例代码,测试 ...

随机推荐

  1. APICloud 可视化编程 - 拖拉拽实现专业级源码

    低代码开发平台是无需编码 (0 代码或⽆代码) 或通过少量代码就可以快速生成应用程序的开发平台.它的强⼤之处在于,允许终端⽤户使⽤易于理解的可视化⼯具开发自己的应用程序,而不是传统的编写代码⽅式.当遇 ...

  2. [CISCN2019 华北赛区 Day1 Web2]ikun-1|python反序列化

    考点:JWT身份伪造.python pickle反序列化.逻辑漏洞 1.打开之后首页界面直接看到了提示信息,信息如下: 2.那就随便注册一个账号进行登录,然后购买lv6,但是未发现lv6,那就查看下一 ...

  3. 可别小看了XSS漏洞

    可别小看了XSS漏洞 ​ 对于初了解xss漏洞的人来说,XSS漏洞的危害就是获取受害者的cookie,来进行 'cookie劫持'. ​ 今天就总结一下XSS漏洞的危害性,望安全人员不要轻视,开发人员 ...

  4. 开源:Taurus.MVC-Java 版本框架 (支持javax.servlet.*和jakarta.servlet.*双系列,内集成微服务客户端)

    版本说明: 因为之前有了Taurus.MVC-DotNet 版本框架,因此框架标了-Java后缀. .Net  版本: 开源文章:开源:Taurus.MVC-DotNet 版本框架 (支持.NET C ...

  5. Linux_etc-shadow文件总结

    shadow 文件权限 $ll shadow ---------- 1 root root 1131 Aug 6 12:04 shadow 可以看出只有root可以操作它,普通用户执行passwd,内 ...

  6. LFS(Linux From Scratch)构建过程全记录(六):交叉编译临时工具

    写在前面 本章将展示如何使用刚刚构建的跨工具链来交叉编译基本实用程序. M4安装 和前文一样,先进行解压,然后cd进入 注意:不需要构建build文件夹,直接输入以下配置文件 ./configure ...

  7. 2022CSP-J初赛游记

    2022年9月16日: 下午,在学校集训,刘洋让我看了一下时间,突然发现,距离初赛就剩2天了...... 晚上,辅导班的老师对我们进行最后的培训,做了2套有道小图灵模拟题,但是做的不理想,很慌. 20 ...

  8. SkyWalking 6.x 的架构图

    可以看到主要由四部分组成: Agent(也叫Probe):代理或者探针,集成在被监测的应用中(SDK形式或者动态注入),采集应用的数据发送给后端(OAP). UI:自带的Web页面. OAP:后端,接 ...

  9. 使用 openssl 生成 https 证书, 并在 nginx 中配置 https

    创建一个私钥 openssl genrsa -des3 -out server.key 2048 注意:这一步需要输入私钥,否则会提示:You must type in 4 to 1023 chara ...

  10. MySQL 自增字段取值

    1 前言 本文来自回答思否网友的一个问题,这个网友新建了一张表,auto_increment_increment设为10,AUTO_INCREMENT主键起始值设为9, 当他插入数据的时候,发现主键值 ...