最近在研究怎么让 AI 自动测试、自动验证 BUG。
最大的问题是,要怎么让 AI 看懂你的游戏呢?
截图可以解决一部分问题。但不是全部。
现在大部分 Coding Agent 都支持操作浏览器、截图,所以至少“画面长什么样”这件事情已经很容易达成了。
想了一下,要实现自动测试,绕不过这三个问题:
- 怎么知道现在在哪个界面?界面上有什么?
- 怎么获取游戏里的数据(存档、界面属性)?
- 怎么模拟玩家操作?
普通网页有 DOM,Agent 可以直接知道当前有哪些元素、它们之间是什么关系、内容是什么。
但 Cocos Creator 最终渲染出来就剩一个 Canvas。
截图只能反映结果,没法告诉 Agent 游戏里的细节。
静态分析拿到的信息终归是有限的,而且很依赖模型的识图能力。
更要命的是,有些时候问题本就出在界面上,甚至有些时候看到的东西不等于真相。
怎么提高 Cocos 对于 Agent 的可见性?
最近突然想到,既然 Agent 可以获取到 DOM 信息,甚至也可以在控制台执行脚本,那这不就很容易把这层隔阂打通了吗?
如果我能够让它通过一段脚本拿到项目里的类,那后面的事情其实就好办很多了。
比如拿节点树、查 Manager、读文本组件的内容,都可以基于这个能力轻松构建。
Creator 2.x 里面这件事比较简单。
在预览环境中,本身就有__quick_compile_project.require
所以可以直接通过这个 require 去拿项目里已经加载的模块。
但到了 Creator 3.x,这个办法就不能用了。
《一顿猛烈的研究…》
最后是从 window.System 下手的。我发现当前已经加载过的模块,可以通过System.entries()遍历出来。
既然模块已经加载进来了,那我把这些模块导出的类全部收集起来,不就可以通过名字再找回去了?
可以做一个类似这样的辅助类:
class ClassRegistry {
static _map = new Map();
static init() {
const system = window.System;
if (!system?.entries) return;
for (const [, ns] of system.entries()) {
for (const key in ns) {
if (key === "default") {
this._map.set(ns[key].name, ns[key]);
} else {
this._map.set(key, ns[key]);
}
}
}
}
static require(name) {
this.refresh();
return this._map.get(name);
}
}
Agent 就可以在控制台使用ClassRegistry.require()找到当前已经加载的类。
注:方法多少有点邪修。如果不介意的话还有一些更粗暴的方法,比如直接 window.game=game
构建基础功能
实现动态获取类的基础功能后,就可以来解决最初的三个问题啦!
这里简单带一下,具体方式就因项目而异啦。
获取节点树
只要能够拿到 Cocos 相关的对象,就可以从当前场景开始遍历节点,把整个节点关系整理出来。
到了这一步,重点反而是应该怎么让 Agent 能够更灵活地去获取数据,而不是把整个节点树的所有数据都一次性丢给 Agent。
获取游戏数据
比如某个 View 的状态是否正确、某个 Manager 当前保存的数据、存档有没有正确更新……
单例处理起来是最简单的,其他的模式,只要拿到管理类,也不是难题。
模拟玩家操作
这就很简单啦,Cocos 的接口调一调。
自动测试!
有了前面的功能作为基础,就能够来实现我们想要的自动测试了。每个项目的需求、架构都是不一样的。
如果想要验证 UI 的正确性,可以使用截图
想要查找 bug,可以参考 Cursor 的 debug 模式
想要自动测试,可以落地单测的自动执行
中秋快乐~
很久没发文(摸鱼)的日子里,每天都在跟 AI 斗智斗勇。也狠狠补了一些 AI 的基础知识,研究怎么更好地使用 AI,怎么通过 AI 提效。
时代变化太快了,一年前还不敢真的把项目交给AI,现在 AI 已经完全能够独当一面,进入了真正的 AI 开发时代。
大家共勉吧。
每天都在瘫坐