当你在写生产代码时,你处在高认知的状态(obvious),你的研发流程和你的工程实践,有助于你一步一步的提升你的认知能力,把你的问题进行一个降解(分解),只要你做到同样的事情,你用什么方法开发,我认为都是一种高效的方法。
list
- TDD的困惑
- TDD的思考
- TDD的使用场景
- 写一个TDD的实例
- TDD对我们的影响
TDD的困惑
什么是TDD
TDD 是测试驱动开发 (Test-Driven Development)的英文简称,是敏捷开发中的一项核心实践和技术,也是一种设计方法论。TDD 的原理是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么产品代码。
Kent Beck:“测试驱动开发不是一种测试技术。它是一种分析技术、设计技术,更是一种组织所有开发活动的技术”。
分析技术: 体现在对问题域的分析,当问题还没有被分解成一个个可操作的任务时,分析技术就派上用场,例如需求分析、任务拆分和任务规划等,《实例化需求》这本书可以给予一定的帮助作用。
设计技术: 测试驱动代码的设计和功能的实现,然后驱动代码的再设计和重构,在持续细微的反馈中改善代码。
组织所有开发活动的技术: TDD 很好地组织了测试、开发和重构活动,但又不仅限于此,比如实施 TDD 的前置活动包括需求分析、任务拆分和规划活动,这使得 TDD 具有非常好的扩展性。
TDD的目标
Kent Beck 在他的著作《Test-Driven Development》一书中提到:“代码简洁可用“这句言简意赅的话,正是 TDD 所追求的目标。
对于如何保证“代码简洁可用”可以使用分而治之的方法,先达到“可用”目标,再追求“简洁”目标。
可用: 保证代码通过自动化测试。
代码简洁: 在不同阶段人们对简洁的理解程度也不一样,不过遵循的原则差不多,例如 OOD 的 SOLID 原则,Kent Beck 的 Simple Design 原则等。
虽然有很多因素妨碍我们得到整洁的代码,甚至可用的代码,无需征求太多意见,只需要采用 TDD 的开发方式来驱动出简洁可用的代码。
TDD 的规则
在 TDD 的过程中,需要遵循两条简单的规则:
- 仅在自动测试失败时才编写新代码。
- 消除重复设计(去除不必要的依赖关系),优化设计结构(逐渐使代码一般化) 。
第一条规则的言下之意是每次只编写刚刚好使测试通过的代码,并且只在测试运行失败的时候才编写新的代码,因为每次增加的代码少,即使有问题定位起来也非常快,确保我们可以遵循小步快跑的节奏;第二条规则就是让小步快跑更加踏实,在自动化测试的支撑下,通过重构环节消除代码的坏味道来避免代码日渐腐烂,为接下来编码打造一个舒适的环境。
关注点分离是这两条规则隐含的另一个非常重要的原则。其表达的含义指在编码阶段先达到代码“可用”的目标,在重构阶段再追求“简洁”目标,每次只关注一件事!!!
TDD 的口号
简单来说,不可运行/可运行/重构——这正是测试驱动开发的口号,也是 TDD 的核心。在这个闭环中,每一个阶段的输出都会成为下一阶段的输入。
- 不可运行——写一个功能最小完备的单元测试,并使得该单元测试编译失败。
- 可运行——快速编写刚刚好使测试通过的代码,不需要考虑太多,甚至可以使用一些不合理的方法。
- 重构——消除刚刚编码过程引入的重复设计,优化设计结构。
假设这样的开发方式是可能的,那我采用 TDD 真正的动机是什么?
采用 TDD 的动机
- 控制编程过程中的忧虑感。
有一个有趣的想象,当我感觉压力越大,自身就越不想去做足够多的测试。当知道自己做的测试不够时,就会增加自身的压力,因为我担心自己写的代码有 BUG,对自己编写的代码不够自信,这是一种心态上的变化。此时测试是开发人员的试金石,可以将对压力的恐惧变为平日的琐事,采用自动化测试,就有机会选择恐惧的程度。
- 把控编程过程中的反馈与决策之间的差距。
如果我做了一周的规划,并且量化成一个个可操作的任务写到 to-do list,然后使用测试驱动编码,把完成的任务像这样划掉,那么我的工作目标将变得非常清晰,因为我明确工期,明确待办事项,明确难点,可以在持续细微的反馈中有意识地做一些适当的调整,比如添加新的任务,删除冗余的测试;还有一点更加让人振奋,我可以知道我大概什么时候可以完工。项目经理对软件开发进度可以更精确的把握。
为什么TDD没有普及
很多项目团队并没有使用 TDD (测试驱动开发)的开发方式,我想这在目前的开发团队中占比非常高,特别是中小型公司的前端开发团队,几乎可以说是“全军覆没”,为什么?原因可能是以下所列的一些:
- TDD 太麻烦,增加了工作量
- TDD 太复杂,普通程序员掌握不了
- TDD 并不是必须的,不必要投入这些时间成本
- TDD 是个太理想的方式,还是要面对现实
- TDD 很好,可是我们公司实力弱,招不起那么专业的开发人员啊
就好比,有人跟我们说,健身很快乐、很上瘾,收益非常大,而我们却没办法体会,也明知这个道理,也不能实践。然后呢?总是有一堆理由和借口来给别人,也给自己开脱。
- 健身 太麻烦,太累,每天上班工作已经很累了
- 健身 太难了(要办健身卡,请健身教练),一般人没条件
- 健身 也不是第一要务,暂时没那么多时间去投入
- 健身 的生活方式是理想的方式,目前的现况还是要面对的
- 健身 很好,可是家里的现状不允许啊
我想这里面有一些可能的原因:
-
没有了解健身的益处(对 TDD 的理解可能还不够深刻)
-
没有勇敢的走出第一步(没有给团队一定的空间和时间去尝试和体会)
-
安于当下(眼光看得不够远,只关注眼下项目的结果)
-
没有真正体会过 TDD 的好处和收益
-
缺乏软件质量意识
-
缺乏一定程度的程序设计能力,很难设计出高内聚低耦合、意图清晰的结构和代码。
-
缺乏分析需求并进行任务分解和规划的能力,很容易在还没开始 TDD 的时候就被打乱了节奏。
-
缺乏合适的测试环境和测试规范。
-
测试优先的习惯难以养成。
-
重构手法不熟练。
当然,健身还只是一个个人的事情,而 TDD 则是一个团队和一个公司的事情,有时候可能最终能推动会显得更困难。当然,也可以从自身做起,逐渐带动周围的人慢慢加入,这需要一个过程。
简述TDD开发流程
- 需求分析
理解业务需求
- tasking(任务拆分)
把我们大的需求拆分成小的,然后逐一击破,最后大的测试也就顺其自然的完成了,分别是happy path和sad path(异常抛出)
- 重构
好处 -> 可维护性和可扩展性 -> 可读性 -> 性能 -> 节省成本
总结
因为我当前所在团队是以敏捷的方式来进行开发,故把和敏捷开发息息相关的TDD来总结一下,我们团队当下也正在尝试一些新的可以提高个人水准和工作效率的方案,例如TDD。
相关资料
- https://juejin.cn/post/7078906878779981832
- https://juejin.cn/post/6930895635277316103
- https://www.bilibili.com/video/BV1zK4y1n7jf/?spm_id_from=autoNext&vd_source=144d89ce87155b6e261663d11afd3e08
- https://juejin.cn/post/6844903780970921991
- https://www.bilibili.com/video/BV1eL4y1M7PJ/?spm_id_from=333.337.search-card.all.click&vd_source=144d89ce87155b6e261663d11afd3e08
水平有限,还不能写到尽善尽美,希望大家多多交流,跟春野一同进步!!!