Lecture 9 软件测试与调试
测试是发现 errors,调试是定位并修改 errors。
测试之前,先保证程序能跑起来(能过编译),且备好输入输出数据。
调试有三种方式:
- brute force,这里指的是肉眼死死盯着看
- backtracking,比较适合小型程序
- cause elimination,猜什么东西导致 bug,然后检查是不是
为了便于测试和调试,代码不应该是一大块一大块的,而应该是分成若干功能(函数)。
ISO91261 指出了关于产品质量的六个属性,这些属性可以从主观或客观方面进行衡量:
几个术语
Error,Fault,Failure
这三个越来越严重。
- Error 是 mistake,就是开发者代码写错了,可能导致 fault
- Fault 是 wrong,就是一个或多个 error 导致的,可能导致 failure
- Failure,很严重,一个或多个 fault 导致的,可能会导致最终的系统崩溃、数据丢失
Software Faults
课件第 17 页列举了好多。不过最常见的是以下两种:
- Algorithmic faults,就是一个组件,执行指定算法,得到错误的结果,那说明算法实现出问题了
- computational & precision faults,就是使用的计算公式,得到了不准确的答案,或者精度不足
Verification,Validation
- verification(验证),
- validation(确认),
静态验证与动态验证
静态验证不需要执行软件代码,而动态验证需要。
静态验证就是仅阅读代码来查找 faults。动态验证就是让程序把测试跑一遍。
Omission,Commission
- 白盒测试找不出 omission 错误(功能性)
- 黑盒测试找不出 commission 错误(额外功能性)
开发过程中的测试
前四种用的比较多。
- 单元测试 unit testing,被测试的可以是一个类或者子系统,也可以是 GUI 按钮,需要使用单元的编程接口
- 集成测试 integration testing,就是把两个或者多个单元结合起来一起测试,确保能够正常协作;可以是自顶向下、自底向上或者端对端的;可能需要使用系统级别的编程接口
- 系统测试 system testing,仅用黑盒测试,测试整个软件系统,确保正确工作,满足用户需求,可能要用到 GUI 了
- 验收测试 acceptance testing,由用户进行,确认满足需求
- 回归测试 regression testing,说白了就是,软件进行修改之后,再把之前的测试跑一遍,确保之前已经解决掉的错误不会重新出现。可能需要使用自动化的测试管理工具。此外为了让测试易于理解,最好分类一下。如果之前累积的测试太多,还要确定不同测试的优先级,比如用户需求相关的测试优先。
- 现场测试 field testing,分 alpha 和 beta 两种。alpha 是开发人员测,beta 是找志愿者用户体验预览版。beta 测试可以找出很多开发团队没想到的错误。
当测试已经花了太多时间(超出预算),或者所有能想到的测试点都通过了,或者没能全部通过但是风险已经很低了,就可以结束测试。
测试应当尽量用少的测试点来完成。穷举测试(exhaustive testing) 会花费大量的时间,不切实际。
黑盒白盒
- 黑盒测试的测试数据(输入)完全根据规格说明书编写,
- 白盒测试的测试数据(输入)是根据代码实现编写。
Coverage Interpretation
第四十页。机翻如下。
- 黑盒测试提供了规范的覆盖范围,但不是实现的全部覆盖范围。也就是说,实现中可能存在生成规范中未说明的结果的代码。
- 白盒测试提供了实现的覆盖范围,但不包括规范。也就是说,规范中可能声明了在实现中没有代码的行为。
黑盒测试
根据规格说明书构造测试数据,不关心代码如何实现,只管对不对
黑盒测试技术
CS265 都学过了其实
- 等价类
- 边值测试
- 组合测试
- 随机测试
黑盒测试场景
- 对于功能性需求,都要用黑盒测试跑一遍;
- 对于非功能性需求,跑黑盒测试可以研究程序性能和易用性等方面。
- 回归测试的时候也要跑黑盒
白盒测试
根据代码的实现构造测试数据,看看覆盖了多少之类的
白盒测试技术
也是 CS265 都学过了,但是差不多忘干净了
- 语句覆盖
- 分支覆盖
- 条件覆盖
- CDC
- MCC
- 数据流(du pair),课件当中花了稍微多一点的篇幅介绍,不知道会不会考
测试工具
- 对于 GUI 界面的测试,可以搞模拟按键之类的东西
- 对于网络程序测试,可以搞爬虫
- Junit 和 Test NG 是两个很有名的测试工具