本章重点:
- 单元测试
- 回归测试
- 效能分析
- 个人软件开发流程(PSP)
1 单元测试
如何能让自己负责的模块功能定义尽量明确,模块内部的改变不会影响其他模块,而且模块的质量能得到稳定的、量化的保证?单元测试就是一个很有效的解决方案。
1.1 创建单元测试
创建单元测试的主要步骤是:
- 设置数据;
- 使用被测试类型的功能;
- 比较实际结果和预期的结果。
1.2 好的单元测试的标准
- 单元测试应该在最基本的功能/参数上验证程序的正确性:要测试API中的每一个方法及每一个参数;
- 单元测试必须由最熟悉代码的人(程序的作者)来写;
- 单元测试过后,机器状态保持不变:这样就可以不断地运行单元测试,且保证单元测试不受以前单元测试实例的干扰。若单元测试创建了临时地文件或目录,则应该在Teardown阶段删掉;
- 单元测试要快(一个测试的运行时间是几秒钟,而不是几分钟):可分层次进行测试;
- 单元测试应该产生可重复、一致的结果:如果单元测试的结果是错的,那一定是程序出了问题,而且这个错误一定是可以重复的;
- 独立性-单元测试的运行/通过/失败不依赖于别的测试,可以认为构造数据,以保持单元测试的独立性;
- 单元测试应该覆盖所有代码路径:但要注意,100%的代码覆盖率并不等同于100%的正确性;
- 单元测试应该集成到自动测试的框架中:这样每个人都能随时、随地运行单元测试。***团队一般是在每日构建之后运行单元测试的,这样单元测试的错误就能及时被发现并得到修改;
- 单元测试必须和产品代码一起保存和维护:保证源代码和测试代码一致。
2 回归测试
在单元测试的基础上,我们就能够建立关于这一模块的回归测试(Regression Test)。在软件项目中,如果一个模块或功能以前是正常工作的,但是在一个新的构建中出了问题,那么这个模块就出现了一个退步(Regression),从正常工作的状态退化到不正常工作的状态。在一个模块的功能逐步完成的同时,与此功能有关的测试用例也同样在完善中。一旦有关的测试用例通过,我们就得到了此模块的功能基准线(Baseline),一个模块的所有单元测试就是这个模块最初的Baseline。
针对一个Bug Fix,我们也要做Regression Test,目的是:
- 验证新的代码的确改正了缺陷;
- 同时要验证新的代码有没有破坏模块的现有功能,有没有Regression。
3 效能分析工具
可用三方工具实现代码的效能分析,有两种分析方法:
/ | 抽样(Sampling) | 代码注入(Instrumentation) |
---|---|---|
定义 | 当程序运行时,Visual Studio(或其他编译工具)时不时看一看这个陈旭运行在哪一个函数内,记录下来。程序结束后,Visual Studio就会得出一个关于程序运行时间分布的大致印象 | 将检测的代码加入到每一个函数中 |
优点 | 不需要改动程序,运行较快,可以很快找到瓶颈 | 程序的一举一动都被记录在案,程序的各个效能数据都可以被精确地测量 |
缺点 | 不能得出精确的数据,也不能准确表示代码中的调用关系树(Call Tree) | 程序地运行时间会大大加长,还会产生很大地数据文件,也相应增加了数据分析地时间。同时,注入地代码也影响了程序真实地运行情况 |
4 个人开发流程(PSP)
卡内基梅隆大学(CMU)的能力成熟度模型(CMM和CMMI),是用来衡量一个团队能力的一套模型。CMU的专家们针对软件工程师也有一套模型,叫Personal Software Process(PSP)。
4.1 PSP流程介绍
根据最新版本(彼时最新,PSP 2.1)来看一个软件工程师在接到一个任务之后应该怎么做:
PSP 2.1 | 软件工程师的任务清单 |
---|---|
Planning -Estimate | 计划 -明确需求和其他相关因素,指明时间成本和依赖关系 |
Development -Analysis -Design Spec -Design Review -Coding Standard -Design -Coding -Code Review -Test | 开发 -分析需求 -生成设计文档 -设计复审(和同事审核设计文档) -代码规范(为目前的开发制定合适的规范) -具体设计 -具体编码 -代码复审 -测试(包括自测,修改代码,提交修改) |
Record Time Spent | 记录用时 |
Test Report | 测试报告 |
Size Measurement | 计算工作量 |
Postmortem | 事后总结 |
Process Improvement Plan | 提出过程改进计划 |
4.2 PSP数据比较
大学四年级学生 vs 工作三年的软件工程师
可以看到,工程师在需求分析和测试这两方面明显地要花更多的时间(多60%以上);但是在具体编码上,工程师比学生要少花1/3的时间。
4.3 PSP的特点
- 不局限于某一种软件技术(如编程语言),而是着眼于软件开发的流程,这样,开发不同应用的软件工程师可以互相比较;
- 不依赖于考试,而主要靠工程师自己收集数据,然后分析、提高;
- 在小型、初创的团队中,很难找到高质量的项目需求,这意味着给程序员的输入质量不高。在这种情况下,程序员的输出(程序/软件)往往质量也不高,然而这并不能全部由程序员负责;
- PSP依赖于数据:
- 需要工程师输入数据,记录工程师的各项活动,这本身就需要不小的时间代价;
- 如果数据不准确或有遗失,怎么办?让工程师编造一些?
- 如果一些数据不利于工程师本人(例如:花很多时间修改缺陷),我们怎么能保证工程师愿意如实地记录这些数据呢?
- PSP的目的是记录工程师如何实现需求的效率,而不是记录顾客对产品的满意度。工程师有可能很高效地开发出一个顾客不喜欢的软件(例如用户界面很差,功能未能解决用户实际问题,等等),那么这位工程师还是一个优秀的工程师么?
3 参考
[1]邹欣. 构建之法:现代软件工程(第三版)[M]. 人民邮电出版社.