软件测试与测试优先的编程

作者:syt

软件测试

什么是软件测试

软件测试:提高软件质量的重要手段。
确认是否达到可用级别(用户需求)。

测试特性

测试跟其他活动的目标相反——破坏、证错、负能量。
再好的测试也无法证明系统无错。

什么是好的测试?
能发现错误,不冗余,最佳特性,别太复杂也别太简单。

测试等级

测试等级分为单元测试->集成测试->系统测试->验收测试、回归测试。
回归测试:代码发生变更或修复 bug 后,重新运行之前的测试(单元、集成或系统级别),以确保新代码没有破坏原有已正常工作的核心功能。

白盒测试与黑盒测试

白盒测试:对程序内部代码结构的测试。
黑盒测试:对程序外部表现出来的行为的测试。

软件测试的难点

1.暴力穷举不可行——用例空间太大。
2.随意测试效率低下——靠偶然性测试没有意义。
3.统计学采样不适用于软件。

如何做一个测试者

目标从“使其运行”变成“使其出错”。
学会对自己的代码暴力些。

测试用例

什么是测试用例

测试用例=输入+执行条件+期望结果

好测试用例的特性

1.最可能发现错误。
2.不重复不冗余
3.最有效
4.既不简单也不复杂

测试优先编程

测试优先编程

在写代码前写测试。
先写spec,再写符合spec的测试样例,再写代码实现。

spec:软件需求规范,描述软件系统功能和性能要求的文档。
写测试用例,就是理解,修正,完善spec设计的过程。

单元测试

针对程序中最小单元模型开展测试,隔离各个模块,容易定位错误和调试。

使用pytest自动单元测试

黑箱测试

只检查功能,不关心源代码。
检查程序是否符合规约。
检测错误种类:
1.功能错误或遗漏
2.接口错误
3.数据结构或外部数据库访问错误
4.行为或性能错误
5.初始化或终止错误
用尽可能少的测试用例,在尽可能短的时间内,最大限度地验证程序的合规性。

黑盒测试——通过划分选择测试用例

等价类划分

将被测函数的输入域划分为等价类,从等价类中导出测试用例。
针对每个输入数据需要满足的约束条件,划分等价类。
等价关系:自反、对称、传递。
每个等价类代表着对输入约束加以满足/违反的有效/无效数据集合。
核心假设:相似的输入=相似的行为。
选择不相似的用例——降低测试用例数量的同时保证测试覆盖率。
等价类划分指南:
1.限定数值范围——定义1个有效等价类和2个无效等价类。
2.指明特定的值——定义1个有效等价类和1个无效等价类。
3.确定一组数值——定义1个有效等价类和1个无效等价类。
4.输入为布尔值——定义1个有效等价类和1个无效等价类。
例子与练习。

黑盒测试——将边界纳入划分

边界值分析

大量的错误发生在输入域的边界而不是中央。
边界值分析已经成为一个测试技术。

为什么bugs总发生在边界

程序员经常犯大小差1的错误。
某些边界值是特值,需要特殊处理。
程序的行为在边界可能突变。
等价类划分时,将边界作为等价类之一加入考虑。
边界值划分指南:
1.5个测试用例——最小,略高于最小,正常,略低于最大,最大。
2.增加1个略高于最大和1个略低于最小。

覆盖划分的2个极端

笛卡尔积:全覆盖。
多个划分维度上的多个取值,要组合起来,每个组合都要有一个用例,但并非所有组合情况都可能。
测试完备,但用例数量多,测试代价高。
覆盖每次取值:最少1次即可。
每个维度的每个取值至少被1个测试用例覆盖一次即可。
测试用例数量少,代价低,但测试覆盖度未必高。

白盒测试

黑盒测试VS白盒测试

黑盒测试完全从函数spec导出测试样例,不考虑函数内部。
白盒测试要考虑内部实现细节。

白盒测试

根据程序执行路径设计测试用例。
白盒测试用例:
1.保证路径覆盖。
2.覆盖逻辑决策。
3.边界循环执行。
4.验证内部数据结构。
独立/基本路径测试——对程序所有执行路径进行一次等价类划分,找出最有代表性最简单的路径,设计测试用例使每一条基本路径被至少覆盖一次。

测试覆盖度

代码覆盖度

已有的测试用例多大程度覆盖了被测程序。
代码覆盖度低,测试不充分。代码覆盖度高,测试用例多,测试代价高。
覆盖率指标:函数覆盖,语句覆盖,分支覆盖,条件覆盖,路径覆盖。
测试效果:路径覆盖>分支覆盖>语句覆盖。
测试难度:路径覆盖>分支覆盖>语句覆盖。
白盒测试最彻底的办法是路径覆盖,但路径数量巨大,难以覆盖全。
实际当中,根据预先设计的覆盖度标准,逐步增加测试用例数量,直到覆盖度达标。

自动化测试与回归测试

自动化测试

手工测试代价太高,最好达到完全自动化。
自动调用被测函数、自动判定测试结果、自动计算覆盖度。

自动化测试VS自动测试生成

回归测试

一旦程序被修改,重新执行之前的所有测试。
一旦发现bug,要马上写一个可以重现该bug的测试用例,并且将其加入测试库。
自动化回归测试。

记录测试策略

记录测试策略

测试策略(根据什么选择测试用例)非常重要,需要在程序中显式记录下来。
目的:在代码评审过程,其他人能理解你的测试,并评判你的测试是否足够充分。

总结

测试优先编程:在编写实际代码前编写测试用例。
划分与边界:用于系统化选择测试用例的方法。
白盒测试与语句覆盖:用于完善和补充测试套件。
单元测试:尽可能孤立对每个模块进行独立测试。
自动化回归测试:防止已修复的bug再次出现。
远离bug:测试的本质是为了发现代码中的bug,而测试优先编程的意义在于尽可能早地发现它们——即在Bug被引入代码后瞬间将其揪出来。

← 返回博客目录