ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EEZ Studio Agent Harness 测试方案全解析:从原生 `.eez-project` 编辑到真实后端构建的验证体系

EEZ Studio Agent Harness 测试方案全解析:从原生 `.eez-project` 编辑到真实后端构建的验证体系 EEZ Studio Agent Harness 测试方案全解析从原生.eez-project编辑到真实后端构建的验证体系【免费下载链接】CLI-AnythingCLI-Anything: Making ALL Software Agent-Native -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything导读本文围绕 CLI-Anything 仓库中 EEZ Studio 工具链的测试计划文档 TEST.md系统拆解该 Agent 化 CLI 工具cli-anything-eez-studio如何通过单元测试、端到端E2E测试与真实工作流场景验证其对 EEZ Studio 原生 LVGL 工程 JSON、SCPI 仪器命令模型、会话撤销/重做及真实 Node 后端的控制能力。阅读完本文你将掌握这套测试矩阵的设计意图、每个用例背后的源码实现依据、可复现的测试运行命令以及默认不依赖真实后端、按需 opt-in 接入 EEZ Studio这一测试分层策略的落地方式。该 harness 的定位是直接编辑 EEZ Studio 原生.eez-projectJSON 文件并在配置好EEZ_STUDIO_SOURCE时调用真实 EEZ Studio上游eez-open/studio的 Node 后端完成构建/导出。测试体系的根本目标就是在没有真实桌面软件的环境下仍能验证核心能力同时为真实后端留出可选的验证闸门。一、测试存量总览两层测试矩阵TEST.md 声明的测试清单分为两个文件位于 tests 目录测试文件规划数量实际运行结果test_core.py8 个单元测试规划10 passed含后补的 REPL 分发与自定义构建命令用例test_full_e2e.py4 个 E2E 测试规划4 passed 1 skipped真实后端用例默认跳过需要特别指出规划与实际之间的演进TEST.md 记录的最终执行结果中test_core.py实际包含 10 个用例比最初规划的 8 个多出两个——test_repl_dispatch_preserves_open_session_mutation_and_undoREPL 分发与会话复用与test_custom_build_command_uses_shlex_for_quoted_args自定义构建命令的引号解析。这体现了测试计划在迭代中持续扩充文档末尾的执行输出忠实反映了这一状态。单元测试通过 Click 的CliRunner在进程内驱动 CLI 逻辑test_core.py而 E2E 测试则把 CLI 当作独立进程通过subprocess.run调用test_full_e2e.py并在找不到已安装命令时回退到python -m cli_anything.eez_studio.eez_studio_cli。这两种方式分别覆盖内部逻辑正确性与真实命令行入口的可用性。二、单元测试方案四大模块的逐点拆解TEST.md 将单元测试按被测核心模块分组以下结合源码逐一还原其设计意图与验证逻辑。1.core.project原生工程文档的生命周期project.py 是整套 harness 的心脏直接操作 EEZ Studio 原生 JSON 结构。规划的五类用例分别对应创建含原生必需分节的工程。create_project()project.py生成的结构必须包含settings.generalprojectType、lvglVersion、displayWidth/Height 等、settings.builddestinationFolder 及一组构建模板文件、userPages首个页面内挂LVGLScreenWidget根组件与scpi分节。test_create_project_has_native_sections断言默认lvglVersion DEFAULT_LVGL_VERSION即 9.2.2、destinationFolder src/ui、首屏首组件类型为LVGLScreenWidget且project_info()统计page_count 1test_core.py。保存/加载往返。save_project()采用带fcntl文件锁的原子写方式project.pyload_project()在解析后立即执行validate_project()校验project.py。test_save_load_round_trip验证字节数大于 0且回读后projectName一致。修改通用设置与构建目标。set_general()只允许修改白名单内的键projectName、lvglVersion、flowSupport、displayWidth、displayHeight、colorBpp并对数值/布尔做强制转换与正值检查project.pyset_build_destination()则统一把反斜杠归一为正斜杠project.py。添加页面与 LVGL 控件。add_page()依据 display 尺寸追加页面并分配自增 idadd_label()/add_button()把控件挂到页面的LVGLScreenWidget根组件 children 下其中按钮还自动附带一个子 Label 控件project.py。对应用例断言页面数为 2、LVGLLabelWidget与LVGLButtonWidget均被识别。从源码结构还可以看到一处分层技巧validate_project()将工程类型限定为lvgl/dashboard/firmware/resource四种并对 LVGL 工程的显示分辨率做正值校验project.py。这意味着凡是能通过load_project()的文档都已被强制约束在可被 EEZ Studio 消费的骨架内。2.core.scpi仪器命令模型与查询响应元数据scpi.py 面向为可测性仪器添加命令面这一场景规划用例为添加子系统、命令与参数。add_subsystem()拒绝重名子系统add_command()拒绝同名命令add_parameter()同样做重名保护scpi.py、[L63-L92]、[L95-L124)。保留查询命令以?结尾的响应元数据。这是 SCPI 建模中最值得注意的语义add_command()判断命令名是否以?结尾若是则为该命令写入response.type默认quoted-string可通过response_type覆盖如nr3否则response为空对象scpi.py。list_commands()则通过name.endswith(?)还原每个命令的query布尔标记并统计参数个数、响应类型scpi.py。test_scpi_subsystem_command_parameter的断言commands[0][query] is True与parameters 1test_core.py验证了整条链路的正确性query 判定不是靠额外字段而是命令名后缀即事实。3.core.session跨原生变更的撤销/重做快照Session 为Agent 在一次会话内连续变更工程提供内存级保护要点如下每次变更前调用checkpoint()用deepcopy把当前工程快照推入_undo_stack深度上限MAX_UNDO_DEPTH 50超限时从栈底弹出最早快照先被丢弃undo()把当前工程压入 redo 栈后弹回上一快照redo()对称反向操作save_state()把会话状态含工程 info 汇总以 JSON 落盘到~/.eez-studio-cli/sessions/session_id.jsonlist_states()按时间倒序读取。test_session_undo_redo模拟加 Label 前打点 → undo 回退 → redo 重做三步验证控件数量 1 → 2 → 1 → 2 的往返test_core.py。Session 状态status()汇总了 project_path、modified、undo/redo 可用深度等字段是 CLI 与 Agent 交互的标准化接口。4. CLI JSON 输出机器可读的工程创建规划用例要求通过 Click/subprocess 验证--json project new输出机器可读 JSON 且实际落盘。test_cli_json_project_new使用CliRunner.invoke(cli, [--json, project, new, -o, ...])解析 stdout 为 JSON 并断言project_name与文件存在test_core.py。与之配套的test_cli_json_mutation_autosaves验证了 CLI 的自动保存契约所有会变更工程的命令都会先session.checkpoint()随后在 Click 回调关闭时call_on_close钩子自动调用session.save_project()——除非带了--dry-run或处于 REPL 模式eez_studio_cli.py。该用例新建 → 加 Label → 回读文件三步确认变更确实持久化到了磁盘上的原生工程文件。5. 规划之外的追加用例实际结果中的两个补充最终运行的 10 个单元测试还包含两个后续补充用例test_repl_dispatch_preserves_open_session_mutation_and_undo验证 REPL 模式下CLI 内部复用的是同一个全局_session对象未保存的变更留在会话内存中磁盘文件不变且session undo只作用于会话快照test_core.py。对应 REPL 实现中--project参数注入与会话复用的逻辑eez_studio_cli.py。test_custom_build_command_uses_shlex_for_quoted_args通过 monkeypatch 伪造subprocess.run验证EEZ_STUDIO_BUILD_COMMAND环境变量中的引号参数被shlex.split正确拆分为独立的 argv含含空格的可执行文件路径与参数且工程路径作为最后一个参数追加test_core.py对应实现见 eez_studio_backend.py。三、E2E 测试方案跨进程验证 CLI 行为E2E 层通过子进程驱动真实 CLI 入口优先cli-anything-eez-studio可执行文件否则回退python -m ...覆盖四类行为。1. Native CLI 工作流test_native_project_scpi_workflow完整串联project new建工程 →lvgl add-label→lvgl add-button→scpi subsystem-add SOURCE→scpi command-add SOURCE :VOLTage?随后用project_mod.load_project()回读并断言widget_count 3根屏幕组件 Label Button与scpi_commands 1test_full_e2e.py。这就是文档嵌入式面板脚手架 SCPI 命令面两类真实场景的自动化缩影。2. Backend 状态探测test_backend_status_json调用--json backend status断言 stdout 中包含available键。对应 backend_status() 会扫描EEZ_STUDIO_SOURCE/--source指向的源码树校验 package.json 的 name 为eezstudio、定位 build 目录及docker-build-lib.js返回结构化状态可用时含版本号与 Node 路径。3. 真实后端 Inspectopt-in 闸门这是整套测试体系分层验证思想的集中体现拆成两种执行路径默认路径无需真实后端当未设置EEZ_STUDIO_SOURCE时test_backend_inspect_reports_unavailable_without_source断言命令非零退出stderr 是可解析的结构化 JSON{error: ..., type: RuntimeError}且错误信息含EEZ_STUDIO_SOURCE的配置指引test_full_e2e.py。该错误文本来自 eez_studio_backend.py 的INSTALL_MESSAGE而结构化错误输出由_emit_error()在--json模式下统一负责eez_studio_cli.py。值得注意的是TEST.md 的执行记录显示该 stderr 文本中保留了git clone https://github.com/eez-open/studio.git的安装指引这是文档中唯一出现的外部代码仓库地址用于说明后端来源而非项目宣传。真实后端 opt-in 路径test_real_backend_inspect_required用pytest.mark.skipif(os.environ.get(EEZ_STUDIO_RUN_LIVE_BACKEND) ! 1, ...)守卫test_full_e2e.py只有同时满足EEZ_STUDIO_RUN_LIVE_BACKEND1且EEZ_STUDIO_SOURCE指向已npm run build的 EEZ Studio 检出时才执行并断言回读的projectInfo.displayWidth 800。这条用例直接驱动上游build/project-editor/lvgl/docker-build/docker-build-lib.js的readProjectFile()见 inspect_project()。4. 模拟器输出验证verify_simulator_output()export.py负责验证 LVGL 模拟器构建产物要求index.html、index.js、index.wasm三者存在且非空并分别做内容嗅探——HTML 前 32 字节须含!DOCTYPE html或htmlWASM 前 4 字节必须等于 WebAssembly 魔数\x00asm。该函数在lvgl simulator-build成功后自动执行eez_studio_cli.py也可通过lvgl verify-simulator output_dir单独调用。文档将该验证列为 E2E 计划的一部分用于防止构建成功但产物无效的假阳性。四、真实工作流场景把测试还原为 Agent 使用故事TEST.md 用三个角色扮演式场景说明测试矩阵覆盖的业务动因它们与上文用例一一对应嵌入式面板脚手架模拟嵌入式 GUI 开发者搭建面板工程建工程 → 加 LVGL 控件 → 保存 → 校验。验证点原生 JSON 结构、页面/控件计数、产物文件存在。对应 CLI 参考 README.md 中的project new/lvgl add-label/lvgl add-button链。SCPI 仪器命令模型模拟测试工程师添加可测命令面加子系统 → 加查询命令 → 按需加参数。验证点子系统与命令数组与 EEZ Studio SCPI 模型一致。后端 LVGL 工程检查模拟构建自动化在制造/测试导出前读取工程设置准备目标目录 → 验证默认的 unavailable-backend 行为 → 可选地调用真实 EEZ Studio Node 后端。验证点默认返回结构化不可用错误opt-in 时返回后端退出码与来自docker-build-lib.js的结构化工程信息。这三个场景共同回答了测试到底在保护谁的体验单个 Agent 进程内的连续编辑安全场景 1/2 会话快照、无桌面软件的 CI/沙箱环境下的确定性错误场景 3 默认分支、以及追求完整构建链路的用户场景 3 opt-in 分支。五、测试执行命令、结果与解读TEST.md 记录了从 eez-studio/agent-harness 目录执行的完整验证序列python3 -m json.tool ../../registry.json python3 -m compileall cli_anything/eez_studio python3 -m pip install -e . python3 -m pytest cli_anything/eez_studio/tests/test_core.py -v env -u EEZ_STUDIO_SOURCE -u EEZ_STUDIO_RUN_LIVE_BACKEND python3 -m pytest cli_anything/eez_studio/tests/test_full_e2e.py -v五条命令分别对应registry.json 的 JSON 合法性、全包字节码编译、可编辑安装、单元测试、以及在显式清除两个后端环境变量-u前缀前提下运行 E2E 套件。最后一条-u的使用细节值得注意——它确保 E2E 在测试机上不会因残留的EEZ_STUDIO_SOURCE意外滑入真实后端分支从而保证默认不可用行为的确定性。实际输出文档原文摘录显示两层结果单元测试10 passed in 0.11stest_create_project_has_native_sections、test_save_load_round_trip、test_set_general_and_destination、test_add_page_and_widgets覆盖工程文档生命周期test_scpi_subsystem_command_parameter覆盖 SCPI 建模test_session_undo_redo覆盖会话快照test_cli_json_project_new、test_cli_json_mutation_autosaves覆盖 CLI JSON 契约与自动保存test_repl_dispatch_preserves_open_session_mutation_and_undo、test_custom_build_command_uses_shlex_for_quoted_args补充 REPL 复用与引号解析。E2E4 passed, 1 skipped in 1.12stest_help、test_native_project_scpi_workflow、test_backend_status_json、test_backend_inspect_reports_unavailable_without_source通过test_real_backend_inspect_required因 opt-in 条件未满足被跳过——这正是在无 EEZ Studio 真机环境下期望的行为。六、汇总统计与覆盖边界文档末段的统计结论可作为回归基准单元测试 10 passed / 0 failedE2E 4 passed、1 skipped默认跳过因真实后端检入为 opt-inregistry.json JSON 校验通过Python 全量 compileall 通过可编辑安装pip install -e .通过。覆盖边界说明是理解这套体系设计哲学的最后一块拼图原生.eez-project编辑路径、REPL 会话复用、会话撤销/重做、SCPI 模型编辑、CLI 子进程执行、JSON 输出、unavailable-backend 处理、带引号的自定义构建命令解析全部在默认环境中被覆盖而真实 EEZ Studio 后端路径被设计为 opt-in E2E 闸门仅当设置EEZ_STUDIO_RUN_LIVE_BACKEND1且EEZ_STUDIO_SOURCE指向已构建的源码检出时才启用。七、如何复现这套验证在 eez-studio/agent-harness 目录下准备 Python 3.10 环境运行时依赖 Click 与 prompt-toolkit见 setup.py随后依次执行pip install -e . python3 -m pytest cli_anything/eez_studio/tests/test_core.py -v python3 -m pytest cli_anything/eez_studio/tests/test_full_e2e.py -v若要解锁真实后端 E2E 闸门需要先准备 EEZ Studio 源码树并构建npm install npm run build再导出两个环境变量后重跑 E2E完整 LVGL 模拟器构建还要求 Docker 可用。工程操作命令的完整入口可参考 README.md 中的命令参考表project/lvgl/scpi/backend/session五大命令组。这种默认轻量、按需重型的测试分层为其他依赖真实桌面软件或重型后端工具的 Agent harness 提供了一个可直接借鉴的工程范本。【免费下载链接】CLI-AnythingCLI-Anything: Making ALL Software Agent-Native -- CLI-Hub: https://clianything.cc/项目地址: https://gitcode.com/GitHub_Trending/cl/CLI-Anything创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表