跳转到内容

软件测试

本页使用了标题或全文手工转换
维基百科,自由的百科全书

软件测试(英語:software testing)是通过静态审查或运行程序的方式,评价软件是否满足规定需求、并识别其中缺陷的活动[1]。国际标准 ISO/IEC/IEEE 29119-1 将测试定义为对软件产品的一组活动,用以评估其质量并降低软件失效的风险[1]。中文文献中常见的经典定义为:在规定的条件下对程序进行操作,以发现程序错误、衡量软件质量,并对其是否满足设计要求进行评估的过程[2]。

测试是验证与确认(V&V)的手段之一,但并不等同于软件质量保证:质量保证着眼于改进产生软件的过程,测试则着眼于检查已经产生的工作产品[3]。测试也不能证明软件正确。艾兹赫尔·戴克斯特拉的著名论断指出,测试只能显示缺陷的存在,而无法显示缺陷不存在[4];要在数学意义上确立程序的正确性,需要形式化验证等其他手段。

由于输入空间、执行路径与运行环境的组合在实际系统中通常极为庞大,穷尽测试一般不可行。因此现代测试实践的核心问题不是"测完所有情况",而是在有限的时间与成本下,依据风险选择最有价值的测试,并向利益相关方提供关于软件质量的信息[3]。

目的与局限

[编辑]

测试的目标

[编辑]

测试通常同时服务于多个目标,包括:

  • 发现缺陷,使其在交付前被修复;
  • 评估工作产品是否满足需求、是否达到约定的质量水平;
  • 为发布、验收等决策提供信息,降低不确定性;
  • 通过回归测试,确认变更没有破坏既有功能;
  • 满足合同、法规或行业标准(如医疗、航空、金融领域)对测试证据的要求[1]。

值得注意的是,"发现缺陷"与"证明可用"这两个目标在测试设计上会导向不同的策略:前者鼓励设计容易使程序失效的用例,后者倾向于覆盖典型使用场景。梅耶斯主张应把测试视为"以发现错误为目的"的破坏性活动,因为以"证明程序能工作"为心理预设的测试往往不易发现问题[5]。

错误、缺陷与失效

[编辑]

标准术语区分三个相互关联的概念[1]:

  • 错误(error / mistake):人在编写需求、设计或代码时的失误;
  • 缺陷(defect / fault,俗称bug):错误在工作产品中留下的静态瑕疵;
  • 失效(failure):缺陷在运行时被触发,导致系统的实际行为偏离预期。

动态测试只能观察到失效,再由此回溯定位缺陷;缺陷存在并不必然导致失效——只有当代码被执行、状态被污染且污染传播到可观察的输出时,失效才会显现(即所谓 RIP 模型:可达性、感染、传播)[6]。这也是许多缺陷长期潜伏而未被发现的原因。

穷尽测试的不可行性

[编辑]

即使是很小的程序,其输入组合与执行路径数量也可能大到无法逐一验证。含有循环的程序在理论上具有无限多条执行路径,因此路径覆盖通常无法完全达成[6]。

从可计算性理论的角度看,一般性的自动判定同样受到根本限制:停机问题是不可判定的,即不存在能对任意程序与任意输入判断其是否会终止的通用算法;莱斯定理进一步表明,程序所计算函数的任何非平凡语义性质都是不可判定的[7]。这意味着不可能构造出一个通用工具,自动判定任意程序是否"正确"。测试因而只能是抽样式的:通过有限的观察来降低——而非消除——对质量的不确定性。

测试预言问题

[编辑]

执行测试需要判断实际结果是否可接受,这一判断依据称为测试预言(test oracle)。预言可以来自规格说明、参照实现、既往版本的行为、不变式或人工判断。在图形渲染、机器学习、科学计算等领域,预期结果往往难以精确给出,被称为"测试预言问题";蜕变测试(metamorphic testing)等方法通过检查输入与输出之间应当成立的关系来缓解这一困难[8]。

历史

[编辑]

早期的程序调试与测试并无明确分野,两者常被统称为"调试"。1957年前后,测试才逐渐被区分为独立于调试的活动:调试的目的是定位并修复已知问题,测试的目的是发现未知问题[9]。

格尔佩林与海策尔将测试实践的演进划分为若干时期:以调试为导向的时期、以证明满足需求为导向的"演示"时期、以发现缺陷为导向的"破坏"时期、强调风险与成本的"评估"时期,以及自1980年代起强调缺陷预防、把测试活动前移到需求与设计阶段的时期[9]。1979年梅耶斯出版的《软件测试的艺术》系统提出了以发现错误为目标的测试观[5]。此后,单元测试框架、持续集成与测试驱动开发的普及,使自动化测试成为日常开发流程的组成部分。

测试方法

[编辑]

静态测试与动态测试

[编辑]

静态测试不运行被测程序,通过评审、走查、检视与静态程序分析工具检查需求、设计、代码等工作产品。静态手段可以在早期发现缺陷,且能覆盖难以运行到的代码,但无法发现与运行时环境、并发或性能有关的问题。

动态测试则实际运行程序并观察其行为,是通常意义上"测试"一词所指的活动。两者互补:静态测试直接发现缺陷,动态测试通过失效间接发现缺陷。

黑盒测试

[编辑]

黑盒测试(black-box testing,又称黑箱测试、基于规格的测试)不考察内部结构,仅依据需求、规格或接口约定设计用例,检查给定输入下的输出是否符合预期。测试者无需了解实现细节,因此用例可在实现完成前设计,也不易随重构而失效。其局限在于难以保证内部逻辑分支被充分覆盖,也可能遗漏规格本身未提及的行为。

白盒测试

[编辑]

白盒测试(white-box testing,又称透明盒测试、玻璃盒测试或结构测试)依据程序的内部结构设计用例,关注语句、分支、条件与路径的执行情况,常与代码覆盖率度量配合使用。白盒方法能发现被规格忽略的实现问题,但无法发现"需求本身被遗漏"一类的缺陷——未写出的代码不会出现在任何覆盖率报告中。

灰盒测试

[编辑]

灰盒测试介于两者之间:测试者了解部分内部信息(如数据库结构、模块划分、内部接口),据此设计更有针对性的用例,但主要仍从外部接口进行验证。集成测试与许多接口测试在实践中属于此类。

脚本化测试与探索式测试

[编辑]

脚本化测试先设计并记录用例,再按用例执行,便于复用、审计与自动化。探索式测试则将测试设计、执行与学习作为同时进行的活动,由测试者根据上一步的观察决定下一步的操作,常用于快速评估新功能或补充脚本化测试的盲区[3]。二者并非对立,成熟团队通常按风险与目的混合使用。

测试层级

[编辑]

按被测对象的粒度与所处阶段,测试通常分为以下层级。

单元测试

[编辑]

单元测试针对软件的最小可测试单元(如函数、方法或类)进行验证,通常由开发人员编写,并借助xUnit 类框架自动执行。单元测试运行快、定位准,是回归防护网的基础;对外部依赖一般使用测试替身(桩、模拟对象等)加以隔离。为使单元便于测试,代码需具备良好的可测试性,这也促使开发者改善模块划分与依赖管理。

集成测试

[编辑]

集成测试(又称整合测试、组装测试)在单元测试通过后,将模块按一定策略组装,检验模块之间的接口、数据传递与协作是否正确。常见策略包括自顶向下、自底向上、三明治式与大爆炸式集成;针对分布式系统与微服务,还发展出契约测试等做法。

系统测试

[编辑]

系统测试以完整、集成后的系统为对象,在尽可能接近真实的环境中,依据需求规格验证端到端的行为,涵盖功能与各类非功能特性。

验收测试

[编辑]

验收测试从用户或采购方的角度确认系统是否可以接受,通常由用户方主导或参与,包括用户验收测试(UAT)、运维验收测试、合约与法规验收测试等。第三方开展的 Alpha、Beta 测试亦常被归入这一层级。

测试类型

[编辑]

功能测试

[编辑]

功能测试检查系统"做什么",即是否实现了规定的功能与业务规则。设计时通常按功能点与功能组合划分,力求覆盖全部功能项及主要的条件组合,并包含正常流程、备选流程与异常流程。

非功能测试

[编辑]

非功能测试检查系统"做得怎么样",对应 ISO/IEC 25010 所定义的各项产品质量特性[10]。

类型 关注点
性能测试 在给定负载下的响应时间、吞吐量与资源占用是否满足要求。
负载测试 在预期的并发用户数或事务量下,系统能否维持既定的性能指标。
压力测试 施加超出设计容量的负载,观察系统的降级方式、是否出现数据损坏,以及负载回落后能否恢复。
容量与可扩展性测试 确定系统的容量上限,以及通过增加资源提升处理能力的效果。
安全测试 认证与授权、输入校验、数据保护、加密与审计等方面的缺陷,常配合渗透测试与模糊测试。
易用性测试 用户完成任务的效率、出错率与主观满意度,通常需要真实用户参与。
兼容性测试 在不同操作系统、浏览器、设备、分辨率与依赖版本下的表现。
可靠性测试 长时间运行下的稳定性、故障率与故障恢复能力,包括耐久性(浸泡)测试。
可维护性与可移植性测试 代码的可修改性、可分析性,以及安装、迁移与卸载过程是否可靠。

性能测试与压力测试的区别

[编辑]

两者常被混淆。性能测试在符合规定条件的负载下度量系统表现,关注指标是否达标;压力测试则刻意超出设计指标,关注系统在极限与超限条件下的行为。例如某网站设计容量为100个并发用户,以100个并发用户度量响应时间属于性能测试,以远超100的并发量施压、观察系统是否崩溃与能否恢复则属于压力测试。压力测试通常以两点作为判断依据:负载回落后系统能够自行恢复;加压过程中不出现数据丢失或不可接受的性能塌陷。

与变更有关的测试

[编辑]
  • 确认测试(再测试):针对已修复的缺陷,验证修复确实生效。
  • 回归测试:在修改代码后重新执行既有用例,确认变更没有破坏原有功能,也用于检验新功能是否对既有功能产生副作用。回归测试贯穿维护阶段,其累积成本在软件生命周期中占比可观,因而如何从既有用例集中选择、排序与精简用例,长期是该领域的研究重点[11]。
  • 冒烟测试:在构建产出后快速执行的一小组关键用例,用于判断该版本是否值得投入进一步测试。

测试设计技术

[编辑]

ISO/IEC/IEEE 29119-4 将测试设计技术分为基于规格、基于结构与基于经验三类[12]。

基于规格的技术

[编辑]
  • 等价类划分:将输入域划分为若干等价类,假定同一类内的取值会触发相同的处理逻辑,从每类中取代表值以减少用例数量。
  • 边界值分析:针对等价类的边界及其邻近取值设计用例。缺陷在边界处出现的概率显著高于区间内部,是性价比最高的技术之一。原条目所称的"极限值测试"大致对应此类做法与容量类非功能测试的组合,并非标准术语。
  • 判定表测试:将多个条件的组合及其对应动作列表化,系统地覆盖业务规则组合。
  • 状态转换测试:为具有状态的系统建立状态机模型,覆盖状态、转换与非法转换。
  • 成对组合测试:当参数众多时,覆盖任意两个参数的所有取值组合。经验研究显示,相当比例的缺陷由单个或两个参数的交互触发,因此低阶组合覆盖能以较少用例发现大部分交互缺陷[13]。

基于结构的技术与代码覆盖率

[编辑]

代码覆盖率度量测试执行触及了多少程序结构,用于发现测试的盲区。常用准则的强度依次递增[14]:

  • 语句覆盖(行覆盖):每条可执行语句至少被执行一次;
  • 判定覆盖(分支覆盖):每个判定的真、假分支各被取到一次;
  • 条件覆盖与修正条件/判定覆盖(MC/DC):要求复合判定中的每个原子条件都能独立影响判定结果,被 DO-178C 等航空软件标准用于最高安全等级;
  • 路径覆盖:覆盖控制流中的所有可行路径,在含循环的程序中通常无法完全达成。

覆盖率的采集需要插桩或特殊编译,会带来运行时开销,因此多用于测试环境而非生产环境。更重要的是,覆盖率是必要而非充分的指标:高覆盖率只说明代码被执行过,并不说明结果被有效断言,也无法反映规格中被遗漏的功能。将覆盖率作为硬性考核指标,容易诱导出只执行不校验的低效用例。此外,竞态条件等对时序敏感的缺陷,在插桩带来的时序扰动下往往更难复现。

基于经验的技术

[编辑]

包括错误推测、基于检查表的测试与探索式测试等,依赖测试者对同类系统常见失效模式的经验。这类技术难以系统化,但在补充覆盖盲区与快速定位高风险区域方面效果显著。

变异测试

[编辑]

变异测试通过向源代码中注入人工缺陷(变异体),检验现有测试集能否将其检出,从而评估测试集本身的有效性。它在一定程度上弥补了覆盖率无法度量断言强度的缺陷,代价是计算开销较大[15]。

测试过程与管理

[编辑]

测试过程

[编辑]

ISO/IEC/IEEE 29119-2 将动态测试过程描述为测试设计与实现、测试环境搭建与维护、测试执行、测试事件报告等一组活动,并置于测试规划、监控与控制、测试完成等管理过程之下[16]。这些过程可依项目规模与风险裁剪,并适用于瀑布与敏捷等不同生命周期模型。

测试用例、测试脚本与测试场景

[编辑]

测试用例由前置条件、输入、执行步骤与预期结果构成,是可执行、可复查的最小测试单位。测试脚本是用例的可自动执行形式;测试场景描述一条贯穿多个功能的端到端业务流程,常作为组织用例的上层结构。测试文档的模板可参考 ISO/IEC/IEEE 29119-3[17]。

缺陷管理

[编辑]

测试中发现的失效以缺陷报告的形式记录,内容通常包括复现步骤、实际结果、预期结果、环境信息、严重程度与优先级。缺陷在提交、确认、修复、验证与关闭之间流转,形成缺陷生命周期。缺陷数据同时也是评估产品质量与过程改进的重要输入。

进入与退出准则

[编辑]

进入准则规定开始某一测试活动所需具备的条件(如构建可用、冒烟测试通过);退出准则(完成准则)规定何时可以停止测试,常结合用例执行率、缺陷收敛趋势、覆盖率、遗留缺陷的风险评估与预算时间等多项因素判断。单一指标不宜作为停止测试的唯一依据。

发布阶段的测试

[编辑]

Alpha 与 Beta 指产品发布前的开发阶段,描述的是"何时、由谁测试",与黑盒、白盒等描述"如何测试"的技术维度属于不同分类,二者不应混为一谈。

Alpha测试

[编辑]

Alpha测试在开发方场地进行,由开发人员、内部测试人员或受邀用户以模拟或实际操作的方式执行,环境与数据通常仍是受控的。其目的是在向外部发布前确认系统基本满足需求与设计预期。

Beta测试

[编辑]

Beta测试在用户的真实环境中、由实际用户使用真实数据执行,开发方通常不在现场。它用于确认系统在多样化的真实条件下的可用性、性能、兼容性与恢复备份等运维特性,并收集实际使用中的问题反馈。

封闭测试与公开测试

[编辑]

封闭测试(Closed Beta,简称封测、CB)只向数量有限的受邀者开放,主要用于功能验证与缺陷检查;部分厂商会要求参与者签署保密协议,以防内容提前外流。MMORPG在封测结束后通常会删除角色数据,但亦有不删档的情形。

公开测试(Open Beta,简称公测、OB)在正式上市前向不特定用户开放试用。虽然原意是收集问题反馈,但参与者并非严格意义上的验证人员。公测通常免费,能吸引大量用户参与,因而兼具行销作用,同时可在真实规模下检验带宽与服务器的承载能力,节省专职测试的成本。

生产环境中的测试

[编辑]

在持续交付实践中,部分验证被移至生产环境进行,包括金丝雀发布(先向小比例流量投放新版本并监控指标)、A/B测试、功能开关控制的渐进放量,以及以混沌工程主动注入故障验证系统韧性。这类做法并不取代发布前测试,而是承认部分问题只有在真实流量与规模下才会暴露。

自动化测试

[编辑]

自动化测试使用工具与脚本自动执行测试并比对结果,适合需要频繁重复执行的场景,如回归测试、跨环境的兼容性测试与性能测试。其价值在于快速反馈与可重复性,而非"取代测试人员"——用例的设计、结果的解释与探索式测试仍依赖人的判断。

自动化本身也是需要维护的软件资产。若断言薄弱、与界面细节过度耦合或存在不稳定用例(flaky test),维护成本可能超过其收益。常见的组织原则是所谓测试金字塔:以大量快速的单元测试为基础,向上依次减少集成测试与端到端测试的数量。

测试与开发流程的结合

[编辑]
  • 测试驱动开发(TDD):先编写一个失败的测试,再编写使其通过的最小实现,随后重构,以测试驱动设计的演进[18]。
  • 行为驱动开发(BDD):以业务语言描述的示例作为需求与自动化测试的共同载体,促进开发、测试与业务人员的沟通。
  • 敏捷测试:测试贯穿整个迭代,由整个团队共同承担质量责任,而非在开发完成后由独立团队集中执行。
  • 测试左移与右移:左移指将测试活动前移至需求与设计阶段(评审、静态分析、可测试性设计),以降低缺陷的修复成本;右移指借助生产环境的监控、日志与可观测性手段持续获取质量信息。

常见误解

[编辑]
  • "Beta测试就是黑盒测试":Alpha、Beta 描述的是产品所处的发布阶段与测试的参与者,黑盒、白盒、灰盒描述的是设计用例时所依据的信息,二者是不同维度的分类。
  • "Gamma测试":该说法偶见于非正式文献,用以指代"带有已知缺陷仍予发布"的阶段,但缺乏标准定义,也未被 ISO/IEC/IEEE 29119 等标准或主流教材采用,通常不宜作为正式术语使用。
  • "测试通过即证明软件无缺陷":测试只能针对已执行的场景给出结论,通过并不等于不存在缺陷。
  • "测试是测试人员一个人的事":缺陷源自需求、设计与实现的各个环节,质量需由整个团队共同负责。
  • "覆盖率100%即测试充分":覆盖率不度量断言的强度,也无法覆盖未实现的需求。

相关标准

[编辑]
  • ISO/IEC/IEEE 29119 系列——软件测试的国际标准,现行版本为第1部分《一般概念》(2022)、第2部分《测试过程》(2021)、第3部分《测试文档》(2021)、第4部分《测试技术》(2021)与第5部分《关键字驱动测试》(2024,第2版)[1][16][17][12][19]。该系列取代了 IEEE 829、IEEE 1008 等早期标准。
  • ISO/IEC 25010——SQuaRE 系列中的产品质量模型。2011年版取代了 ISO/IEC 9126,将质量特性扩展为八项;2023年发布的第2版增设了"安全性"(safety)为独立特性,共九项,并将"易用性"改称"交互能力"、"可移植性"改称"灵活性",原有的使用质量模型则移至 ISO/IEC 25019:2023[10]。
  • GB/T 15532《计算机软件测试规范》——中国国家标准,规定了各测试阶段的过程与文档要求。
  • 特定领域标准如航空的 DO-178C、汽车的 ISO 26262、医疗器械的 IEC 62304,对测试的覆盖准则与证据留存有更严格的规定。

参见

[编辑]

参考文献

[编辑]
  1. ^ 1.0 1.1 1.2 1.3 1.4 ISO/IEC/IEEE 29119-1:2022 — Software and systems engineering — Software testing — Part 1: General concepts. ISO. 2022 [2026-09-09]. 
  2. ^ 郑人杰. 计算机软件测试技术. 清华大学出版社. 
  3. ^ 3.0 3.1 3.2 Cem Kaner; James Bach; Bret Pettichord. Lessons Learned in Software Testing: A Context-Driven Approach. Wiley. 2001. 
  4. ^ Edsger W. Dijkstra. Notes on Structured Programming (PDF). 1970 [2026-09-09]. EWD249. 
  5. ^ 5.0 5.1 Glenford J. Myers; Corey Sandler; Tom Badgett. The Art of Software Testing 3rd. Wiley. 2011. 
  6. ^ 6.0 6.1 Paul Ammann; Jeff Offutt. Introduction to Software Testing 2nd. Cambridge University Press. 2016. 
  7. ^ H. G. Rice. Classes of Recursively Enumerable Sets and Their Decision Problems. Transactions of the American Mathematical Society. 1953, 74 (2): 358–366. 
  8. ^ Earl T. Barr; Mark Harman; Phil McMinn; Muzammil Shahbaz; Shin Yoo. The Oracle Problem in Software Testing: A Survey. IEEE Transactions on Software Engineering. 2015, 41 (5): 507–525. 
  9. ^ 9.0 9.1 David Gelperin; Bill Hetzel. The Growth of Software Testing. Communications of the ACM. 1988, 31 (6): 687–695. 
  10. ^ 10.0 10.1 ISO/IEC 25010:2023 — Systems and software engineering — SQuaRE — Product quality model. ISO. 2023-11-15 [2026-09-09]. 
  11. ^ Shin Yoo; Mark Harman. Regression Testing Minimization, Selection and Prioritization: A Survey. Software Testing, Verification and Reliability. 2012, 22 (2): 67–120. 
  12. ^ 12.0 12.1 ISO/IEC/IEEE 29119-4:2021 — Software and systems engineering — Software testing — Part 4: Test techniques. ISO. 2021 [2026-09-09]. 
  13. ^ D. Richard Kuhn; Dolores R. Wallace; Albert M. Gallo. Software Fault Interactions and Implications for Software Testing. IEEE Transactions on Software Engineering. 2004, 30 (6): 418–421. 
  14. ^ Hong Zhu; Patrick A. V. Hall; John H. R. May. Software Unit Test Coverage and Adequacy. ACM Computing Surveys. 1997, 29 (4): 366–427. 
  15. ^ Yue Jia; Mark Harman. An Analysis and Survey of the Development of Mutation Testing. IEEE Transactions on Software Engineering. 2011, 37 (5): 649–678. 
  16. ^ 16.0 16.1 ISO/IEC/IEEE 29119-2:2021 — Software and systems engineering — Software testing — Part 2: Test processes. ISO. 2021 [2026-09-09]. 
  17. ^ 17.0 17.1 ISO/IEC/IEEE 29119-3:2021 — Software and systems engineering — Software testing — Part 3: Test documentation. ISO. 2021 [2026-09-09]. 
  18. ^ Kent Beck. Test-Driven Development: By Example. Addison-Wesley. 2002. 
  19. ^ ISO/IEC/IEEE 29119-5:2024 — Software and systems engineering — Software testing — Part 5: Keyword-driven testing. ISO. 2024 [2026-09-09]. 

延伸阅读

[编辑]
  • 郑人杰. 计算机软件测试技术. 清华大学出版社. 
  • Boris Beizer. Software Testing Techniques 2nd. Van Nostrand Reinhold. 1990. 
  • Dorothy Graham; Rex Black; Erik van Veenendaal. Foundations of Software Testing: ISTQB Certification 4th. Cengage. 2019. 
  • Edsger W. Dijkstra. Notes on Structured Programming (PDF). 1970. EWD249. 

外部链接

[编辑]