我是一名喜欢追求高质量代码和高效率工做的软件开发工程师,所以我学习 SOLID 和 Simple Design 等原则、阅读优秀的开源代码、阅读相关的书籍、学习软件过程方法和真实项目实践,可是在追求高质量代码的道路上,总感受目前的知识还不能帮我塑形成一种思惟框架。在 2018 年年初机缘巧合阅读了TDD(测试驱动开发)培训录这篇文章,瞬间欣喜若狂!程序员
到如今接触 TDD 将近一年,期间由于沉不下心只阅读了不多的资料就在项目中实践了一段时间,获得的效果还不错,自觉得已经很理解 TDD 实践和背后的思想,结果在不断阅读相关书籍和关于一些 TDD 的讨论中不断暴露本身的无知,发现本身就像站在“达克效应”曲线的愚昧之巅,原来大部分自认为正确的知识都是不许确甚至是错误的。不过我很享受这种过程,在学习的过程当中不断验证本身的知识是很是有趣的,这使我变得更有自知之明的同时也在不断突破自身的认知上限。编程
接下来我会经过图文的方式总结这段时间来对 TDD 的实践和思考,以便于沉淀自身对 TDD 的理解,但愿对读者有所帮助,也但愿读者能够指点一二,集思广益才能离真相更进一步。框架
Kent Beck:“测试驱动开发不是一种测试技术。它是一种分析技术、设计技术,更是一种组织全部开发活动的技术”。
分析技术: 体如今对问题域的分析,当问题尚未被分解成一个个可操做的任务时,分析技术就派上用场,例如需求分析、任务拆分和任务规划等,《实例化需求》这本书能够给予必定的帮助做用。函数
设计技术: 测试驱动代码的设计和功能的实现,而后驱动代码的再设计和重构,在持续细微的反馈中改善代码。单元测试
组织全部开发活动的技术: TDD 很好地组织了测试、开发和重构活动,但又不只限于此,好比实施 TDD 的前置活动包括需求分析、任务拆分和规划活动,这使得 TDD 具备很是好的扩展性。学习
Kent Beck 在他的著做《Test-Driven Development》一书中提到:“代码简洁可用这句言简意赅的话,正是 TDD 所追求的目标”。测试
对于如何保证“代码简洁可用”可使用分而治之的方法,先达到“可用”目标,再追求“简洁”目标。优化
可用: 保证代码经过自动化测试。编码
代码简洁: 在不一样阶段人们对简洁的理解程度也不同,不过遵循的原则差很少,例如 OOD 的 SOLID 原则,Kent Beck 的 Simple Design 原则等。设计
虽然有不少因素妨碍咱们获得整洁的代码,甚至可用的代码,无需征求太多意见,只须要采用 TDD 的开发方式来驱动出简洁可用的代码。
在 TDD 的过程当中,须要遵循两条简单的规则:
第一条规则的言下之意是每次只编写刚恰好使测试经过的代码,而且只在测试运行失败的时候才编写新的代码,由于每次增长的代码少,即便有问题定位起来也很是快,确保咱们能够遵循小步快跑的节奏;第二条规则就是让小步快跑更加踏实,在自动化测试的支撑下,经过重构环节消除代码的坏味道来避免代码日渐腐烂,为接下来编码打造一个温馨的环境。
关注点分离是这两条规则隐含的另外一个很是重要的原则。其表达的含义指在编码阶段先达到代码“可用”的目标,在重构阶段再追求“简洁”目标,每次只关注一件事!!!
简单来讲,不可运行/可运行/重构——这正是测试驱动开发的口号,也是 TDD 的核心。在这个闭环中,每个阶段的输出都会成为下一阶段的输入。
假设这样的开发方式是可能的,那我采用 TDD 真正的动机是什么?
有一个有趣的想象,当我感受压力越大,自身就越不想去作足够多的测试。当知道本身作的测试不够时,就会增长自身的压力,由于我担忧本身写的代码有 BUG,对本身编写的代码不够自信,这是一种心态上的变化。此时测试是开发人员的试金石,能够将对压力的恐惧变为平日的杂事,采用自动化测试,就有机会选择恐惧的程度。
若是我作了一周的规划,而且量化成一个个可操做的任务写到 to-do list,而后使用测试驱动编码,把完成的任务像这样划掉,那么个人工做目标将变得很是清晰,由于我明确工期,明确待办事项,明确难点,能够在持续细微的反馈中有意识地作一些适当的调整,好比添加新的任务,删除冗余的测试;还有一点更加让人振奋,我能够知道我大概何时能够完工。项目经理对软件开发进度能够更精确的把握。
这三条规则的目的是达到代码的“可用”目标,只须要键入咱们认为正确的代码使测试程序尽快经过便可。
不管是测试程序覆盖的范围仍是重构时的中间步骤,TDD 建议是采用尽可能小的步伐(测试没法再拆分,微小的重构),可是也没有强制必定按照这种步伐,不一样人的步伐能够不一样,能够在实践中不断寻找适合本身的步伐,可是前提必须尽可能小。
除了那些不写测试还能对本身的代码感到很是自信的人以外,这取决于本身的经验和对代码的信心程度。若是某些代码本身认为即便不须要测试,运行和重构时也很是有信心,就能够不须要测试,好比大部分 set get ;相反,若是去掉会让本身感到不安,就须要考虑加入测试。
这个问题《测试驱动开发》做者 Kent Beck 也很难去证实,由于没有专门的人真正去作过这个统计,因此他表示不否定可能存在一些更好的顺序设计。
由于要尽快使测试运行起来,这样能够下降来自系统的反馈周期,若是可以快速持续获得来自系统的反馈,那么就能够持续保持小步快跑的节奏。若是能够短期实现一个好的设计,写出优雅简洁的代码,那么在一开始 TDD 的时候,就应该采用最好的设计,由于这样的效率会比较高。
TDD 不是银弹,遇到问题须要寻找核心痛点是什么,而后再对症下药。
与 ATDD 不一样, UTDD 主要面向的是开发人员,因此 UTDD 在这里主要关注的是软件内部的质量属性,若是说软件的外部质量体如今“缺陷数”和“缺陷率”等指标,那软件的内部质量属性体如今代码的“可测试性”、“可读性”和“可扩展性”等,这些几乎是每一位软件开发工程师的追求。“单元测试”做为 TDD 的产物之一,为了把控软件内部的质量属性,一般会使用到自动化“单元测试”做为软件质量保证的“根基”。
在计算机编程中,单元测试(英语:Unit Testing),一般由软件开发人员编写,用于确保他们所写的代码匹配软件需求和遵循开发目标,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工做。
每一个理想的测试案例独立于其它案例;为测试时隔离模块,常用 stubs、mock 或 fake 等测试马甲程序。
一般来讲,程序员每修改一次程序就会进行最少一次单元测试,在编写程序的先后极可能要进行屡次单元测试,以证明程序达到软件规格书要求的工做目标。
从维基百科的描述中能够看出单元测试拥有以下特色
这里从我我的的角度对单元测试进行简单的分析,但对“单元测试”的理解,或者是它所处的位置仍是不够清晰,因此接下来我使用了“测试金字塔”模型来帮助我站在一个更高的视角理解“单元测试”。
上图的“测试金字塔”模型按照运行速度和投入成本两个维度对不一样阶段的测试工做进行很是直观的可视化,能够看到单元测试是位于“测试金字塔”的最底部,很明显“单元测试”相对于其它不一样阶段的测试工做,拥有速度快(运行效率),成本低(维护成本)的优点,同时也是做为上层测试工做的支撑,体现了“单元测试”的重要程度。
纸上得来终觉浅,惟有知行合一,经过理论指导实践,在实践中不断总结经验,不断验证本身的知识,才能不断对 TDD 有更深刻更正确的理解。接下来将计划出几篇文章演示使用 TDD 如何解决一些真实的案例的总结,以便于提升本身的 TDD 技艺。