ARCHIVE / INITIALIZING000%
正在载入档案界面SYS.07
Interview Prep

测试基础

从测试对象、Oracle、测试分类与反馈层次,到覆盖率、Mutation、风险驱动和 Agent 系统的双重不确定性。

测试基础

软件测试无法证明“系统绝对没有Bug”,只能在一组输入、环境和Oracle下寻找反例,并给发布决策提供证据。真正的问题不是“测没测”,而是:测了哪个性质,覆盖了什么风险,失败时能否定位,成本是否允许持续运行。

1. 测试的五个元素

一条测试至少有:

SUT:System Under Test,被测对象
Input:输入与前置状态
Action:执行动作
Oracle:判断对错的规则
Isolation:与外部环境隔离到什么程度

没有Oracle的脚本只能完成自动操作,无法判断系统行为是否正确。仅产生大量日志而不执行判定,不构成完整测试。

Oracle类型

  • Exact Oracle:输出必须等于精确值;
  • Schema Oracle:结构、类型、必填字段合法;
  • Invariant Oracle:余额不为负、状态不能逆转、权限不能扩大;
  • Differential Oracle:新旧实现或两个实现结果一致;
  • Metamorphic Oracle:输入按某种变换后,输出满足已知关系;
  • Statistical Oracle:成功率、分布或评分达到阈值;
  • Human / Rubric Oracle:人工或模型依据评分量表判断。

传统业务逻辑优先使用Exact与Invariant;Agent最终答案常需Rubric和统计指标,但工具参数、状态机和权限仍然可以精确断言。

2. 测试分类维度

维度分类它在问什么
是否看内部实现黑盒、白盒、灰盒测试是否利用内部结构
测试范围Unit、Component、Integration、E2E一次跨过多少组件
测试目标Functional、Performance、Security、Usability验证哪类质量属性
执行方式Manual、Automated、Exploratory怎样获得证据
生命周期Smoke、Regression、Acceptance在交付流程中承担什么角色

例如,“通过HTTP调用真实PostgreSQL的API测试”既可以归类为黑盒或灰盒测试,也可以归类为集成测试、功能测试和自动化回归测试。讨论测试分类时,应先明确采用的分类维度和定义。

3. 测试层次是一组反馈回路

软件测试的多层反馈回路

层次速度隔离主要发现
Static极快最高类型、格式、已知危险模式
Unit快高局部逻辑、边界条件、状态转换
Integration / Contract中中SQL、序列化、协议、依赖兼容
E2E慢低关键用户旅程与系统装配
Production Verification持续最低真实流量、长尾环境、容量与漂移

Test Pyramid强调反馈成本:低层测试通常更快、更稳定且更容易定位,因此数量更多;高层测试覆盖真实装配,但成本更高,所以集中保护关键路径。它不要求固定比例,也不意味着应当减少有价值的集成测试。

4. 测试用例设计

等价类与边界值

把输入划为行为相同的集合,每类选代表值;边界两侧单独测试。例如分页参数:

非法:page_size < 1
边界:1
常规:20
上边界:100
非法:101

Decision Table

适合多个条件组合:

登录有权限需要审批结果
否任意任意401
是否任意403
是是是PENDING_APPROVAL
是是否EXECUTE

Agent Tool Policy尤其适合Decision Table,条件散落在Prompt里则很难穷举。

状态转换

先列合法状态图,再测合法与非法边:

PENDING → RUNNING → SUCCEEDED
                  ↘ FAILED
PENDING / RUNNING → CANCELLING → CANCELLED

断言不只看终态,还要验证SUCCEEDED → RUNNING这类逆转被拒绝、重复事件幂等、并发更新有版本约束。

Pairwise与组合爆炸

浏览器、数据库、模型、语言和权限的完整笛卡尔积会产生大量组合。Pairwise使用较少Case覆盖任意两个参数值的组合,以发现常见交互缺陷;高风险组合仍需显式加入,不能仅依赖Pairwise覆盖。

5. 覆盖率的含义与边界

常见覆盖率:Statement、Branch、Condition、Function和Path Coverage。Branch Coverage公式:

BranchCoverage⁡=#Executed branches#Total branches\operatorname{BranchCoverage} =\frac{\#\text{Executed branches}}{\#\text{Total branches}}

假设代码有10个分支,测试走过8个,Branch Coverage是80%。它证明两条分支被执行过,不证明断言正确,也不证明输入边界充分。

100% Statement Coverage可能完全没有验证结果:

func TestTransfer(t *testing.T) {
    _ = Transfer(accountA, accountB, 100) // 跑到了,没断言
}

覆盖率适合发现明显未测试的区域和设置增量门禁,不适合直接作为质量KPI。如果按覆盖率数值考核,团队可能倾向于提高数值而忽视断言质量和风险覆盖。

6. Mutation Testing比覆盖率更接近断言强度

Mutation Tool会对代码做小改动:>变成>=、删除条件、把返回值改成0,再运行测试。测试若没有失败,Mutant存活,说明测试可能没有抓住行为变化。

MutationScore⁡=MkilledMtotal−Mequivalent\operatorname{MutationScore} =\frac{M_{\text{killed}}}{M_{\text{total}}-M_{\text{equivalent}}}

例如生成100个Mutant,10个与原程序等价,测试杀死72个:

MutationScore⁡=72100−10=0.8\operatorname{MutationScore}=\frac{72}{100-10}=0.8

Mutation Testing成本较高,适合核心状态机、计费、权限等高风险模块,不必每天对整个仓库执行。

7. 风险驱动测试

可用一个简单优先级模型:

R=Pfailure×Iimpact×EexposureR=P_{\text{failure}}\times I_{\text{impact}}\times E_{\text{exposure}}
  • PfailureP_{\text{failure}}:出错概率;
  • IimpactI_{\text{impact}}:损失程度;
  • EexposureE_{\text{exposure}}:被多少请求或用户触发。

高风险区域包括资金、副作用、租户隔离、权限、数据迁移和不可逆操作。它们需要更强的Invariant、并发测试、故障注入与人工审查;低风险展示文本可以采用成本更低的验证策略。

8. Agent系统中的概率不确定性

Agent系统有两类变化:

软件不确定性:竞态、超时、依赖失败、Schema变化
模型不确定性:采样、Prompt敏感、语义等价输出、多条合法轨迹

测试策略因此分层:

  • 精确测:Parser、Tool Schema、Policy、状态机、预算、幂等、权限;
  • 受控测:Fake Model输出固定Action,验证Orchestrator;
  • 统计测:真实模型多次采样,计算Task Success、Tool Accuracy、成本;
  • 安全测:Prompt Injection、越权Tool、SSRF、敏感数据外泄;
  • 线上测:漂移、长尾失败、模型与工具版本变化。

Agent测试最忌讳只断言最终答案包含某句话。答案可能碰巧正确但调用了危险工具,也可能措辞不同却完全正确。需要同时验证Trajectory、Evidence、Side Effect和Final Answer。

9. 缺陷向回归资产的转化

每个生产缺陷走这条闭环:

保存失败输入、环境、版本与Trace
→ 缩小成最小复现
→ 在能抓住它的最低测试层加Case
→ 修复并确认测试先红后绿
→ 加入回归集和CI门禁
→ 监控同类错误是否下降

Agent失败还要保存Model、Prompt、Tool Schema、知识快照和随机参数。若只保存用户Query,在模型或索引版本变化后通常无法准确复现原始运行条件。

10. 面试速答

单元测试越多越好吗

不是。测试也有维护成本。优先覆盖稳定行为、边界和风险;大量复制实现细节的脆弱测试会阻碍重构。

覆盖率多少合适

没有通用数字。看高风险模块、增量覆盖和未覆盖分支;覆盖率配合Mutation、缺陷数据和评审使用。

E2E最真实吗,为什么不全写E2E

它覆盖真实装配,但慢、昂贵、定位差且更易Flaky。边界和异常应尽量在低层验证,E2E保护少数关键旅程。

Agent评测和传统测试有什么区别

传统测试多用确定性Oracle判断Pass/Fail;Agent评测常面对多种合法输出,需要数据集、Rubric、统计和人工校准。但Agent周围的传统软件仍应使用普通测试。

参考