软件测试的主要概念体系
在深入原则之前,我们必须建立对几个主要概念的深入理解。
1. 软件测试的经典定义
标准定义:使用人工或自动化的手段来运行或测定某个软件系统的过程,目的在于检验它是否满足规定的需求或弄清预期结果和实际结果之间的差别。
主要内涵:测试不仅仅是为了发现缺陷,更是为了提供关于软件质量的信息,以便于利益相关者做出决策。它是一种“质量检测”活动,而非“质量保证”活动(质量保证是预防,测试是检测)。
2. 错误、缺陷和故障
这是一个因果链,精确区分对缺陷管理和根因分析非常重要:
错误:人为行为。指在软件生命周期内,人员(开发、产品经理等)在思考、设计、编码过程中产生的错误判断或行为。例如,程序员误解需求,写错了计算公式。
缺陷:软件静态表现。错误被引入到软件代码、设计或文档中,形成了一个静态的、存在于产品内部的“瑕疵”。缺陷是错误的产物,是故障的潜在原因。
故障:软件动态表现。在特定条件下,缺陷被激活,导致软件在运行期间出现可观测的、偏离预期结果的行为。俗称“Bug”。
失效:用户视角的影响。当故障影响了软件对外提供的服务,导致无法完成预期功能时,用户或外部系统感知到的就是一次失效。
关系链:错误 → 缺陷 → 故障 → 失效
3. 验证和确认
这两个概念常常被混淆,但它们的目标截然不同:
验证:“我们是否在正确地构建产品?” 确保软件正确地实现了所规定的功能和技术要求。它关注的是过程的正确性,通常通过代码审查、单元测试、集成测试等实现。例如,“这个登录功能是否按照设计文档实现了?”
确认:“我们是否构建了正确的产品?” 从用户需求和业务目标的角度,评估最后的软件产品是否满足了预期的使用目的。它关注的是结果的正确性,通常通过验收测试、用户验收测试等实现。例如,“这个登录功能是否方便、安全,满足了用户的真实登录需求?”
简单概括:验证关乎“做对事情”,确认关乎“做对的事情”。
4. 测试用例
测试用例是测试执行的最小实体,是测试设计的产出物。一个专业的测试用例应包含:
用例标识符:唯一ID。
测试目标:要验证的功能点。
前置条件:执行测试前系统必须达到的状态。
输入数据/测试步骤:具体的操作或数据。
预期结果:在给定前置条件和输入下,系统应有的正确行为和输出。
后置条件:测试执行后系统的状态。
实际结果:执行后实际观察到的结果(执行时填写)。
软件测试的七大基本原则
这些原则指导着我们所有的测试活动。
原则一:测试显示缺陷的存在
主要阐述:测试可以证明软件中存在缺陷,但不能证明软件中没有缺陷。
实践意义:
管理测试期望:测试的价值在于发现并帮助修复缺陷,从而提升质量,而非保证完美。
决定测试停止标准:测试应在风险评估、时间、预算等因素下停止,而非追求“测完”。
原则二:穷尽测试是不可能的
主要阐述:除非是极简单的程序,否则测试所有可能的输入、预置条件和输出组合是不可行的。
专业解读:考虑一个带有两个整数输入框的程序,每个整数是32位。可能的输入组合有 2^64 种,这已经是一个天文数字。再加上不同的执行路径、系统状态和环境变量,穷举测试在计算上是不可行的。
实践意义:
测试分析和设计技术 变得非常重要。我们必须运用等价类划分、边界值分析、判定表、状态转换等技术,
原则三:早期测试
主要阐述:测试活动应在软件开发生命周期中尽可能早地开始,并聚焦于已定义的目标。
专业解读:缺陷的修复成本随着被发现的时间推移而呈指数级增长。在需求阶段发现的一个歧义,修复成本可能只是一次会议的沟通;而同样的问题在产品上线后被用户发现,修复成本可能涉及召回、赔偿和品牌声誉损失。
实践意义:
推行 测试左移:测试人员早期介入,参和需求评审、设计评审、代码评审。
在编码开始前,就应完成测试计划和测试用例的设计初稿。
原则四:缺陷集群性
主要阐述:通常,大部分缺陷会集中在少数几个模块中。
专业解读:也称为“帕累托法则”在测试中的体现(80%的缺陷发现于20%的模块)。这些模块通常是:
复杂度最高的模块。
经常改动的模块。
由经验不足的开发人员编写的模块。
新旧系统集成的接口部分。
实践意义:
基于风险的测试策略:将有限的测试资源重点投入到高风险、高复杂度的模块。
缺陷分析:通过对历史缺陷数据的分析,可以预测未来的缺陷高发区,指导测试重点。
原则五:杀虫剂悖论
主要阐述:重复使用相同的测试用例集,这些测试将不再能发现新的缺陷。
专业解读:就像害虫会对一直使用的杀虫剂产生抗药性一样,软件也会对固定的测试用例“免疫”。已经被测出的缺陷被修复了,未被覆盖的代码路径或新引入的缺陷,旧的测试用例无法触及。
实践意义:
测试用例需要定期评审和更新,以覆盖新的功能和代码变更。
引入探索性测试,利用测试人员的知识、经验和创造力,在测试执行过程中设计和执行新的、未经计划的测试,以发现那些在脚本化测试中无法发现的、意想不到的缺陷。
定期进行回归测试包的优化,增加新用例,淘汰过时或低效的用例。
原则六:测试活动依赖于测试背景
主要阐述:测试在不同的环境和项目中是不同的。没有“放之四海而皆准”的测试方法。
专业解读:测试的深度、广度、方法和工具,完全取决于项目的具体背景。
安全至上的系统(如航空软件):需要极严格和详尽的测试。
电商网站:更关注性能、负载和用户体验测试。
移动App:需要重点关注兼容性、中断测试和网络适应性。
实践意义:
测试策略必须量身定制。在项目启动初期,就必须分析业务领域、技术架构、风险、时间表等因素,来制定最合适的测试策略。
原则七:不存在缺陷的谬论
主要阐述:发现并修复大量缺陷,并不意味着软件就可以交付了。如果软件无法满足用户的需求和期望,那么修复所有已知缺陷也是徒劳。
专业解读:这条原则是原则一的补充,并再次强调了确认的重要性。一个在技术上完美无缺的系统,如果解决的是错误的问题,或者用户体验极差,那么它依然是失败的。
实践意义:
测试必须始终以用户价值和业务目标为准绳。
不仅要验证“软件是否做得对”,更要持续确认“软件做的是否是用户想要的”。这需要通过原型评审、可用性测试、早期用户参和等方式来实现。
关联关系
这七大原则相互关联,共同构成了一个坚实的测试哲学基础。
因为穷尽测试是不可能的(原则二),所以我们采用风险驱动(原则四) 和背景驱动(原则六) 的策略。
为了更早、更低成本地发现缺陷,我们推行早期测试(原则三)。
但我们明白,无论如何测试,都无法证明无缺陷(原则一和七),并且测试方法需要不断创新以避免杀虫剂悖论(原则五)。