Day26-01|5.4.1 测试方法
Day26-01|5.4.1 测试方法:用证据评价软件是否满足预期
本文对应《系统架构设计师教程(第2版)》第5章“软件工程基础知识”5.4.1“测试方法”。软件测试是通过执行程序、检查产物或分析运行行为,发现缺陷、验证需求和评价质量的活动。测试不能证明软件绝对没有缺陷,但可以在明确范围、风险和置信度的前提下提供证据。系统架构师需要把功能、性能、安全、可靠性、可维护性和部署等架构质量纳入测试设计,而不是把测试理解为开发结束后的找错环节。
一、学习目标与考试定位
完成本节后,应能够解释测试的目的、原则和基本分类;区分静态测试与动态测试、黑盒测试与白盒测试、功能测试与非功能测试、手工测试与自动化测试;掌握等价类、边界值、判定表、因果图、状态迁移、场景法和路径覆盖等测试设计方法;能够理解测试覆盖率的意义和局限;能够在案例题中设计测试策略并分析漏测原因;能够在论文中说明测试如何验证架构质量属性。
软考高级案例往往给出“测试通过但上线仍故障”“测试用例很多但核心风险未覆盖”“自动化测试比例很高但质量不升”等情景。答题时要先识别被测对象和质量目标,再选择方法和层次,明确数据、环境、预期结果、退出准则和缺陷闭环。不要把“测试越多越好”作为唯一判断。
二、测试的目的和原则
测试的主要目的包括发现缺陷、验证需求、确认系统可用性、评估风险和为发布决策提供证据。验证关注“系统是否按照设计正确实现”,确认关注“系统是否满足用户和业务需要”。测试还可以暴露需求不清、架构不合理、环境不一致、数据质量差和运维准备不足等问题。
测试有几个重要原则。测试应尽早开始,需求和架构阶段就要设计可验证条件;穷尽测试通常不可行,应基于风险和代表性选择样本;缺陷具有集群性,少数模块可能集中大部分问题;杀虫剂悖论说明重复相同用例会降低新缺陷发现能力,需要持续更新测试;没有缺陷不代表系统有用,必须验证真实需求;测试活动应独立于开发,但测试人员要与开发、业务和架构协作。
测试闭环可以概括为:
目标与风险 → 测试条件 → 用例与数据 → 执行与观察 → 缺陷分析 → 修复回归 → 质量评价
三、静态测试与动态测试
静态测试不运行程序,通过评审、走查、检查、静态分析和模型验证发现问题。需求评审可以发现歧义和冲突,架构评审可以发现边界、依赖和质量风险,代码静态分析可以发现复杂度、重复、潜在空指针和安全编码问题。静态测试发现问题较早,修复成本通常较低。
动态测试需要执行软件,依据输入、环境和预期结果观察实际行为。单元测试、集成测试、系统测试、性能测试和验收测试都属于动态测试。动态测试需要准备可重复的环境、数据和执行条件,结果应记录版本、配置、输入、输出、日志和判定。
四、黑盒、白盒和灰盒测试
黑盒测试不依赖被测程序内部结构,依据需求、接口和外部行为设计输入和预期输出。它适合验证功能、业务流程、接口契约和用户场景,能够发现实现与需求不一致,但对内部路径覆盖有限。
白盒测试了解程序内部结构、控制流、数据流和代码路径,依据代码设计语句、分支、条件、路径和数据流覆盖。它有助于发现逻辑错误和未执行代码,但即使代码覆盖率较高,也可能没有覆盖错误需求、异常场景或真实业务组合。
灰盒测试掌握部分内部信息,例如架构、数据模型、接口和部署拓扑,在黑盒行为验证基础上针对关键路径设计测试。系统级和架构级测试常采用灰盒思路,因为测试人员需要了解缓存、消息、数据库、权限和故障转移才能构造有效场景。
| 方法 | 依据 | 适合发现的问题 | 局限 |
|---|---|---|---|
| 黑盒 | 需求和外部行为 | 功能、流程、接口不一致 | 内部路径覆盖有限 |
| 白盒 | 代码和控制结构 | 逻辑、分支和路径缺陷 | 可能忽略需求和环境 |
| 灰盒 | 部分架构和数据知识 | 跨层、集成和关键路径问题 | 需要更多系统信息 |
五、功能与非功能测试
功能测试检查系统是否正确完成业务功能,包括输入、处理、输出、规则、权限、异常和边界。非功能测试评价系统的质量属性,包括性能、可靠性、可用性、安全性、兼容性、易用性、可维护性和可移植性。
架构师要把非功能目标写成可测试场景。例如性能测试需要并发模型、数据规模、请求分布、响应时间和吞吐目标;可用性测试需要故障类型、切换时间、数据丢失范围和恢复成功标准;安全测试需要角色、攻击面、权限、审计和漏洞处理;可维护性测试可以观察部署耗时、故障定位时间和配置变更影响。没有场景和指标,“系统性能好”“系统安全”无法验收。
六、测试设计方法
1. 等价类划分
把输入划分为若干等价类别,认为同一类别中的输入具有相似处理方式,从每类选择代表值。等价类可以是有效类和无效类,用于减少用例数量。划分不能只按数据类型,还要考虑业务规则、权限、状态和组合条件。
2. 边界值分析
缺陷常出现在输入范围边界、空值、最大值、最小值和临界状态。测试应覆盖边界内、边界上和边界外的值。例如页码、金额、日期、文件大小、连接数和超时时间都应验证边界。边界值要结合业务语义,不能只测试程序允许的类型范围。
3. 判定表和因果图
对于多个条件组合影响一个结果的规则,判定表列出条件、条件取值、动作和规则组合,能够发现遗漏和冲突。因果图先表示输入原因与输出结果之间的逻辑关系,再转换为判定表。适合费率、优惠、审批、权限和风控等规则复杂场景。
4. 状态迁移测试
针对对象状态、事件、条件和迁移设计用例,覆盖有效迁移、非法迁移、重复事件、超时和异常恢复。订单、支付、审批、工单和设备控制都适合状态测试。分布式环境还要测试消息重复、乱序、延迟和节点恢复。
5. 场景法
以用户或系统的完整业务场景设计端到端用例,包括主成功场景、替代流程和异常流程。场景法能够连接多个模块和外部系统,适合验收和系统测试,但执行成本较高,需要控制数据和环境。
6. 路径与覆盖测试
白盒测试可以根据控制流设计语句、分支、条件和路径覆盖。覆盖率用于发现未执行区域和衡量测试充分性,但不是质量分数。高覆盖率代码如果断言薄弱、数据单一或需求错误,仍可能漏掉严重问题。应结合风险、缺陷历史、业务场景和变异测试等方法评价有效性。
七、测试层次与测试金字塔
单元测试验证最小代码单元,执行快、定位准,适合大量自动化;集成测试验证模块、服务、数据库和消息系统之间的协作;系统测试验证完整系统和质量属性;验收测试由用户或业务代表确认系统满足目标。不同层次不能完全互相替代。
测试金字塔通常建议底层快速测试数量较多,中层集成测试适量,顶层端到端测试数量较少但覆盖关键用户旅程。若全部依赖端到端测试,执行慢、环境脆弱、失败定位困难;若只有单元测试,又可能漏掉接口、配置、数据和部署问题。架构师应根据系统边界和风险调整层次。
八、自动化测试和持续验证
适合自动化的测试具有重复执行、结果明确、频率高、人工成本大和环境可控等特点。自动化可以覆盖构建、单元、接口、回归、静态分析、依赖检查、性能基线和部署验证。但自动化脚本也需要维护,脆弱脚本、固定数据、环境依赖和无效断言会制造虚假信心。
持续集成中应在代码合并时执行快速检查,持续交付中执行更完整的验证,发布后通过冒烟、灰度、合成监控和真实指标持续观察。测试失败要有明确处理:阻断、隔离、重试或人工确认,不能通过无限重试掩盖不稳定。
九、测试环境、数据与可重复性
测试结果依赖环境、配置和数据。环境应尽量接近生产,记录操作系统、依赖版本、网络、资源、开关和拓扑;测试数据要覆盖正常、边界、异常、权限、隔离和历史状态,并保护真实敏感数据;时间、随机数、外部接口和消息顺序要能够控制或模拟。
可重复性要求同一版本、同一条件下能够重新执行并获得可解释结果。每个缺陷报告应包括版本、环境、前置条件、步骤、输入、实际结果、预期结果、日志、截图和严重程度。对偶发故障还要采集链路追踪、指标、线程、数据库和消息证据。
十、案例分析:测试通过却发生订单重复扣款
某电商系统上线前功能测试和自动化测试均通过,上线后网络抖动时出现少量重复扣款。分析发现,客户端超时会自动重试,支付服务没有幂等键;测试只覆盖单次成功请求,没有覆盖回调延迟、请求重复、消息重复和服务重启。
改进首先是明确业务风险和状态机,定义订单、支付和退款的状态转换;在接口层引入业务幂等键和请求唯一号,将关键字段纳入签名或认证;服务端用唯一约束和状态检查保证重复请求不重复执行;对第三方回调采用可重复接收、去重和对账;测试覆盖客户端重试、响应丢失、回调重复、消息乱序、数据库提交成功但响应丢失和节点重启等故障场景;通过故障注入和端到端对账验证结果。
这个案例说明功能测试通过只证明部分正常行为,不能证明分布式异常和质量属性。测试设计必须从架构风险和业务后果出发。
十一、常见误区
第一,测试就是找程序员的错。测试应评价产品、需求、架构、过程和风险,缺陷责任应以事实为依据。第二,覆盖率越高质量越好。覆盖率只说明执行范围,不说明断言有效和需求正确。第三,自动化越多越好。自动化应服务于稳定、可重复和高价值验证。第四,只测正常流程。边界、异常、权限、并发、故障和恢复往往更容易暴露架构问题。第五,测试通过就可以发布。发布还要考虑未关闭风险、监控、回滚、数据迁移和运行准备。
十二、课后练习
练习一:单项选择
下列最适合使用判定表设计测试的是( )。
A. 只有一个输入的最大值;B. 多个业务条件组合决定审批结果;C. 检查一段代码是否被执行;D. 验证页面颜色。
答案:B。判定表适合多个条件组合决定动作或结果的业务规则。
练习二:简答题
请说明代码覆盖率高为什么仍可能存在严重缺陷。
参考答案:覆盖率只表示某些语句、分支或路径被执行,不代表需求理解正确、断言能够发现错误、输入数据充分、异常和权限场景被覆盖,也不代表生产环境配置和外部依赖一致。应结合需求覆盖、风险场景、边界和异常测试、接口与系统测试、缺陷历史和运行验证综合评价。
练习三:案例分析
某系统自动化回归测试有 2000 个用例,但执行时间很长、失败后经常无人处理,线上仍频繁出现接口兼容问题。请分析并提出改进方案。
参考答案:用例数量多不等于有效,可能存在重复、脆弱脚本、固定数据、断言不足和分层不合理;接口兼容问题说明单元测试无法替代契约、集成和端到端验证;失败无人处理说明没有责任、分类和质量门禁。应按风险和测试层次重构,增加快速单元和接口测试,建立消费者驱动契约和版本兼容检查,保留关键端到端场景;治理测试数据和环境,区分产品缺陷、环境故障、脚本故障和偶发问题;设置失败责任人、阻断规则、趋势分析和定期清理;在发布前后验证接口、配置和真实流量指标。
十三、论文素材
论文可写:在项目中我以需求和架构风险为基础制定测试策略。对核心业务采用场景、状态、边界和判定表方法,对代码使用静态检查和单元测试,对服务协作使用接口、契约和集成测试,对系统质量采用性能、安全、可靠性、故障恢复和灾备演练;通过持续集成、自动化回归和灰度验证缩短反馈周期。测试环境、数据、配置和版本均纳入管理,缺陷按严重度和业务影响闭环处理,并以缺陷逃逸率、关键场景成功率、P99 延迟和恢复时间评估测试有效性。
十四、今日复盘
测试是基于证据的验证和风险评价活动。静态测试尽早发现需求、设计和代码问题,动态测试观察实际行为;黑盒关注外部需求,白盒关注内部结构,灰盒适合跨层关键场景。等价类、边界值、判定表、状态迁移、场景和覆盖方法各有适用范围,功能测试不能替代性能、安全、可靠性和恢复测试。下一篇进入 5.4.2 测试阶段。