软件测试
- 概念
- 确认是否达到可用级别
- 关注系统的某一侧面的质量特性
Hint
:即使最好的测试,也无法达到100%的无错误
- 特征:
- 破坏、证错、负能量
- 再好的测试也无法证明系统里不存在错误
- 一个好的测试
- 能发现错误
- 不冗余
- 最佳特性
- 别太复杂页别太简单
- 测试级别:
- 单元测试:函数级别
- 集成测试:测试多个类、包、组件
- 系统测试:测试整个系统
- 测试类别:
- 静态测试不用实际运行程序
- 动态测试:用给定的测试用例运行程序
- 测试和调试:
- 测试:发现是否有错误
- 调试:识别错误根源,消除错误
- 白盒测试和黑盒测试:
- 白盒测试:对程序内部代码结构的测试
- 黑盒测试:对程序外部表现出来的行为的测试
测试用例
- 概念:输入+执行条件+期望结果
- 好的测试用例:
- 最可能发现错误(
而不是证明程序正确) - 不重复,不冗余
- 有效
- 不简单也不复杂
- 最可能发现错误(
测试优先编程
- 具体流程:
- 先写归约
- 在写符合归约的测试用例
- 写代码,测试
- Test-driven development(TDD)
单元测试
- 概念:针对软件的最小单元模型开展测试,隔离各个模块,容易定位错误和调试
用JUnit实现自动测试
- JUnit:
- 作为JAR在编译阶段被链接
黑盒测试
- 概念:用于检查代码功能,不关心内部实现细节
- 黑盒测试针对以下错误类型:
- 不正确或丢失的函数
- 接口错误
- 数据结构或外部数据库过程错误
- 行为或性能错误
- 初始化和终止错误
测试用例
- 检查程序是否符合规约
- 用尽可能少的测试用例,尽快运行,并尽可能大的发现程序的错误
通过划分选择测试用例
- 等价类划分:
- 将被测函数的输入域划分为等价类,从等价类中导出测试用例
- 针对每个输入数据需要满足的约束条件,划分等价类
- 每个等价类代表着对输入约束加以满足/违反的有效/无效数据的集合
- 有关划分的一些提示:
- 输入数据限定了数值范围,则…
- 输入数据指明了特定的值,则…
- 输入数据确定了一组数值,则…
- 输入数据是Y/N,则…
- 需要考虑输入数据的特殊情况(0)
- 考虑输入的上限:很大的数是否仍正确?/
边界分析
划分中包括边界
- 大量的错误发生在输入域的"边界"而非中央
- 0
- 最大值,最小值
- 空集
- 集合的第一个和最后一个元素
- 覆盖划分的两种策略:
- 笛卡尔积:全覆盖(
考试用这个
) - 覆盖每个取值:最少一次即可
- 笛卡尔积:全覆盖(
白盒测试
- 概念:
- 测试程序路径和条件
- 要考虑内部实现细节
- 根据程序执行路径设计测试用例
- 白盒测试一般较早执行
- 独立/基本路径测试:对程序所有执行路径(
条件分支,循环起始和结束
)进行等价类划分,找出有代表性的最简单的路径(例如循环只需执行1次),设计测试用例使每一条基本路径被至少覆盖1次。
测试覆盖
- 代码覆盖度:已有的测试用例有多大程度覆盖了被测程序
- 函数覆盖
- 语句覆盖
- 分支覆盖
- 条件覆盖
- 路径覆盖
- 测试效果:路径覆盖>分支覆盖/条件覆盖(二者不可比较)>语句覆盖
- 测试难度:路径覆盖>分支覆盖>语句覆盖
回归测试
一旦程序被修改,重新执行之前的所有测试
为测试策略写注释
/*
* Testing strategy
*
* Partition the inputs as follows:
* text.length():0,1,> 1
* start: 0, 1, 1 < start < text.length(),text.length()-1,text.length()
* text.length()-start: 0,1,even > 1,odd > 1
*
* Include even- and odd-length reversals because only odd has a middle element that doesn't move
*
* Exhaustive Cartesian coverage of partitions.
*/