1.当我们决定用 AI 辅助生成测试

最近,我们 QA 部门正在进行一项自动化工作:将现有的自动化测试框架从 A 迁移到 B。

我们的任务是将基于框架 A 的脚本转换到框架 B 上。

“这不就是个翻译工作嘛?直接用大语言模型啊!” 这是一种很自然的反应。

于是,我们开始使用 Github Copilot 来辅助这次自动化脚本的迁移工作。

然而,我们遇到了非常多的问题,以至于花费了近两倍的工作量(相比于不使用 AI),生成的测试脚本仍然无法完美地执行。

2.我们踩过的坑

2.1. AI 并不知道框架的定义

一开始,我们给了一个非常直觉的提示词:“把 tests/目录下的 pytest 脚本都转换成基于 RobotFramework 的测试脚本”,并选择了 Github Copilot 的 Agent 模式。

我们本以为它会正确完成所有工作,我们只需要点击 Run 就行了。然而,结果却出乎意料。

经过预览,我们发现了两个严重的语法错误:

  1. AI 大量使用了 Click UI Element、Verify UI、Setup Test Env 等关键字。这些关键字是直接从框架 A“翻译” 过来的,在新的自动化框架 B 中根本就不存在。

  2. AI 使用了 AppiumLibrary 中定义的关键字,而不是框架 B 中的定义。

我们这才意识到,AI 对我们的自动化框架 A 和 B 并不了解,极度缺乏这部分的上下文知识。于是,我们找出了框架 A 和 B 的相关文档,特别是 API 的定义,将它们加入到 Github Copilot 的上下文中,这才解决了一些问题。

2.2. AI 不懂装懂

增加了 API 定义文档的上下文后,问题解决了一部分,但并非全部。AI 只是自以为是地生成了一个结果,我们完全不清楚它这么做的依据。

例如,我在原来的框架 A 脚本中调用了一个 Python 的 API 函数,但在框架 B 中并没有对应的定义。于是 AI 就直接生成了一个关键字,但没有任何额外的说明。

再比如,下面是框架 A 中的一行脚本:

element = driver.find_element(by=By.ID, value="id")

assert element is not None

AI 直接生成了一行:

Element Should Exist id=id

然而,Element Should Exist 是一个没有定义的关键字,这可以被视为 “幻觉” 的产生。

类似 “不懂装懂” 的案例还有很多。这严重影响了我们测试迁移的效率,因为我们假设 AI 是 “懂” 的,但它实际上 “不懂” 却又不告诉我们。

2.3. AI 不知道环境上下文

在解决了所有语法问题之后(这让我们编写了大量的提示词并额外增加了不少测试脚本),也就是说,生成的每个关键字要么在框架 B 中有了定义,要么能在内置关键字中找到。随后,我们进入了试运行阶段。

接着,我们又遇到了许多运行时报错和警告。我们发现生成的脚本中包含了许多旧版本的关键字,例如 Run Keyword If、[Return] 等。这些关键字是早期版本 4.0/5.0 使用的,而在最新的 7.0 版本中已经被 IF/END 和 RETURN 等关键字替换了。于是,我们再次修改了提示词,增加了 RobotFramework 的版本声明。

此外,我们之前框架 A 所依赖的一些 Python 开源库版本比较老旧,而框架 B 的封装库切换到了全新的 Python 库上。这种隐藏的版本差异性导致我们发现了许多潜在的错误,而且这些问题只有在试运行时才能发现。

2.4.AI 并不知道框架的隐藏实现

之后,我们的被测系统进行了一次重大升级,导致安卓设备偶尔会发生连接中断。

自动化框架 A 有一个主动预防机制,它能智能地检测安卓设备的连接状态,并尝试重连和再次执行 API。但在自动化框架 B 中,这样的机制是不存在的。

这种在框架 A 中存在的隐藏实现,AI 并不知道它在框架 B 中不存在。

我们发现,试图通过提示词告诉 AI 这种差异,和我们自己重新编写一个封装关键字,在时间和效率上是差不多的。这让我们最终放弃了完全依赖 AI 来完成所有隐藏映射的想法。

在跨过了很多坑,才让我们的测试脚本迁移工作站告一段落。同时,我们也感到了失望,认为 AI 并没有帮助我们节省多少成本,基于我们对它过高的期望。

3.测试生成的人机协作模式

然而,当我们用更开放的心态回顾这次实践后,我们都认为如果再来一次,我们会做得更好。在踩过这些坑之后,人机协作的范式和迭代方式似乎变得更加清晰了。

无论你是像我们一样从一个自动化框架迁移到另一个,还是直接从业务和产品需求生成手工测试用例,或是通过 API 定义生成单元测试,只要你开始思考并优化以下四个步骤,就能让与 AI 的协作更加紧密和符合期望。

3.1.制定测试生成策略

如果一开始就想生成所有测试,必然需要考虑得尽可能周全,但这与大语言模型的 “交互式” 形态是相悖的。

我们必须进行多轮与 AI 的交互,增量和迭代地验证我们的设想。这种设想是基于我们对环境(被测系统)表现和所使用的工具(AI)能力的观察。

因此,敏捷是唯一的选择,不要指望一句话就能解决复杂的测试生成问题。

我们可以从生成某个测试脚本、某个被引用最多的函数/用例,或者某个核心业务用例开始,开启迭代过程。

当然,选择合适的 AI 工具也很重要,需要考虑成本、效率和合规等问题。

如果团队需要多人协作完成,那么如何进行职能分工、如何同步和合并生成的测试、以及如何处理生成的冲突,也需要充分讨论和实践。

如果这一步实在无法规划,特别是你第一次接触 AI 生成测试的任务,也没关系,可以继续往下走,因为后面还会再来优化。

3.2.构造 “合适的” 上下文

在测试生成任务中,上下文的构建可以通过提示词和 RAG 来实现。

无论是 Google、OpenAI 还是 Anthropic,都发布了关于如何设计提示词的最佳实践。总结起来,以下五条是我们进行测试生成时可以借鉴的:

明确具体的任务描述:模型是基于概率预测的,不会 “读心”。模糊的描述会导致输出偏离预期。

提供示例:模型不了解你的项目和业务,需要给它提供上下文和必要的示例。

分解任务,迭代优化:一次性要求模型输出庞大复杂的内容容易出错。我们应该将复杂任务拆解。

约束格式和质量标准:明确输出的格式和质量要求,以便验证和自动化处理。

  1. 设定角色和思维方式:让模型以特定身份或方式思考,能提高相关性和专业度。

此外,需要说明的是,每种模型、模型的每个版本,甚至是工作模式,都可能有不同的提示词构建实践。因此,了解它们的 “脾气”,给它们 “可口” 的提示词,才能让返回结果更符合你的预期。换句话说,我们很难找到所谓的 “最佳” 实践。

引入 RAG 可以让模型直接搜索已知文件,并自动构建提示词来生成测试。现在有很多成熟且简单的 RAG 集成案例,在此不再赘述。

3.3.执行测试并收集反馈

虽然我们可以借助其他 AI 来做审查,但在实际测试或生产环境中执行生成的测试,是验证 AI 生成质量的重要途径。

这种验证工作包括以下几个逐步升级的步骤:

  1. 针对可执行脚本,验证是否有编译和连接错误,这是最快速了解和修复生成测试初级错误的方法。

  2. 在测试环境中,进行单次执行,检查每个输入/输出是否都被正确驱动和验证。

  3. 进行多次执行,观察生成测试的稳定性,评估生成测试脚本的准确率和召回率。

  4. 将生成的测试脚本集成到持续集成流水线中,检查是否有任何不适应或冲突。

  5. 进行更长期的监控和观察,验证 AI 生成的测试是否能有效覆盖产品质量特性并发现潜在风险。

收集实际测试结果的反馈,是你进入下一个迭代的原始数据和动力。为了高效地获取反馈并推动测试生产的持续改进,我们可以固定我们的测试环境和被测对象,让整个反馈流程自动化和闭环执行起来。

3.4.认识 AI 能力的边界

前三步的输入和 AI 的输出,让我们对 AI 的边界有了一定的认知。认识 AI 能力的边界是 AI 辅助测试的核心前提,否则很容易对模型抱有 “全知全能” 的幻觉,导致失败。

结合测试用例/脚本生成这个场景,我们可以看到以下几类典型的边界:

  1. 上下文缺失边界:AI 模型无法自动 “知道” 你的系统、业务逻辑和技术栈。如果你让模型 “生成支付接口测试”,但没有给出 API 文档和参数规范,模型只能凭借经验胡编字段。再比如,我们在迁移 pytest 到 RobotFramework 时,如果不提供现有封装的关键字和库名,模型会假设一些并不存在的关键字。因此,你需要提供接口定义、示例用例和框架封装说明,否则输出会 “看起来很真,但无法使用”。

  2. 事实与实时性边界:AI 模型的知识可能过时或虚构(因为训练数据选择和污染的影响)。例如,AI 生成的断言语法可能只在某个新版本中支持,但你的运行环境是旧版,导致执行失败。测试脚本对版本依赖性很强,必须验证 AI 输出与实际运行环境一致。必要时,需要结合搜索或手动验证。

  3. 推理与业务理解边界:模型缺乏对你业务规则的真实推理能力。例如,在自动生成边界值测试时,模型不会自动知道系统约束(如字段最大长度、合规性规则),除非你明确提供。因此,AI 的推理能力更多是 “模式匹配 + 概率预测”,需要人提供业务规则和边界条件,才能生成有用的测试。

  4. 确定性与一致性边界:同样的提示词,多次调用可能会产生不同的结果,输出具有随机性。例如,在与 AI 的多轮对话中,模型可能会 “遗忘” 前面提到的上下文,导致风格或命名不一致。因此,对关键测试用例要做人工审查,或通过提示词工程明确约束输出格式,并分批锁定版本。

  5. 合规与隐私边界:AI 无法自行判断输入是否涉及隐私或敏感数据。例如,直接将生产用户数据粘贴到提示词中让 AI 生成用例,可能违反法规或公司合规要求。因此,我们需要设计脱敏策略、使用内部私有模型,或严格审查输入输出,AI 不会自动帮你做合规判断。

只有认识到 AI 的能力边界,我们才能更好地提供上下文,并在上下文的质量和所付出的成本之间做出权衡,进入下一轮迭代。

4.了解你对 AI 的认知偏差

最后,我们需要探讨一下,为什么我们一开始如此相信 AI 的能力,但最终却不得不付出上述努力来重构以 AI 为辅助的人机协作新模式?

首先,从心理学理论来看,人类天生会将意图、知识和情境理解能力归因于其他智能体。当面对 AI 时,人们会自动类比人类对话,假设 AI 也能 “知道我知道的东西”。这就是为什么人们常常以为 AI 能记住上下文、共享背景知识,但 AI 实际上并没有达到这样的预期。

其次,从社会心理学来看,人们倾向于将非人类系统赋予人类特征。一旦 AI 以自然语言回答,用户很容易下意识地认为它拥有 “理解力” 和 “常识背景”。

最后,在传播学中有一个 “共同知识偏差”:人们以为对方拥有与自己相同的背景信息。当对方是 AI 时,这种错觉更加明显,因为 AI 流畅的对答让人误以为它真的 “懂上下文”。

由于上述认知偏差的存在,我们需要借助上下文工程来纠正这种偏差,让生成的测试真正符合我们的期望。

也正因为如此,在未来一段时间内,AI 测试工程师的存在仍然非常必要。他们将负责将现有的已知知识与 AI 系统进行适配,寻求并推动一条将 AI 整合到测试架构中的道路。

5.小结

本文探讨了利用 AI 辅助进行自动化测试脚本迁移的实践与挑战。

我们的团队尝试使用 Github Copilot 将基于 pytest/python 的框架 A 脚本迁移到基于 RobotFramework 的框架 B,但遭遇了 AI 因缺乏上下文知识而无法理解框架定义、"不懂装懂"、以及不知晓环境差异等问题。这导致迁移工作量不减反增。

通过反思,文章提出了一种人机协作新范式,强调制定策略、构建上下文、执行反馈以及认识 AI 能力边界的重要性。

最终认为,由于人类对 AI 的认知偏差,AI 并不能完全替代测试工程师,而是需要通过有效的上下文工程实现辅助,未来的测试工作将是人机协作的模式。

张昊翔

2025/08/28


↙↙↙阅读原文可查看相关链接,并与作者交流