news 2026/9/12 2:11:55

Composio E2E 测试体系实战:基于 Docker 的多运行时端到端测试框架解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Composio E2E 测试体系实战:基于 Docker 的多运行时端到端测试框架解析

Composio E2E 测试体系实战:基于 Docker 的多运行时端到端测试框架解析

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

导读

ts/e2e-tests/是 Composio 仓库中专为@composio/core与 CLI 设计的端到端测试体系:它以 Docker 为隔离沙箱,在 Node.js、Deno、Cloudflare Workers 与 CLI 四种运行时上,对核心 SDK 的 ESM/CJS 兼容性、Tool Router、JSON Schema 转换、Claude Agent SDK 集成等关键能力做跨版本回归验证。读完本文,你将掌握该 E2E 框架的目录组织、运行命令、e2e()配置 API、版本解析优先级,以及如何为自己的模块新增一套可复制的多版本测试。

一、框架定位:为什么需要一套独立的多运行时 E2E 测试

@composio/core作为 Composio 的 TypeScript 核心运行时,既要兼容 Node.js 22/24/25 等不同主版本,又要面向 Deno、Cloudflare Workers 等非 Node 生态,还要同步验证 CLI 的命令行为。仅靠单元测试无法覆盖"真实环境下的安装、导入、执行"这条完整链路,因此仓库在 ts/e2e-tests/README.md 中定义了一套以 Docker 容器为执行环境的 E2E 测试体系,核心设计目标有三个:

  1. 隔离性:每个测试在独立 Docker 容器中运行,宿主机环境(全局依赖、版本冲突)不会污染测试结果;
  2. 矩阵化:同一套测试逻辑按 Node.js / Deno / CLI 多版本重复执行,一次编写、多版本验证;
  3. 可调试:每次运行自动生成结构化的DEBUG.log,按运行时版本分组记录每个阶段的命令、耗时、退出码与输出。

二、目录结构:测试套件与共享基础设施

E2E 测试位于 ts/e2e-tests/,由共享基础设施、运行时测试、CLI 测试三大部分组成:

ts/e2e-tests/ ├── _utils/ # 共享测试基础设施 │ ├── Dockerfile.node # Node.js 测试镜像(多阶段构建) │ ├── Dockerfile.deno # Deno 测试镜像 │ ├── Dockerfile.cli # CLI 测试镜像(scratch 基础镜像) │ ├── Dockerfile.install # CLI 安装器测试镜像 │ ├── scripts/ # docker-build.ts / docker-clean.ts 等构建清理脚本 │ ├── src/ # TypeScript 运行器工具(config / e2e / runner / volume 等) │ └── README.md # 基础设施 API 文档 ├── runtimes/ │ ├── node/ # Node.js 运行时测试 │ │ ├── cjs-basic/ # require(esm) 互操作测试 │ │ ├── claude-agent-sdk/ # @composio/claude-agent-sdk + MCP 测试 │ │ ├── custom-tools/ # session.execute / proxyExecute / Zod 校验 │ │ ├── esm-basic/ # ESM 兼容性测试 │ │ ├── json-schema-to-zod-v3/ # Zod v3 兼容 │ │ ├── json-schema-to-zod-v4/ # Zod v4 兼容 │ │ ├── mastra-tool-router-zod-v3/ # Mastra Tool Router + Zod v3 │ │ ├── mastra-tool-router-zod-v4/ # Mastra Tool Router + Zod v4 │ │ ├── openai-zod4-compat/ # OpenAI + Zod v4 兼容 │ │ ├── tool-router-files/ # Tool Router 会话文件(list/upload/download/delete) │ │ ├── tool-router-pagination/ # session.toolkits() 游标分页 │ │ └── typescript-mjs-import-nodenext/ # moduleResolution: nodenext 导入测试 │ ├── deno/ │ │ └── esm-basic/ # 通过 npm: 说明符导入的 ESM 测试 │ └── cloudflare/ │ ├── cf-workers-basic/ # Cloudflare Workers 基础测试 │ ├── cf-workers-files/ # Workers 文件处理测试 │ └── cf-workers-tool-router-ai/ # Workers AI SDK Tool Router 测试 └── cli/ # CLI 运行时测试(scratch 镜像) ├── version/ # composio version ├── whoami/ # composio whoami └── toolkits/ # composio toolkits ├── list/ # composio toolkits list ├── info/ # composio toolkits info └── search/ # composio toolkits search

其中_utils/是整套框架的心脏,其内部源码分工如下(详见 ts/e2e-tests/_utils/README.md):

文件职责
src/e2e.tse2e()入口,从调用者的import.meta.url自动推断工作目录与套件名
src/runner.ts主执行器:按版本创建 describe 块、驱动 Docker 容器、管理DEBUG.log
src/config.ts版本解析(环境变量 / 配置 / mise.toml / package.json)与 CI 跳过逻辑
src/image-lifecycle.ts镜像的按需构建(ensure*Image)与容器运行(run*Container
src/volume.tsDocker 命名卷的创建、所有权初始化与清理
src/types.tsE2EConfigE2ETestResultDefineTestsContext等全部类型定义
src/const.ts预定义版本、透传环境变量白名单、超时常量
src/sanitize.ts输出清洗(去 ANSI、规范化换行)与 JSON 解析助手

三、运行 E2E 测试:命令与版本覆盖

3.1 顶层命令

仓库根目录的 package.json 中,E2E 测试通过 turbo 按包名过滤执行:

命令作用
pnpm test:e2e运行全部 E2E 测试(turbo test:e2e --filter='@e2e-tests/*'
pnpm test:e2e:node仅 Node.js 测试(--filter='@e2e-tests/node-*'
pnpm test:e2e:deno仅 Deno 测试(--filter='@e2e-tests/deno-*'
pnpm test:e2e:cli仅 CLI 测试(--filter='@e2e-tests/cli-*'
pnpm test:e2e:install仅 CLI 安装器测试(--filter='@e2e-tests/cli-install'
pnpm test:e2e:cloudflare仅 Cloudflare Workers 测试(--filter='@e2e-tests/cf-*'

Node 与 Deno 测试在 Docker 内通过bun test驱动(Bun 同时充当运行时与测试框架)。执行前提:宿主机必须安装并启动 Docker,测试框架在启动时会调用docker info检查 Docker 可用性。

3.2 用环境变量覆盖测试版本

默认版本来自mise.toml(Node.jscurrent即 mise.toml 中node = "24.17.0",Denocurrentdeno = "2.6.7")。如需针对特定版本执行,在命令前注入环境变量即可:

# 只跑 Node.js 22.22.3 COMPOSIO_E2E_NODE_VERSION=22.22.3 pnpm test:e2e:node # 只跑 Deno 2.6.7 COMPOSIO_E2E_DENO_VERSION=2.6.7 pnpm test:e2e:deno # 指定 CLI 版本 COMPOSIO_E2E_CLI_VERSION=0.1.24 pnpm test:e2e:cli

3.3 版本解析的优先级(源码级确认)

从 ts/e2e-tests/_utils/src/config.ts 的实现可以看到,三种运行时遵循统一的解析顺序:

  1. COMPOSIO_E2E_*_VERSION环境变量(最高优先级):本地模式下直接覆盖为单版本运行,此时不需要本地安装 mise 工具链也可执行;
  2. e2e()配置中的versions数组:使用测试内声明的版本列表;
  3. 默认值:Node/Deno 读取mise.toml(通过mise current node/deno命令解析),CLI 读取 ts/packages/cli/package.json 中的version字段。

此外,const.ts从 toolchain-versions.json 直接读取 CI 矩阵认可的版本集合:

  • Node.js 预定义版本:22.22.324.17.025.9.0current
  • Deno 预定义版本:2.6.7current
  • CLI 预定义版本:current(即 CLI package.json 版本)。

在 CI 模式下(CI环境变量已设置且版本变量已指定),config.ts 中的computeSkipForVersion等函数会把不匹配的版本标记为skipped,并在DEBUG.log中记录跳过原因,从而实现"矩阵任务各跑各的版本"的并行策略。

四、e2e()API:配置项与上下文

每个测试套件的入口是e2e(import.meta.url, config)。入口函数(ts/e2e-tests/_utils/src/e2e.ts)会先校验import.meta.url必须是file://URL,然后从调用者所在目录自动推导出 Docker 内的工作目录与套件名(目录最后一段),再交给runE2E执行。

4.1 E2EConfig 配置项

属性类型说明
versionsRuntimeVersions要测试的运行时版本,node/deno/cli三选或全选;省略时默认使用mise.toml或 CLI package.json 版本
envRecord<string, string \| undefined>注入 Docker 容器的环境变量;值为undefined时在启动阶段快速失败
usesFixturesbooleantrue时将容器工作目录切到{testDir}/fixtures,用于自带 package.json、需要npm install的测试;默认false
defineTests(ctx: DefineTestsContext) => void使用 bun:test 原语定义测试的回调,每个运行时版本注册一次

4.2 DefineTestsContext 上下文

属性签名说明
runtime'node' \| 'deno' \| 'cli'当前被测运行时
runCmd(command) => Promise<E2ETestResult>,或({ command, files }) => Promise<E2ETestResultWithFiles>在容器内执行任意命令;传入files数组时会把容器内文件拷回宿主机
runFixture({ filename, setup? }) => Promise<E2ETestResult \| E2ETestResultWithSetup>运行 fixture 文件;带setup时启用两阶段(见下文)

4.3 结果类型

  • E2ETestResult{ exitCode, stdout, stderr }
  • E2ETestResultWithFiles:额外携带files映射(文件名 → 内容),用于断言容器内产生的文件;
  • E2ETestResultWithSetup:顶层字段为 fixture 阶段结果,额外提供setup子对象记录 setup 命令的退出码与输出。

五、新增测试完整指南

5.1 Node.js 运行时测试

以真实套件 ts/e2e-tests/runtimes/node/esm-basic/e2e.test.ts 为范本,新增 Node.js 测试只需四步:

  1. ts/e2e-tests/runtimes/node/下新建目录(如runtimes/node/my-test);
  2. 添加package.json,name 取@e2e-tests/node-my-test,并声明test:e2etest:e2e:node脚本(这样 turbo 过滤@e2e-tests/node-*才能命中);
  3. 编写e2e.test.ts,以e2e(import.meta.url, {...})内联配置;
  4. fixtures/目录放置被测脚本。

最小可运行模板:

import { e2e, type E2ETestResult } from '@e2e-tests/utils'; import { TIMEOUTS } from '@e2e-tests/utils/const'; import { describe, it, expect, beforeAll } from 'bun:test'; e2e(import.meta.url, { versions: { node: ['22.22.3', '24.17.0', '25.9.0'], // 可选:默认取 mise.toml 中的 current }, env: { MY_VAR: process.env.MY_VAR }, // 可选:启动时校验缺失变量 defineTests: ({ runtime, runFixture }) => { let result: E2ETestResult; beforeAll(async () => { result = await runFixture({ filename: 'fixtures/test.mjs' }); }, TIMEOUTS.FIXTURE); describe('output', () => { it('exits successfully', () => { expect(result.exitCode).toBe(0); }); it('contains expected output', () => { expect(result.stdout).toContain('expected text'); }); }); }, });

要点说明:

  • versions若不传,框架会回落到mise.tomlcurrent版本;显式声明多版本可同时覆盖 22/24/25 三个主版本;
  • env中传入的变量若在宿主机未设置(值为undefined),runner.ts 的validateRequiredEnvVars会在任何 Docker 操作之前抛错,避免凭据缺失导致的"静默失败";
  • TIMEOUTS.FIXTURE(120 秒)用于beforeAll中调用runFixture的场景,避免镜像首次构建与依赖安装超时。

5.2 Deno 运行时测试

Deno 测试结构相同,差异点在于:

  • 目录建在runtimes/deno/下,包名@e2e-tests/deno-my-test,脚本为test:e2e:deno
  • fixture 通过 Deno 的npm:说明符导入包(如import ... from 'npm:@composio/core');
  • defineTests中无需自行拼deno run,框架在 runner.ts 内部会自动以deno run --allow-all <filename>执行 fixture,以保证权限充足:
e2e(import.meta.url, { versions: { deno: ['2.6.7'], // 可选:默认取 mise.toml 的 current }, usesFixtures: true, defineTests: ({ runFixture }) => { let result: E2ETestResult; beforeAll(async () => { result = await runFixture({ filename: 'test.ts' }); }, TIMEOUTS.FIXTURE); describe('output', () => { it('exits successfully', () => { expect(result.exitCode).toBe(0); }); }); }, });

5.3 需要外部依赖的测试(setup 两阶段模式)

当测试需要在运行时安装 npm 包(例如验证@composio/corezod@4openai@5等第三方库的协同工作),必须使用usesFixtures: true并配合setup选项:

import { e2e, type E2ETestResultWithSetup } from '@e2e-tests/utils'; import { TIMEOUTS } from '@e2e-tests/utils/const'; import { describe, it, expect, beforeAll } from 'bun:test'; e2e(import.meta.url, { versions: { node: ['22.22.3', '24.17.0', '25.9.0'], }, usesFixtures: true, // 容器工作目录切换到 fixtures/ env: { MY_API_KEY: process.env.MY_API_KEY }, defineTests: ({ runFixture }) => { let result: E2ETestResultWithSetup; beforeAll(async () => { result = await runFixture({ filename: 'index.mjs', setup: 'npm install --legacy-peer-deps', // 在 fixture 执行前运行 }); }, TIMEOUTS.FIXTURE); describe('setup', () => { it('npm install completes successfully', () => { expect(result.setup.exitCode).toBe(0); }); }); describe('fixture', () => { it('exits successfully', () => { expect(result.exitCode).toBe(0); }); }); }, });

两阶段机制的底层原理(来自 runner.ts 的runFixture与 volume.ts):

  1. 框架按e2e-{suiteName}-{version}-{timestamp}生成唯一的 Docker 命名卷;
  2. setup 阶段:以读写方式把卷挂载到容器内fixtures/node_modules目录,执行npm install等安装命令;
  3. fixture 阶段:同一卷以只读方式重新挂载,执行node <filename>,保证被测代码无法篡改已安装的依赖;
  4. 卷在finally中清理,且清理是"尽力而为"——失败仅告警、不使测试失败。

这里有一个细节:Docker 卷默认归 root 所有,而 Node 容器以node:node用户、Deno 容器以deno:deno用户运行,因此 volume.ts 的initializeVolumeOwnership会先以 root 启动一个临时容器执行chown,解决写入权限问题。

5.4 Cloudflare Workers 测试

Cloudflare 测试目录在runtimes/cloudflare/下,包名@e2e-tests/cf-my-test。与 Node/Deno 不同,它不通过bun test+ Docker 运行,而是使用 vitest 配合@cloudflare/vitest-pool-workers(可参考真实套件 ts/e2e-tests/runtimes/cloudflare/cf-workers-basic/ 中的vitest.config.mtswrangler.jsonc),以pnpm test:e2e:cloudflare触发。

5.5 CLI 运行时测试

CLI 测试在cli/目录(真实套件还包括agent-signininstallrunsetup-pluginsupgrade等,见 ts/e2e-tests/cli/),运行于 scratch 基础镜像之上,通过runCmd直接断言命令输出:

import { e2e, sanitizeOutput, type E2ETestResult } from '@e2e-tests/utils'; import { TIMEOUTS } from '@e2e-tests/utils/const'; import { describe, it, expect, beforeAll } from 'bun:test'; e2e(import.meta.url, { versions: { cli: ['current'], }, defineTests: ({ runCmd }) => { let result: E2ETestResult; beforeAll(async () => { result = await runCmd('composio version'); }, TIMEOUTS.FIXTURE); describe('output', () => { it('exits successfully', () => { expect(result.exitCode).toBe(0); }); it('stdout matches snapshot', () => { expect(sanitizeOutput(result.stdout)).toMatchSnapshot(); }); }); }, });

注意事项:

  • CLI 运行时不支持runFixture,runner.ts 中对应实现会直接抛出 "runFixture is not supported for CLI runtime tests";
  • 断言前用sanitizeOutput清洗输出,它会在比较前移除 ANSI 转义码(颜色/格式)、把\r\n规范化为\n并修剪首尾空白(见 ts/e2e-tests/_utils/src/sanitize.ts),保证快照在不同终端环境下稳定;
  • CLI 容器运行时会额外注入--add-host host.docker.internal:host-gateway,使测试套件可以确定性地访问宿主机上的 mock 服务(image-lifecycle.ts)。

文件捕获断言:若要在容器内执行命令后断言其产生的文件,可把files数组传给runCmd,框架会用docker cp把文件拷到临时目录、读回内容并打包进结果(容器使用--name命名且关闭--rm以便拷贝,完成后手动docker rm):

const result = await runCmd({ command: 'composio version > out.txt', files: ['out.txt'], }); expect(result.files['out.txt']).toBe('0.1.24');

六、镜像生命周期:按需构建与并发安全

ts/e2e-tests/_utils/src/image-lifecycle.ts 实现了镜像的懒构建策略,三种运行时各有独立镜像标签:

  • Node.js:composio-e2e-node:{version},构建参数NODE_VERSION
  • Deno:composio-e2e-deno:{version},构建参数DENO_VERSIONNODE_MAJOR(Deno 镜像需要 Node 主版本配合);
  • CLI:composio-e2e-cli:{version},构建参数CLI_VERSIONNODE_VERSION

每个镜像都带composio.e2e=true及对应运行时的标签(label),便于统一清理。ensure*Image先执行docker image inspect,命中缓存则直接复用;未命中才构建。针对 CI 并发构建可能出现的竞态(多个 job 同时构建同一 tag),代码在构建失败后检测already exists错误并重新 inspect,若镜像已存在则视为成功。

容器运行时还有两个值得注意的细节:

  1. 环境变量透传buildContainerEnv会自动把ANTHROPIC_API_KEYCOMPOSIO_API_KEYCOMPOSIO_BASE_URLOPENAI_API_KEY这几个"已知变量"从宿主机透传进容器(白名单定义在 const.ts),无需在每个测试里重复声明;
  2. 凭据注入:若宿主机存在~/.composio目录,Node/Deno 容器会以只读 bind mount 方式挂载到容器内/root/.composio,让 E2E job 可以一次性注入user_data.json;CLI 容器则挂载到/tmp/.composio

七、DEBUG.log:结构化调试输出

每个测试套件运行后都会在自身目录下生成一个DEBUG.log文件(路径由 runner.ts 计算为{testDir}/DEBUG.log),其内容由DebugLogManager类负责生成,特性包括:

  • 启动即清空:每次测试运行开始先覆盖文件,杜绝残留数据干扰;
  • 按运行时版本分组:每个版本一个###分隔区段,每个阶段(setup/fixture)一个---区段;
  • 完整的阶段明细:容器名、执行命令、耗时(秒)、退出码(success/failure)、stdout/stderr(空输出显示为(empty));
  • 结尾汇总:逐版本给出 PASS/SKIPPED 状态、阶段数与总耗时,以及整个套件的总时长。

实际输出形态(以真实套件openai-zod4-compat为例):

================================================================================ E2E Test: openai-zod4-compat Started: 2026-01-30T12:18:42.000Z Test file: ts/e2e-tests/runtimes/node/openai-zod4-compat/e2e.test.ts Runtime versions: Node.js 22.22.3, Node.js 24.17.0, Node.js 25.9.0 ================================================================================ ################################################################################ ### Node.js 22.22.3 ################################################################################ Image: composio-e2e-node:22.22.3 --- Phase 1/2: setup --- Container: e2e-openai-zod4-compat-22-22-3-1769775520382-setup Command: npm install --legacy-peer-deps Duration: 2.55s Exit Code: 0 (success) [stdout] added 3 packages, and audited 5 packages in 2s [stderr] (empty) --- Phase 2/2: fixture --- Container: e2e-openai-zod4-compat-22-22-3-1769775520382-fixture Command: node index.mjs Duration: 0.56s Exit Code: 0 (success) [stdout] zod@4 works openai@5 works All packages work together! [stderr] (empty) ================================================================================ Summary ================================================================================ Node.js 22.22.3: PASS (2 phases, 3.11s total) Node.js 24.17.0: PASS (2 phases, 3.09s total) Node.js 25.9.0: PASS (2 phases, 3.08s total) Finished: 2026-01-30T12:18:46.500Z Total duration: 4.50s ================================================================================

调试时,先看 Summary 定位失败的版本,再回到对应版本的阶段区段比对 stdout/stderr 即可快速定位问题。

八、预构建与清理脚本

_utils/scripts/提供了两个镜像维护脚本(通过_utils包的pnpm docker:build/pnpm docker:clean触发):

# 预构建所有预定义 Node / Deno / CLI 版本的镜像(CI 常用,避免任务运行时排队构建) pnpm docker:build # 清理全部 E2E Docker 镜像 pnpm docker:clean

九、约定与边界条件

综合文档与源码,这套框架有以下约定需要遵守:

  1. Docker 是硬性依赖:所有 Node/Deno/CLI 测试都在容器内执行,未安装或未启动 Docker 时无法运行;
  2. 测试按版本串行执行:同一套件内各版本顺序运行,避免资源竞争;容器默认--rm自动清理;
  3. 卷清理是尽力而为:setup 阶段创建的命名卷在finally中删除,删除失败只打印告警、不影响测试结论;
  4. 环境变量必须"前置校验"env中声明但值为undefined的变量会在启动阶段直接报错并列出缺失名单,这是防止凭据静默丢失的关键设计;
  5. 版本矩阵以toolchain-versions.json为准:Node/Deno 的预定义版本来自 toolchain-versions.json,mise.toml中的current版本(Node 24.17.0、Deno 2.6.7)是本地默认,两者结合构成了 CI 与本地行为的一致性基础。

对 Composio 的贡献者而言,理解这套 E2E 框架后,新增一个跨版本回归测试的成本可以压缩到"一个目录 + 一个e2e.test.ts+ 一个 fixture",并且天然获得多运行时、多版本的验证能力——这正是 ts/e2e-tests/README.md 所定义的核心工作流。

【免费下载链接】composioComposio powers 1000+ toolkits, tool search, context management, authentication, and a sandboxed workbench to help you build AI agents that turn intent into action.项目地址: https://gitcode.com/GitHub_Trending/co/composio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 2:10:26

ABB ACS系列变频器GSDML文件:FENA模块接入TIA Portal的完整配置指南

简介&#xff1a;ABB ACS系列变频器GSDML文件&#xff0c;面向工业自动化现场运维与PLC系统集成工程师&#xff0c;用于解决ACS系列变频器在Profibus/Profinet等总线组态时的设备描述与参数配置问题。压缩包内共2个文件&#xff0c;包含1个XML格式的GSDML设备描述文件及1个txt格…

作者头像 李华
网站建设 2026/9/12 2:07:46

轻量IDE不是新工具,而是Java开发者的环境裁剪术

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 2:07:25

SpringBoot+Vue书评系统实战:从后端设计到部署上线

简介&#xff1a;这是一份基于SpringBoot与Vue开发的书评系统毕业设计源码包&#xff0c;面向计算机相关专业学生&#xff0c;可满足毕业设计、课程设计、项目演示及初期立项需求&#xff0c;也适合作为SpringBoot与Vue前后端分离项目的入门范例。项目代码已按前后端分离结构组…

作者头像 李华
网站建设 2026/9/12 2:06:06

Roo Code 聊天界面完整指南:界面布局、输入交互与状态管理

Roo Code 聊天界面完整指南&#xff1a;界面布局、输入交互与状态管理 【免费下载链接】Roo-Code Roo Code gives you a whole dev team of AI agents in your code editor. 项目地址: https://gitcode.com/GitHub_Trending/ro/Roo-Code Roo Code 是运行在 VS Code 侧边…

作者头像 李华
网站建设 2026/9/12 2:05:40

Midscene Chrome 扩展:3 步装好,用一句话驱动浏览器重复操作

Midscene Chrome 扩展&#xff1a;3 步装好&#xff0c;用一句话驱动浏览器重复操作 【免费下载链接】midscene GUI Agent for E2E Testing 项目地址: https://gitcode.com/GitHub_Trending/mid/midscene 每天点登录、填表单、抄数据&#xff0c;这些重复劳动最耗时间。…

作者头像 李华