关于 glubean
glubean 是面向使用 Glubean 进行 API 测试的 Agent 的实践指南,涵盖项目设置、验证和迁移。它根据任务意图与仓库状态选择流程,并提供测试编写和执行规则。
主要功能
- 01区分文档、设置与项目任务
- 02行动前检查仓库上下文
- 03指导 API 测试与契约编写
- 04涵盖迁移、负载和浏览器测试
- 05规范密钥与身份验证处理
适用场景
- 01在新项目中设置 Glubean
- 02为现有 API 编写验证测试
- 03设计先行地定义 API 行为
- 04添加负载或扩展测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ glubean/ skill --skill glubean安装后在 Claude Code 中输入/glubean确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/ci-workflow.mdcli-reference.mdcloud-onboarding.mdcontract-first.mddiagnose.mddocs-index.mddocs-mode.mdimplementation-derived-verification.mdindex.mdload-testing.mdmcp.mdonboarding.mdreferences/patterns/assertions.mdattachment-model.mdauth.mdbrowser.mdbuilder-reuse.mdcase-execution.mdcloud-diagnosis.mdconfigure.mdcontext-setup.mdcontract-browser.mdcontract-first.mdcrud.mddata-driven.mderrors.mdgraphql.mdinit-project.mdmetrics.mdmigration.md详细介绍
Glubean
将此技能用作 Glubean 最佳实践指南。默认采用真实项目工作流。Scratch 模式是用于快速演示扩展功能的路径,并非 Agent 的常规路径。
模式
- 文档:产品问题、概念、比较、迁移、编辑器支持或云功能。
- 入门:尚无 Glubean 项目;用户需要扩展、MCP、cookbook 或项目初始化指导。
- 项目:用户已在 Glubean 项目中,或明确希望开展真实项目测试工作,包括从现有 API 资产迁移。
先确定路径
选择模式之前:
- 检查是否存在
package.json、config/、schemas/、contracts/、tests/、explore/、.env、.env.secrets和GLUBEAN.md。 - 检查依赖项或开发依赖项中是否已包含
@glubean/sdk。 - 检查是否有可用的 MCP 工具。
- 如果存在
GLUBEAN.md,先将其作为项目上下文文件读取。 - 用户应在其中保留关键上下文,包括相关代码、文档、规范和同级工作区的位置。
- 如果用户明确提供了其他上下文位置,也要先读取这些内容,再根据 API 猜测。
然后根据意图和环境确定路径:
- 文档:仅需说明,没有正在进行的项目任务。阅读 references/docs-mode.md。
- 入门:尚无 Glubean 项目,且用户希望妥善完成设置。阅读 references/onboarding.md。
- 项目:代码仓库看起来已是 Glubean 项目,或用户希望在其中开展真实测试工作。阅读 references/project-mode.md。
- 基于实现的验证:相关行为已实现,用户需要测试、契约、覆盖率或验证。在选择
contract()、workflow()或test()输出之前,先阅读 references/implementation-derived-verification.md。 - 设计优先 / 契约优先:用户希望在实现前定义新行为,或规划新的 API 范围。立即转到 references/contract-first.md,然后在编写实际契约时阅读 references/patterns/contract-first.md。
意图示例
- 文档
- “Glubean 是什么?”
- “Glubean 与 Postman 相比如何?”
- “如何在 CI 中运行测试?”
- “如何从 Postman 迁移?”(从 patterns/migration.md 中获取答案)
- 入门
- “为我的项目设置 Glubean”
- “我想试试 Glubean”
- “为 Cursor 配置 MCP”
- 迁移(跨领域——执行请求,路由前先询问)
- “迁移我们的 Postman 集合”
- “转换我们的 Apifox 或 OpenAPI 导出文件”
- “将这些旧 API 测试移植到 Glubean”
- → 询问:“为此设置一个新的 Glubean 项目,还是添加到当前项目中?”
- → 新项目 → 入门 → init → 迁移模式
- → 当前项目 → 项目 → test-after → 迁移模式
- 项目 — 简单模式(默认,test-after)
- “为 /users 编写冒烟测试”
- “提高我的测试覆盖率”
- “修复这个失败的测试”
- “添加认证边界测试”
- → 对于现有行为,阅读
implementation-derived-verification.md;使用explore/或tests/中的test()提供最终的命令式证据
- 云端诊断
- “这次 Glubean 运行为什么失败了?”
- “诊断这次 Cloud 运行:clr_...”
- “获取这次已上传 CI 运行的失败信息”
- → 在获取 Cloud 运行数据前,阅读 references/patterns/cloud-diagnosis.md
- 项目 — 基于实现的验证
- “为这个现有端点编写测试”
- “从这个 API 实现生成契约”
- “提高覆盖率,不要让我列出每个用例”
- → 检查路由/控制器、验证、认证、领域/服务分支、持久化约束、错误映射和现有测试
- → 推导出行为/用例矩阵;除非用户明确要求冒烟测试,否则不要默认只编写一个正常路径或仅检查状态的用例
- → 将稳定承诺表达为契约,将生命周期承诺表达为
workflow(),将命令式证据表达为test()
- 项目 — 契约优先模式(高级,新的结构化规范)
- “我需要一个带 CRUD 的 users API”
- “在我实现之前设计计费端点”
- “为我们尚未实现的 API 编写契约”
- “我的契约覆盖率是多少?”
- “生成投影报告”
- → 仅在定义新行为时将其视为设计优先;在采用简单模式默认值之前阅读
contract-first.md - → 使用
contract.http.with()表达端点承诺,使用workflow()表达生命周期承诺 - → 仅当用户明确要求契约或项目已有
contracts/时使用
- 项目 — 负载测试(选择启用;并发下的性能)
- “以 100 个并发用户对 /checkout 进行负载测试”
- “负载下的 p95 / 吞吐量是多少?”
- “在 CI 中添加性能门禁”
- → 阅读 references/load-testing.md;使用
loadScenario()+loadRunner()+ 阈值编写*.load.ts,通过glubean load <file|dir|glob>运行;仅在用户有意上传到 Cloud 时添加--upload/--upload-target - → 仅在用户选择启用时执行——这会生成真实的并发流量;常规功能覆盖期间绝不自动编写负载测试
- 项目 — 浏览器和 Chrome 扩展测试
- “测试我已解压扩展程序的选项页、内容脚本或 Side Panel”
- “证明工具栏操作可以打开和关闭原生 Side Panel”
- → 阅读 references/patterns/browser.md;对扩展程序支持的页面使用
createExtensionTest(),并将直接文档渲染证明与原生工具栏操作生命周期分开
全局规则
除非项目特定指令另有规定,否则请遵循以下规则:
- 密钥放在
.env.secrets中;公开配置放在.env中。有关多环境设置,请阅读 references/patterns/multi-env.md。 - 使用
configure()创建共享 HTTP 客户端,然后在测试中使用导出的客户端(例如api),不要使用ctx.http。ctx.http仅用于临时演示。 - 环境变量和密钥插值使用
{{KEY}},字面值使用裸字符串。 - 为每个测试添加标签。
- 当
test()需要 teardown、多步骤状态传递、运行时分支或运行时轮询时,使用 builder 模式。 - 使用 kebab-case 测试 ID,并确保在整个项目中唯一。
- 将每个面向人的可读测试字符串都视为诊断信息。用例标题、测试名称、步骤名称、schema 标签、断言消息、警告和日志都应说明正在检查的不变量或业务规则。避免使用“有效”“正常”“检查响应”或“应该通过”等泛泛标签。
- 使用
ctx.assert时,不要省略消息。消息应具体到足以诊断故障;当断言比较运行时值时,传入{ actual, expected }。如果ctx.expect(...)的 matcher 已能生成结构化的实际值和预期值输出,则优先使用。 - 在实际项目中,将可复用的响应类型放在
types/中。仅在用户明确要求的极小临时示例中内联定义。 - 不要使用
.json<any>()。如果响应形状仍未知,先使用.json<unknown>()。只有在已知顶层值是对象时,才使用Record<string, unknown>。一旦字段已知,就尽快收窄为实际类型或 Zod。 - 在实际项目中,将可复用的 Zod schema 放在
schemas/中。仅在用户明确要求的极小临时示例中内联定义。 - 仅当每个用例都调用同一个端点或采用相同的操作模式时,才使用
test.each和test.pick。如果端点互不相关,就分别编写导出的测试。测试 ID 必须包含$field或$_pick占位符,以便每个用例在运行时获得唯一 ID(例如"search-$q"、"user-$_pick")。 - **目标首次需要身份验证且尚未配置身份验证时,先停止编写基础身份验证配置,并向负责人询问身份验证详情。**触发条件是:目标存在身份验证边界,且尚无已确认的身份验证配置覆盖该边界——
401/403、Authorization/Cookie标头、登录/令牌端点、受保护的路由,或 OpenAPI/spec 中的security方案都表明存在此边界。不要猜测身份验证方案,也不要为了“先跑起来”而编写跳过身份验证的测试。先说明你的判断——采用哪种策略(bearer / apiKey / login-exchange)、标头和密钥名称、凭据的来源,以及每项判断的依据——然后等待负责人确认、纠正或补充缺失信息。**一旦目标已有身份验证配置(已设置configure()客户端、密钥已放入.env.secrets,或GLUBEAN.md记录了身份验证决策),就静默复用,不要针对每个 contract 或测试重复询问。**绝不要根据猜测静默配置身份验证。 - 不要向用户复述密钥值。在生成的代码和配置中保留
{{KEY}}占位符,不要替换为解析后的值;在聊天中引用 CLI 输出或响应正文时,删除或遮蔽Authorization标头、Cookie/Set-Cookie值以及任何类似令牌的字段(bearer 令牌、API 密钥、会话 ID)。如果用户分享了看起来经过脱敏的字符串(例如sk-****),不要尝试恢复原值,也不要根据上下文猜测完整值。 - 如果缺少核心项目结构,不要手动创建脚手架。已知目标目录/基础 URL 时,建议运行
npx glubean@latest init --no-interactive;用户想使用交互式提示时,建议运行npx glubean@latest init。 - 用户确认项目级决策(身份验证策略、上下文位置、命名约定、业务规则)后,建议将其添加到
GLUBEAN.md,以便后续会话使用。 - 使用
GLUBEAN.md记录项目级业务规则、角色/状态语义和命名决策。不要在其中手动维护端点矩阵、状态表、请求/响应形状或用例清单;这些内容应放在contracts/中,并通过 projection 或 Cloud 呈现。 - 使用顶层
workflow()编写生命周期 spec。contract.http.with()定义端点行为;workflow()使用call()/poll()和带类型的状态组合已有的 contract 用例;对于不值得进行 projection 的情况,test()仍是命令式运行时的备用方案。 - 不要在 contract 用例中放置
setup/teardown。Contract 用例是语义承诺(description、given、needs、expect、verifyRules、runnability)。运行时设置/清理应根据具体问题放在contract.bootstrap()overlays、defineSession()、workflow().setup/teardown()或test()builder 的 setup/teardown 中。 - 上传和同步应分开进行。
glubean run --upload/glubean load ... --upload会发送目标范围的证据。glubean sync会发送项目范围的源代码 projection,用于 Specifications/OpenAPI/Agent 上下文,且不会运行测试。 - 当前 Cloud 代码使用
runs:write控制glubean sync的 projection 写入,尽管令牌目录中包含了原本用于 contracts/sync 范围的contracts:write。应先说明实际行为;在需要精准说明时,指出范围不匹配。 - Contract 编写的源代码会原样发布供审核——绝不要在 contract 声明中内联密钥。glubean ≥ 0.10.2 的
sync会原样捕获每个 contract 的export const … = contract.…(…)代码片段(包括 verify 函数体),并将其不经脱敏地上传到 Cloud 的 Specs“Source”视图——这正是设计目的:审核者要阅读真实的 contract,因此声明中的内容都不会被遮蔽。所有凭据都必须放在代码片段之外:将真实密钥放入.env.secrets,并通过{{KEY}}/ctx.vars.require("KEY")引用;将具体的非密钥值(ID、主机名)放在文件顶部的 const 中,并通过名称引用——两者都只会以符号而非值的形式进行 projection。写在 contract 对象中的字面令牌/cookie/密码都会被发布。 - 每个 contract 用例的
verify()都必须配有verifyRules——每条断言对应一项,每项都必须是完整的业务陈述,说明该断言强制执行的规则(例如"the returned project id matches the active dogfood project",而不是"id ok")。verify()是运行时闭包:projection 只能记录它存在(hasVerify),因此没有verifyRules时,审核界面只会显示含糊的“custom assertions run”提示,审核者必须切换到源代码查看。Cloud 的 Specs 用例卡片会将verifyRules作为用例的 Verify 步骤呈现,位置就在审核者阅读承诺的地方——应将其写成面向审核者的 verify 函数体规范,并在断言变更时保持同步。没有verifyRules的verify()会造成审核界面缺漏,与没有description的test()属于同一类问题(规则 25)。规则需要稳定标识或单独严重性时,使用对象形式({ id, description, severity });否则使用普通字符串即可。 - Contract ID 是操作的标题,不是命名空间。应使用简短且能描述操作的短语——发挥 OpenAPI
summary的作用:list-projects、get-project、sign-in-with-email、validate-run-upload。绝不要使用点分隔的命名空间关键词堆叠(platform.projects.list)——带作用域的实例名称、feature、tags和endpoint已经体现层级,点分隔的 ID 只是重复这些信息,读起来像内部机制而非实际含义。采用 kebab-case(规则 6),并确保在整个项目中唯一(两个服务公开相同操作时,使用具有描述性的名称加以区分:platform-health-check与dashboard-health-check)。ID 是 contract 的身份标识——它会映射到 OpenAPIoperationId、关联运行证据并作为修订历史的键,因此之后重命名会导致历史记录失联:一开始就取好标题。 - 审核界面的优先顺序:测试
description(第 1 位,最重要),然后是每条断言的message(第 2 位)——两者都必须完整,不得使用简写。Cloud 的 Specs 视图会在不运行测试的情况下将测试投影供审核:只显示测试description、断言的消息、ctx.when/switch/while分支的describe标签、tags和端点——不会投影运行时值(这些值保存在运行证据中,并通过testId关联)。因此:description是审核者首先看到的标题——为每个测试都提供一条完整的一行说明,阐明整个测试验证什么("Authenticate; verify the session contract on success and the rejection contract on failure"),绝不要重复testId、写成 "tests login" 或留空。- 每条断言的
message都是该项检查的说明,也是唯一能说明该检查验证什么的内容。每条断言都必须有一条完整、自包含的结果陈述,可单独审核且不带任何缩写:"a valid session token is returned",而不是 "has token";"a missing order returns 404, not a 500",而不是 "404 ok"。简短标签、对代码的简单复述或空消息都会导致测试无法审核。 在 matcher 适用时,优先使用ctx.expect(...).matcher(expected, "message"),而不是只用ctx.assert(cond, "message")(matcher 名称本身——expect.toBe、expect.toContain、expect.toHaveProperty——会以语义结构呈现)。使用ctx.when/switch/while(每个都带有describe),而不是裸写if/for/while`,这样每种结果的意图都会被呈现,而不只是实际执行到的分支。
- 对
.track("METHOD /path")原始ctx.http调用进行标注,使其按端点审核。Cloud 的 Specs 视图按端点(API 表面)组织内容:每个端点都会汇集其 contract、调用该端点的测试,以及调用该端点的工作流,并标记覆盖缺口。运行 CONTRACT 用例的测试会自动关联(用例本身已包含端点信息)。但原始ctx.http.get(/users/${id})会投影其字面 URL(/users/123),导致覆盖索引无法与 contract 的GET /users/:id对应,并让端点列表充斥一次性路径。因此,无论何时使用原始ctx.http(临时/备用路径——根据规则 2,应优先使用已配置的客户端或 contract 用例),都应固定规范端点:await ctx.http.get(/users/${id}).track("GET /users/:id")。使用与 contract 文档完全相同的METHOD /path字符串,以便测试归入同一个端点条目。(如果字面 URL 已是规范路径,例如GET /users,则.track()可选。) - 声明 contract 的完整请求和响应形状,而不只是状态码。Cloud 会将每个 contract 呈现为 OpenAPI 操作(即发布的 API 参考视图):路径/查询/标头参数、请求正文和响应——包括每个字段的约束标签(
format、enum、minLength/maximum、required)以及逐字段的description。只声明expect: { status }的 contract 会投影出几乎空白的操作,无法审核。因此,对于会写入或读取正文的 contract,应声明带有约束的形状:- 在 contract 级别声明请求正文和请求标头:
request: { body: <SchemaLike>, headers: <SchemaLike>, contentType }(裸写request: <SchemaLike>是正文的简写形式)。正文 schema 是 OpenAPIrequestBody的来源。 - 为每个用例声明查询参数和路径参数:
query: { page: { value, schema, description, required }}和params: { id: { value, schema, description }}(携带 schema 和 description 的是ParamValue对象,而不是裸字符串;路径参数会自动设为必填)。 - 为每个用例声明响应正文和响应标头:
expect: { status, schema: <SchemaLike>, headers: <SchemaLike>}。 使用真正的SchemaLike({ safeParse, toJSONSchema }返回带有format/enum/范围/description的 JSON Schema,或 Zod schema)——仅作为类型占位符的写法({} as SchemaLike<T>)不会投影出任何内容(requestBody为空)。schema 的约束就是审核者要阅读的 contract。
- 在 contract 级别声明请求正文和请求标头:
- 每个不透明的工作流节点都必须有真实的
description。compute/action节点会被投影为opaque(无法静态呈现其转换/IO 逻辑),因此节点的description是审核者唯一能用来理解该步骤的内容——一个不透明节点就会使整个工作流的 projection 变为不完整。绝不要只给不透明节点一个两个词的名称:传入{ id, description },而不是字符串 ID——b.compute({ id: "mark-seed", description: "Mark the run as needing a seed user (sets state.seed=true) so a later step provisions the first account." }, (s) => ...)。description 能在不完整的 projection 中补足结构无法呈现的语义。 - 每个项目都必须通过
typecheck+lint,不能只看运行是否成功。glubean run通过tsx执行——它不会进行类型检查,因此 contract 可以运行成功,但被tsc拒绝。并且tsc完全没有弃用诊断(@deprecated只会在编辑器中显示删除线)——唯一能通过 CLI/CI 检测弃用项的方式是 ESLint 的@typescript-eslint/no-deprecated。Glubean 使用 Zod 4,其弃用 API(.passthrough()、z.string().uuid()/email()/datetime())恰好是 Zod 3 时代代码所使用的 API,可能导致项目在不知不觉中逐渐腐化。因此,应确保项目有npm run typecheck(tsc)和npm run lint(eslint no-deprecated),并在宣布“完成”前同时运行两者,连同运行结果报告各自的退出码 0。如果项目缺少这些检查——包括较早版本的glubean init输出——就补上检查门禁(tsconfig + eslint.config.js + scripts + devDeps)。将verify写成async verify(ctx, res: T),并使用 Zod 4 写法(z.email()/z.uuid()/z.iso.datetime()、.loose())。完整指南和改造步骤见:references/patterns/type-safety.md。 - 验证现有行为时,默认应根据实现推导验证内容。编写测试或 contract 前,请阅读 references/implementation-derived-verification.md。检查可访问的源代码和现有测试,推导有意义的成功、验证、身份验证、状态、冲突和错误用例,并将发现的每条规则映射到已执行的证据或明确记录的缺口。请求/响应 schema 或 OpenAPI projection 只能记录约束,不能证明实现会强制执行该约束。只有在用户明确要求 smoke 测试时,才只生成可达性/状态检查用例。
- 按响应状态码升序排列 contract 的
cases,并将成功路径放在最前面。用例在所有审核界面中都按源码顺序呈现——Cloud 的 Specs 用例卡片、MCPx-glubean-cases和 projection 都是如此——因此用例达到 10 个或以上时,零散的顺序会掩盖成功路径,审核者也必须费力寻找。按expect.status升序排列用例(先放 2xx 成功,再按递增顺序放 4xx:400 → 401 → 403 → 404 → 409 → 422,最后放 5xx);同一状态下按常见程度从常见到极端排列(先放日常验证失败,再放罕见边缘情况)。成功用例是 2xx,因此始终会排在最前。遵循规则 23–28 的同类审核界面规范:读者应能沿着操作主线依次了解如何访问、如何成功以及如何按可预测的顺序失败,而不必通读整个代码块。(用例存在生命周期依赖时——例如后续用例会复用一个deferredseed——应确保依赖关系清晰易读;排序是默认做法,不应因此打乱必要的执行顺序。) - **使用
discover获取资源清单,并在发布到 Cloud 前运行doctor。**优先使用glubean init生成的包脚本:npm run discover会写入资源目录;npm run doctor会以只读方式检查资源、令牌/项目/范围/目标的就绪状态;npm run sync会明确使用.env并发布项目范围的源代码 projection;npm run upload会运行本地 profile 并上传目标范围的证据。doctor 检查成功并不代表获准运行 sync/upload——它只证明已就绪。绝不要将 sync 和 upload 合并为一个操作,也不要仅仅因为 doctor 检查通过就进行发布。 如需详细导航,请从 references/index.md 开始。
如需在实际项目中进行迁移,请先阅读 references/patterns/migration.md,然后再生成文件。
如果提供了 $ARGUMENTS,请将其视为目标端点、文件、标签或自然语言测试请求。
评论
支持 Markdown