# 测试驱动开发 Test Driven Development (TDD) ## 定义 “测试驱动开发”是指一种编程风格,其中紧密结合了三个活动:编码,测试(以编写单元测试的形式)和设计(以重构的形式)。 可以通过以下规则简要描述它: - 编写描述程序一个方面的“单个”单元测试 - 运行测试,该测试将失败,因为该程序缺少该功能 - 编写“足够”的代码(最简单的方法)以使测试通过 - “重构”代码,直到符合简单性标准为止 - 随着时间的推移重复“累积”单元测试 ## 预期收益 - 许多团队报告缺陷率显着降低,但以初期开发工作的适度增加为代价 - 这些团队倾向于报告说,这些间接费用已被项目最后阶段的工作量减少所抵消 - 尽管到目前为止,经验研究都未能证实这一点,但资深从业人员报告说,TDD可以提高代码的设计质量,更普遍的是更高程度的“内部”或技术质量,例如,提高内聚和耦合度。 ## 常见陷阱 典型的个人错误包括: - 忘记经常运行测试 - 一次编写太多测试 - 编写太大或粗粒度的测试 - 编写过于琐碎的测试,例如省略断言 - 为琐碎的代码编写测试,例如访问器 典型的团队陷阱包括: - 部分采用–团队中只有少数开发人员使用TDD - 测试套件的维护不良–通常导致测试套件的运行时间过长 - 废弃的测试套件(即很少运行或从未运行)–有时是由于维护不善,有时是由于团队更替 ## 起源 尽管在编程之前进行测试详细说明的想法并不是敏捷社区的独创,但TDD构成了突破,因为它将该思想与“开发人员测试”相结合,为开发人员测试提供了新的尊重。 - 1976年:格伦福德·迈尔斯(Glenford Myers)出版了“ 软件可靠性 ”,其中指出“开发人员永远不要测试自己的代码”是“公理”(开发人员测试的黑暗时代)。 - 1990年:以“黑匣子”技术为主导的测试学科,特别是以“捕获和重放”测试工具的形式 - 1991年:在Taligent独立创建了一个测试框架,该框架与SUnit有着惊人的相似之处(来源) - 1994年:Kent Beck编写了Smalltalk的SUnit测试框架(源) - 1998年:关于极限编程的文章提到“我们通常首先编写测试”(源) - 1998年至2002年:“测试优先”被细化为“测试驱动”,尤其是在C2.com Wiki上 - 2000年:模拟对象是在此期间开发的新技术(来源) - 2003年:肯特·贝克(Kent Beck)出版的“ 测试驱动开发:以实例为例 ” 到2006年,TDD是一门相对成熟的学科,已经开始鼓励从中获得进一步的创新,例如ATDD或BDD)。 ## 使用迹象 - “代码覆盖率”是证明使用TDD的常用方法;虽然高覆盖率不能保证正确使用TDD,但覆盖率低于80%可能表明团队对TDD的掌握不足 - 版本控制日志应显示每次签入产品代码时都要检查测试代码,数量大致可比 ## 技能水平 初学者 - 能够在编写相应的代码之前编写单元测试 - 能够编写足以使测试通过失败的代码 中级 - 练习“测试驱动的错误修复”:发现缺陷后,编写纠正缺陷的测试 - 能够将复合程序功能分解为要编写的几个单元测试的序列 - 知道并可以列举许多策略来指导编写测试(例如,“在测试递归算法时,首先为递归终止案例编写测试”) - 能够从现有单元测试中排除可重用元素,从而产生针对特定情况的测试工具 高级 - 能够为宏观特征制定计划的单元测试的“路线图”(并在必要时进行修改) - 能够“测试驱动”各种设计范例:面向对象,功能,事件驱动 - 能够“测试”各种技术领域:计算,用户界面,持久数据访问… ## 进一步阅读 《测试驱动开发》,肯特·贝克(Kent Beck)