前言

最近准备重新设计公司的自动化测试框架。

一开始,我的目标其实很简单:

能不能让 AI 完全替代测试人员?

后来越研究越发现,这条路并没有想象中那么简单。

这篇文章主要记录整个思考过程,而不是介绍某个具体项目。


最初的设想

最开始,我想的是:

AI
自己规划测试流程
点击所有按钮
分析结果
生成报告

理论上,大模型已经能够:

  • 理解界面
  • 点击按钮
  • 阅读文本
  • 判断结果

似乎已经可以完成整个自动化测试。

但是深入调研以后,我发现真正的问题并不是:

AI 能不能做到。

而是:

AI 能不能稳定做到。


为什么放弃 AI 全流程驱动?

最大的几个问题:

1. Prompt 太脆弱

不同的软件版本

不同的界面

不同的弹窗

都会影响最终效果。

为了提升稳定性,需要不断调整 Prompt。

最终维护成本非常高。


2. AI 不适合确定性验证

例如:

金额计算

属性计算

优惠券叠加

编码参数

这些结果必须:

100%

正确。

99% 的准确率其实等于不能使用。

这些场景应该交给:

  • 单元测试
  • 集成测试
  • Assert

而不是 AI。


3. AI 自己规划流程容易失控

例如:

今天:

打开软件
录像
关闭软件

明天:

AI 可能决定:

打开软件
修改属性
录像
打开菜单
关闭软件

流程越来越不可预测。

Bug 很难复现。

日志也很难分析。


一个重要的转折

后来看到了一些 AI 自动化测试方案(例如 KUITest)。

让我意识到:

AI 真正擅长的是:

泛化。

不是:

控制流程。

于是整个思路开始改变。


AI 应该负责什么?

后来我把职责重新划分。

AI:

负责:

  • 理解界面
  • 提供扰动
  • 判断视觉异常
  • 分析测试报告
  • 推荐新的测试 Case

传统自动化:

负责:

  • 流程执行
  • 点击
  • Assert
  • 数据验证
  • 属性验证

整个职责开始变成:

DIAGRAM / RESPONSIBILITY_MATRIX
flowchart LR
    goal["可靠的自动化测试"]

    subgraph ai["AI · 负责泛化"]
        direction TB
        a1["理解界面"]
        a2["提供扰动"]
        a3["判断视觉异常"]
        a4["分析报告与推荐 Case"]
    end

    subgraph deterministic["传统自动化 · 负责确定性"]
        direction TB
        d1["执行固定流程"]
        d2["点击与读取属性"]
        d3["数据验证与 Assert"]
        d4["输出可复现结果"]
    end

    ai --> goal
    deterministic --> goal

自动化测试真正的目标

以前我一直认为:

自动化测试:

就是:

模拟人的操作。

后来发现不是。

真正的目标其实是:

构建一条可以不断重复执行的验证链路。

所以我重新定义了一条测试链:

DIAGRAM / OBSERVABLE_VALIDATION_CHAIN
flowchart LR
    backend["Backend<br/>PASS"] --> service["Service / Feeder<br/>PASS"]
    service --> client["Client<br/>FAIL"]
    client --> ui["UI<br/>FAIL"]

    classDef passed fill:#dff4dd,stroke:#171c24,color:#171c24,stroke-width:2px
    classDef failed fill:#ffd9d4,stroke:#171c24,color:#171c24,stroke-width:2px
    class backend,service passed
    class client,ui failed

每一层都应该能够独立观察。

失败的时候,不再只告诉你一个 FAIL,而是同时标出每一层的状态。

这样开发人员几乎可以立即定位问题。


自动化测试应该如何分层?

最终我把整个系统拆成了六层。

DIAGRAM / SIX_LAYER_ARCHITECTURE
flowchart TB
    testCase["06 · Case<br/>组合业务测试流程"]
    ui["05 · UI Adapter<br/>读取界面状态"]
    backend["04 · Backend Adapter<br/>调用 Backend DLL 与记录 Trace"]
    observer["03 · Observer<br/>只观察系统状态"]
    windows["02 · Windows 能力<br/>Process / Service / Shortcut / File"]
    core["01 · Core<br/>Runner / Step / Context / Timeline"]

    testCase --> ui
    testCase --> backend
    testCase --> observer
    ui --> windows
    backend --> windows
    observer --> windows
    windows --> core

第一层:Core

负责:

  • TestRunner
  • Step
  • Context
  • Timeline

这里不关心任何业务。


第二层:Windows 能力

封装:

  • Process
  • Service
  • Shortcut
  • File

所有和 Windows 相关的能力。


第三层:Observer

负责观察系统状态。

例如:

  • service_status.json
  • camera_snapshot.json

Observer 永远不主动控制系统。

只负责观察。


第四层:Backend Adapter

封装 Backend DLL。

提供:

  • Discover
  • Open
  • Close
  • Property
  • Capture

所有调用都会记录 Trace。


第五层:UI Adapter

封装:

UI Automation。

这里只负责:

读取。

而不是业务。


第六层:Case

真正的测试流程。

例如:

CheckService
Launch AdminConsole
Observer 获取 Camera
UI 获取 Camera
Compare
Generate Report

Case 不直接调用底层。

而是组合已有能力。


为什么要这样分层?

因为真正需要复用的不是:

代码。

而是:

能力。

例如:

今天完成:

LaunchProcess()

以后:

任何 Case 都可以使用。

今天完成:

ReadCameraList()

以后:

所有测试流程都能直接调用。

整个系统会越来越像积木。

而不是越来越复杂。


多 Agent 开发

整个项目后面采用了多 Agent 并行开发。

每个 Agent:

只负责一个模块。

例如:

Agent A
Core
----------------
Agent B
Windows
----------------
Agent C
Observer
----------------
Agent D
Backend Adapter
----------------
Agent E
UIA
----------------
Agent F
Case

第二天回来以后。

我不会先 Review 代码。

而是:

Review:

能力。

例如:

今天:

新增了:

  • 启动程序
  • 检查 Service
  • Observer
  • Camera Discovery

只有这些能力全部能够独立验证。

才开始进入下一阶段。


我的收获

这次最大的改变其实不是:

设计了一套自动化测试。

而是重新理解了 AI。

AI 不应该替代整个流程。

而应该负责:

那些传统自动化最不擅长的部分。

而:

确定性、

稳定性、

可复现、

可定位,

依然应该交给传统自动化。

最终形成:

AI
负责:
泛化。
传统自动化
负责:
确定性。

我认为,这种职责划分,才是真正适合工程项目的 AI 自动化测试方向。


后续计划

目前 V1 的目标非常明确:

  • 完成基础框架
  • 建立 Observer
  • 打通 Backend → Client → UI 链路
  • 实现第一条可重复执行的自动化 Case

等这一版稳定以后,再逐步引入:

  • AI 扰动生成
  • AI 日志分析
  • AI 测试建议
  • AI 回归策略优化

而不是一开始就把 AI 放到整个测试流程的中心。