测试的分类
从范围上看
![](https://i-blog.csdnimg.cn/blog_migrate/7535fc430029321ba568f040baee28d5.png)
从静态/动态上看
动态测试可能在程序完全编写完成前就用于测试代码的特定节
从结构上看
白盒测试:对程序内部代码结构的测试
黑盒测试:对程序外部表现出来的行为的测试(例如输入输出)
测试用例及编写
测试用例:输入 + 执行条件 + 期望结果
测试的动机:让代码出错,出错越快越好
编写测试的过程
先写规约,再写符合规约的测试用例
写代码、执行测试、有问题再改、再执行测试用例,直到通过它
测试驱动开发(TDD):将需求转化为具体的测试用例,然后软件经过改进,通过新的测试
规约本身也可能是错误的 - 不正确,不完整,模棱两可缺失边界情况。
JUnit测试用例参数顺序:第一个是期望值,第二个是实际值,测试方法间互不影响
黑盒测试
黑盒测试关键在于检查程序是否符合规约,完全从函数规约导出测试用例,不考虑函数内部实现。
用尽可能少的测试用例,尽快运行,并尽可能大的发现程序的错误。
等价类划分(数据间对称,传递,自反)Equivalence Partitioning 等价类划分
基于等价类划分的测试:将被测函数的输入域划分为等价类,从等价类中导出测试用例
每个等价类代表着对输入约束加以满足/违反的有效/无效数据的集合。
等价类的假设:对于相似的输入,将会展示相似的行为
故可从每个等价类中仅选一个代表作为测试用例,从而降低测试用例数量
典型的划分原则
考虑输入数据是否限定了数值范围,或是指明了特定的值,或是对不同范围的值可能采用不同的计算方案。
边界值分析 Boundary Value Analysis
边界值分析方法是对等价类划分方法的补充。
原理:大量的错误发生在输入域的“边界”而非中央
•0 是正数和负数的边界
基本类型的边界,如 INT_MAX、INT_MIN
•集合中的第一个和最后一个元素
两种覆盖方式
笛卡尔积:全覆盖
将多个划分维度上的多个取值组合起来,每个组合都要有一个用例。不过并非所有组合情况都可能。
测试完备,但用例数量多,测试代价高。
覆盖每个取值:最少 1 次即可
每个维度的每个取值至少被 1 个测试用例覆盖一次即可。
测试用例少,代价低,但测试覆盖度未必高。
白盒测试
白盒测试根据程序执行路径设计测试用例,一般较早执行。
独立/基本路径测试(independent/basis path testing):对程序所有执行路径进行等价类划分,找出有代表性的最简单的路径(例如循环只需执行 1 次),设计测试用例使每一条基本路径被至少覆盖 1 次
覆盖度测试
代码覆盖度:已有的测试用例有多大程度覆盖了被测程序,通常用百分比衡量
代码覆盖度越低,测试越不充分;但要做到很高的代码覆盖度,需要更多的测试用例,测试代价高。
语句覆盖:每⼀条语句至少执行一次
分支覆盖:判定中每个条件的所有可能结果至少出现一次,并且每个判定本身的所有可能结果也至少出现一次
路径覆盖:每条可能执行到的路径至少执行一次
测试效果:路径覆盖 > 分支覆盖 > 语句覆盖
测试难度:路径覆盖 > 分支覆盖 > 语句覆盖
测试策略:根据什么来选择测试用例
——非常重要,需要在程序中显式记录下来
目的:在代码评审过程中,其他人可以理解你的测试,并评判你的测试是否足够充分
分析工具
Junit、EclEmma、VisualVM、AppPerfect:动态检查,需要执行代码
CheckStyle、SpotBugs、PMD:静态检查,无需执行代码