代码整洁之道
简介:
本书是编程大师“Bob 大叔”40余年编程生涯的心得体会的总结,讲解要成为真正专业的程序员需要具备什么样的态度,需要遵循什么样的原则,需要采取什么样的行动。作者以自己以及身边的同事走过的弯路、犯过的错误为例,意在为后来者引路,助其职业生涯迈上更高台阶。
本书适合所有程序员阅读,也可供所有想成为具备职业素养的职场人士参考。
第八章 测试策略
专业开发人员会测试自己的代码。但是,测试并不就是写一些单元测试或验收测试那么简单。编写这些测试只是万里长征的第一步。每个专业的开发团队都需要一套好的测试策略。
8.1 QA
-
尽管公司可能设有独立的QA小组专门测试软件,但是开发小组仍然要把“QA应该找不到任何错误”作为努力的目标。
-
QA和开发人员应该紧密协作,携手保障系统的质量。QA在团队中要扮演的便是需求规约定义者(specifier)和特性描述者(characterizer)。
-
需求规约定义者:
QA的任务便是和业务人员一起创建自动化验收测试,作为系统真正的需求规约文档。每轮迭代中,他们都可以从业务人员那里收集需求,将之翻译为向开发人员描述系统行为的测试(参考第7章)。通常,业务人员编写针对正常路径的测试(happy-path test),而由QA编写针对极端情况(corner)、边界状态(boundary)和异常路径(unhappy-path)的测试。
-
特性描述者:
QA的另一项任务是遵循探索式测试的原则,描述系统运行中的真实情况,将之反馈给开发人员和业务人员。在这项任务中,QA并没有解析需求,而是在鉴别系统的真实情况。
8.2 自动化测试金字塔
单元测试:
- 在金字塔底部是单元测试,这些测试由程序员使用与系统开发相同的语言来编写,供程序员自己使用。
- 编写这些测试的目的是在最低层次上来定义系统。开发人员是这样定义待写代码规约的:先编写测试,再编写产品代码。这些单元测试将作为持续集成的一部分来运行,用以确保程序员的代码意图没有遭到破坏。
- 单元测试是可行的,而且可以做到接近100%的覆盖率。通常而言,这个数字应该保持在90%以上。这里说的是真实的覆盖率,而不是那种虽然能通过但并不关心运行结果的错误的单元测试。
组件测试:
- 组件测试是验收测试的一种,通常,它们是针对系统的各个组件而编写的。系统的组件封装了业务规则,因此,对这些组件的测试便是对其中业务规则的验收测试。
- 组件测试由QA和业务人员编写,开发人员提供辅助。
- 组件测试差不多可以覆盖系统的一半。它们更主要测试的是成功路径的情况,以及一些明显的极端情况、边界状态和可选路径。大多数的异常路径是由单元测试来覆盖测试的。在组件测试层次,对异常路径进行测试并无意义。
集成测试:
- 这些测试只对那些组件很多的较大型系统才有意义。如图8-3所示,这些测试将组件装配成组,测试它们彼此之间是否能正常通信。照例要使用合适的模拟对象和测试辅助,与系统的其他组件解耦。
- 集成测试是编排性(choreography)测试。它们并不会测试业务规则,而是主要测试组件装配在一起时是否协调。它们是装配测试,用以确认这些组件之间已经正确连接,彼此间通信畅通。
- 集成测试一般由系统架构师或主设计师来编写,用以确认系统架构层面的结构是否正确无误。在这个层次上,也许已经可以进行性能测试和吞吐率测试了。
- 集成测试多使用与组件测试同样的语言和环境来编写,一般不会作为持续集成的一部分,因为集成测试的运行时间通常都比较长。但是,只要集成测试的编写人员认为有必要,这些测试就可以周期性(如每天一次或每周一次)运行。
系统测试:
- 这些测试是针对整个集成完毕的系统来运行的自动化测试,是最终的集成测试。它们不会直接测试业务规则,而是测试系统是否已正确组装完毕,以及系统各个组成部件之间是否能正确交互(应该包含吞吐率测试和性能测试)。
- 系统测试由系统架构师和技术负责人来编写,一般使用和UI集成测试同样的语言和环境。测试周期视测试运行时间长短而定,相对而言不会过于频繁,但越频繁越好。
- 系统测试约占测试的10%。其目的不是要确保正确的系统行为,而是要确保正确的系统构造。
人工探索式测试:
- 这是需要人工介入、敲击键盘、盯牢屏幕的测试。它们既非自动化的测试,亦非脚本化的测试。这些测试的意图,是要在验证预期行为的时候,探索系统预期之外的行为。
- 覆盖率并非此类测试的目标。探索式测试不是要证明每条业务规则、每条运行路径都正确,而是要确保系统在人工操作下表现良好,同时富有创造性地找出尽可能多的“古怪之处”。
结论
- TDD(测试驱动开发)很强大,验收测试是表达和强化需求的有效方式。
- 创建由单元测试、组件测试、集成测试、系统测试和探索式测试构成的测试体系。
- 应该尽可能频繁地运行这些测试,提供尽可能多的反馈,确保系统始终整洁。