相关文章推荐
瘦瘦的泡面  ·  深入理解TDD(测试驱动开发):提升代码质量 ...·  7 月前    · 
瘦瘦的泡面  ·  究竟该如何进行测试驱动开发(TDD)?-腾讯 ...·  7 月前    · 
瘦瘦的泡面  ·  测试驱动开发_百度百科·  7 月前    · 
瘦瘦的泡面  ·  (译)TDD(测试驱动开发)的5个步骤- ...·  7 月前    · 
小百科  ›  究竟该如何进行测试驱动开发(TDD)?开发者社区
TDD(测试驱动开发) 社区功能 接口测试 产品测试 测试驱动开发
瘦瘦的泡面
7 月前
tyrchen

究竟该如何进行测试驱动开发(TDD)?

前往小程序,Get 更优 阅读体验!
立即前往
腾讯云
开发者社区
文档 建议反馈 控制台
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
tyrchen
首页
学习
活动
专区
工具
TVP 最新优惠活动
返回腾讯云官网
社区首页 > 专栏 > 究竟该如何进行测试驱动开发(TDD)?

究竟该如何进行测试驱动开发(TDD)?

作者头像
tyrchen
发布 于 2022-03-29 10:13:35
1.4K 0
发布 于 2022-03-29 10:13:35
举报
文章被收录于专栏: 程序人生

前两天,一个微信好友,也是我《Rust 第一课》的读者,就我课程中这段话跟我讨论了几句 TDD(Test Driven Development):

在撰写实现之前撰写单元测试,这是标准的 TDD 的方式。我个人不是 TDD 的狂热粉丝,但 我会在构建完 trait 后,就为这个 trait 撰写测试代码。因为在写测试代码的时候,就是一个很好地验证接口是否好用的时间点 。我不希望实现完 trait 之后,才发现 trait 的定义有瑕疵,需要修改,这个时候改动的代价就比较大了。所以,当 trait 推敲完毕,我会开始写使用 trait 的测试代码,感受 trait 在使用过程中的体验。此刻,如果写测试用例时用得不舒服,或者为了使用它需要做很多繁琐的操作,那么我会重新审视 trait 的设计。你如果仔细看单元测试的代码,就会发现,我秉持测试 trait 接口的思想。尽管在测试中我需要一个实际的数据结构进行 trait 方法的测试,但核心的测试代码,我都是使用泛型函数,让这些代码只跟 trait 相关。这样一来可以避免某个具体的 trait 实现的干扰,二来可以让我未来加入更多 trait 实现时,可以共享测试代码。比如未来我支持 DiskTable,那么只消加几个测试例,调用已有的泛型函数即可。

他觉得这似乎和 TDD 的思想并不一致,并问我我对于网上 TDD 已死的言论是怎么看待的。其实 TDD 已死这样的言论大概 14 年前后就出来了,几年前我为了反驳还把自己对 TDD 的思考总结为一篇文章: 如何用正确的姿势打开 TDD? 这篇文章里的基本观点都是成立的。我再把最近的一些思考放出来跟大家分享一下。

究竟怎样做才算 TDD?

首先,TDD 并不存在一个特别「官方」的解释。Wikipedia 的定义我觉得算是比较符合我的认知:

Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: requirements are turned into very specific test cases , then the software is improved to pass the new tests, only. This is opposed to software development that allows software to be added that is not proven to meet requirements.

在我看来,一切机械地把 TDD 理解为一系列不得不进行的流程,都犯了教条主义的错误,过于刻板。软件工程与其说是一门科学,不如说是在长时间试错过程中,总结出来的方法论。既然是方法论,那么就有使用它的上下文,或者说场景。所以,掌握 TDD 的精髓,根据自己的实际情况采纳合理的流程,去芜存菁,而不是机械地采纳 TDD 的流程或者教条,才是正途。

那么根据 Wikipedia,TDD 的核心是什么呢?是使用测试去描述需求,然后实现需求,并用测试来验证需求得到了实现。

不幸的是,需求作为一种文字性的表达,很难直观用测试代码去表述。所以,我们需要对需求进行功能上的设计(包括架构),用描述行为的代码来描述实现需求所需要的功能,这样才能用测试代码去调用这些描述行为的代码来表达需求。这听上去很拗口,那么,什么样的代码可以用来描述行为呢?

答案是 接口 。接口是个宽泛的定义,它可以是 trait (rust) / typeclass (haskell) / interface (java) / behavior (elixir) 等编程语言本身就提供的语法定义出来的接口,也可以是任何的函数或者方法的函数签名。一旦我们把接口和需求对应起来,我们就可以使用相关的接口撰写测试来描述需求。通过这个过程,我们还可以验证我们的接口设计是否合理。

所以在我看来,TDD 是一种验证接口设计的,代价最小的手段。这可能是 TDD 最最重要的功效。借助 TDD,我可以在没有撰写任何实际功能之前,通过测试来感受接口使用的过程是否流畅。如果在撰写测试时发现接口不合理,不好用,不漂亮,表达能力不强,过早决策(比如可以用泛型的地方使用了具体的类型),那么,我们可以花费很小量的代码不断迭代设计接口,直至接口达到了实用与美感的平衡。

如果在使用 TDD 的过程中,达到了这样的效果,那么我就认为这是成功的,高质量的 TDD。至于走什么具体的流程,以什么顺序写测试代码和功能代码,那都是细枝末节,团队可以自己掌控。

TDD 要做到什么程度?

产品要为需求服务,无论是开发代码,还是测试代码,也都要为这一目标而服务。TDD 做到什么程度要看你在哪个层次考虑问题。如果在产品层面,那么它处理的是产品和外界交互的接口,包括产品和用户间的接口,产品和服务器间的接口,以及产品和第三方集成所需的接口;如果在某个模块的层次考虑 TDD,那么它处理的是这个模块和其它模块交互的公开接口(模块和模块间的需求);如果在类或者结构这个层次考虑 TDD,那么它处理的是这个类或者结构和其它类或结构交互的公开方法和属性(类或结构之间的需求)。

你看,我在这几个层次考虑的都只是接口,并且是外部(公开)接口。无论我们采用什么样的架构,引入什么设计思路,使用什么样的手段编码,测试关心的都只该是外部接口。对调用者来说,外部接口是一份严格的契约 —— 用户如何使用产品的契约,客户端如何与服务器通讯的契约,模块如何被其它模块调用的契约,类如何跟其它类发生作用的契约等等。

从这个角度来看,TDD 应该仅限于外部接口,不应该使用在私有接口上。事实上,任何时候,如果你花费时间和精力为私有接口进行测试(不管什么级别的测试),都是有害无益的。私有接口不是契约,在它所处的层级来看,这些接口可以是不稳定的,随需而变的。所以,如果花费心力去测试私有接口,如果这个接口发生剧烈变化,那么,一切投入都会打水漂。

有同学可能会说:外部接口也可能发生剧烈变化啊!

没错。外部接口发生剧烈变化有几种可能:1) 原有的接口设计考虑不周,甚至有问题,无法很好地应对现有的需求,不得不修改。2) 当需求变更时,原有接口不适应新的需求,不得不拓展以应对新的需求。3) 需求发生剧烈变化,导致接口设计需要跟着变化。

对于 1),TDD 可以很好地避免这个问题;对于 2) 在使用 TDD 对接口迭代的过程中,我们可以通过更深入地挖掘潜在的需求,和进行延迟决策,来减少其带来的影响。

我常常说,产品代码和测试代码,你起码要保持其中之一的稳定性,否则你怎么确保正确性?如果你经常发现在修改产品代码时,需要同时修改测试代码,那么要么你的测试引入了太多对私有接口的不必要的测试,要么你的接口定义不好。这样的代码的质量是堪忧的,不稳定的。

TDD 和单元测试是什么关系?

最后,我们来谈谈 TDD 和单元测试的关系。很多人把 TDD 等同于一种在撰写代码前先撰写单元测试的行为,通过上面的分析,现在你应该会觉得这种认识是不妥当的。TDD 是一种思想,这里的 T 可以是任何种类的测试。至于是什么种类,就像上文分析的那样,取决于你在哪个层次考虑问题。下面是应用 TDD 思想在不同层级可以使用的测试方法:

本文参与 腾讯云自媒体同步曝光计划 ,分享自微信公众号。
原始发表:2022-03-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除
腾讯云测试服务
单元测试
java

本文分享自 程序人生 微信公众号, 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!

腾讯云测试服务
单元测试
java
评论
登录 后参与评论
0 条评论
热度
最新
登录 后参与评论
推荐阅读
LV.
文章
0
获赞
0
目录
  • 究竟怎样做才算 TDD?
  • TDD 要做到什么程度?
  • TDD 和单元测试是什么关系?
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
免费体验 产品介绍 产品文档
2核2G服务器新用户限时秒杀28元/年
领券
  • 社区

    • 技术文章
    • 技术问答
    • 技术沙龙
    • 技术视频
    • 学习中心
    • 技术百科
    • 技术专区
  • 活动

    • 自媒体同步曝光计划
    • 邀请作者入驻
    • 自荐上首页
    • 技术竞赛
  • 资源

    • 技术周刊
    • 社区标签
    • 开发者手册
    • 开发者实验室
  • 关于

    • 社区规范
    • 免责声明
    • 联系我们
    • 友情链接

腾讯云开发者

扫码关注腾讯云开发者

扫码关注腾讯云开发者

领取腾讯云代金券

热门产品

  • 域名注册
  • 云服务器
  • 区块链服务
  • 消息队列
  • 网络加速
  • 云数据库
  • 域名解析
  • 云存储
  • 视频直播

热门推荐

  • 人脸识别
  • 腾讯会议
  • 企业云
  • CDN加速
  • 视频通话
  • 图像分析
  • MySQL 数据库
  • SSL 证书
  • 语音识别

更多推荐

  • 数据安全
  • 负载均衡
  • 短信
  • 文字识别
  • 云点播
  • 商标注册
  • 小程序开发
  • 网站监控
  • 数据迁移

Copyright © 2013 - 2024 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有

深圳市腾讯计算机系统有限公司 ICP备案/许可证号: 粤B2-20090059 深公网安备号 44030502008569

腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287

问题归档 专栏文章 快讯文章归档 关键词归档 开发者手册归档 开发者手册 Section 归档

Copyright © 2013 - 2024 Tencent Cloud.

All Rights Reserved. 腾讯云 版权所有

登录 后参与评论
 
推荐文章
瘦瘦的泡面  ·  深入理解TDD(测试驱动开发):提升代码质量的利器-CSDN博客
7 月前
瘦瘦的泡面  ·  究竟该如何进行测试驱动开发(TDD)?-腾讯云开发者社区-腾讯云
7 月前
瘦瘦的泡面  ·  测试驱动开发_百度百科
7 月前
瘦瘦的泡面  ·  (译)TDD(测试驱动开发)的5个步骤- Iannnnnnnnnnnnn - 博客园
7 月前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
小百科 - 百科知识指南
© 2024 ~ 沪ICP备11025650号