7.6.1 软件测试概述
软件测试首先是一种工程性怀疑:不假设程序天然正确,而是用计划、用例、执行和评审去主动暴露缺陷。它的价值不在于“证明没有问题”,而在于尽可能早、尽可能经济地发现问题,并给修复和交付决策提供证据。
测试到底能证明什么
测试可以证明“某个测试条件下出现了错误”,却不能证明“所有条件下都没有错误”。原因很简单:真实软件的输入组合、状态组合和执行路径通常巨大到无法穷尽。
例如一个登录功能看似只有用户名和密码两个输入,但还会受到账号状态、密码策略、验证码、网络状态、数据库状态、并发请求、浏览器缓存等因素影响。即使这些因素每个只取几个值,组合数量也会迅速膨胀。
| 命题 | 是否成立 | 正确理解 |
|---|---|---|
| 测试能发现缺陷 | 成立 | 只要实际结果与预期结果不一致,就能暴露问题 |
| 测试能提高软件可信度 | 成立 | 用例越有代表性,信心越强 |
| 测试能证明软件没有缺陷 | 不成立 | 未发现缺陷不等于缺陷不存在 |
| 穷尽测试在实际项目中总能做到 | 不成立 | 输入、状态和路径组合通常不可穷尽 |
测试用例不是只有输入
一个完整测试用例至少要包含输入数据和预期结果。只有输入、没有预期结果,就无法判断程序执行后是对还是错。
| 要素 | 说明 | 例子 |
|---|---|---|
| 测试目标 | 这条用例要验证什么规则 | 成绩 90 到 100 应判为“优” |
| 输入数据 | 提供给被测对象的数据或操作 | 输入成绩 95 |
| 执行条件 | 环境、前置状态、权限、配置 | 已登录教师账号,成绩录入页面可用 |
| 预期结果 | 正确系统应给出的结果 | 页面显示等级“优”并保存成功 |
| 实际结果 | 执行后观察到的输出 | 用于和预期结果比较 |
考试常把“测试用例包括输入数据和预期输出”作为基础判断点。不要把测试用例误解成一组随机输入。
为什么要尽早、不断地测试
缺陷发现越晚,修复成本越高。需求阶段发现“业务规则写错”可能只改文档;设计阶段发现“接口方向不对”要改模块设计;编码完成后才发现,则可能牵连代码、测试数据、文档、部署脚本甚至用户培训。
所以“尽早测试”不是一句口号。需求评审、设计评审、代码审查、单元测试、集成测试都属于早发现、早定位、早修复的手段。
测试的基本原则
尽早并持续进行测试
测试计划和测试用例可以在需求、概要设计、详细设计阶段开始准备。这样做能反向检查需求是否可验证、设计接口是否清楚。
避免开发者只测试自己的程序
编写代码的人容易按照自己的理解设计测试,忽略自己没有想到的场景。这就是“自证正确”的偏见。实际项目里,程序员通常要做单元测试,但集成、系统、验收测试应尽量由更独立的人员或团队参与。
同时测试有效数据和无效数据
有效数据验证系统能正常完成业务,无效数据验证系统能否拒绝错误输入、给出合理提示并保持状态安全。只测有效数据,很多输入校验和异常处理问题会被漏掉。
| 输入类型 | 作用 | 例子 |
|---|---|---|
| 有效数据 | 验证正常业务路径 | 年龄 35,学历本科,专业计算机 |
| 无效数据 | 验证边界、校验、异常处理 | 年龄 18、学历高中、专业不在列表中 |
无效用例还有一个细节:通常一条无效用例只故意放一个错误点,便于定位。如果同时把年龄、学历、专业都设错,即使系统报错,也不容易判断它到底检查到了哪个规则。
修改后必须做回归测试
修复一个缺陷可能引入新的缺陷,也可能破坏原有功能。因此修改后不仅要验证原缺陷是否消失,还要回归检查受影响的相关功能。
已发现错误多的模块更值得继续测
课程里提到“未发现错误数量与已发现错误数量成正比”的思想,本质上是缺陷聚集:一个模块已经暴露很多问题,说明它的设计、编码或理解风险较高,剩余缺陷也更可能多。项目上应把测试资源向这类模块倾斜。
考试高频判断
| 题干说法 | 判断 |
|---|---|
| 测试的目的是为了证明软件完全正确 | 错 |
| 测试应尽早开始,并贯穿开发过程 | 对 |
| 测试用例只需要输入数据即可 | 错 |
| 程序修改后应进行回归测试 | 对 |
| 已经发现很多错误的模块可能还隐藏更多错误 | 对 |
| 穷尽测试一般不现实 | 对 |
例题
本节小结
软件测试是一种以缺陷发现为中心的质量控制活动。它要尽早开始、持续进行,要有明确预期结果,要覆盖有效和无效数据;修复后要回归,缺陷多的模块要重点关注。最重要的考试结论是:测试不能证明软件无错,只能证明缺陷存在或增强信心。