我不再硬编码测试登录了:用 @account 管理多环境账号
我写过的每一个端到端测试,开头都一样:登录。而登录这一步,恰恰是我的测试套件开始烂掉的地方。
第一版看起来人畜无害。你在本地迭代,于是直接把 dev 账号敲进 spec:
await page.getByLabel('Email').fill('admin@test.dev');
await page.getByLabel('Password').fill('hunter2');
能跑,于是你提交了。六周后,那个密码永远留在了 git 历史里,这个 spec 只跑得了 localhost,而谁要想拿它跑 staging,就会把整个文件复制一份、改掉那两个字符串。于是你有了两个会慢慢分叉的 spec。再乘以每一条需要认证的流程。
"正确"的修法(process.env.PASSWORD 配一个 .env 文件)要好一些,但它只是把问题挪了个位置,并没真正解决。你照样得接好环境变量、记住哪个名字对应哪个环境、把 .env 挡在 git 外头,然后到了 CI 再把这一整套重来一遍。全是体力活,而且每次总会在某些小地方出岔子。
我真正想要的
我想说一句"登录,再加一条 todo",测试就自动以我当下所指环境里那个对应的用户登录,而我永远不用把密码写进 agent 生成的那个文件里。
这正是 Hover 里 @account 功能所做的事。它是我最舍不得的那部分。
它是怎么工作的
在扩展的 Environments 视图里,我把一个目标(比方说 staging)一次性定义好,配上 URL 和一个测试账号。密码存进 VS Code 的 SecretStorage,而不是文件。然后我在聊天里提一句它:
@account log in, open the orders page, and check the latest order is visible
agent 读取当前环境的账号,登录,把这条流程走一遍。到这儿为止都还只是图个方便。真正改变我干活方式的,是我点 Save as Spec 时落进 spec 里的东西:
test('view latest order', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('Email').fill(process.env.HOVER_STAGING_EMAIL!);
await page.getByLabel('Password').fill(process.env.HOVER_STAGING_PASSWORD!);
await page.getByRole('button', { name: 'Sign in' }).click();
// ...
});
账号密码都参数化成了 process.env 引用。真实的邮箱和密码,既不进 spec,也不进 JSDoc 头部,更不进 .hover sidecar。提交进 git 的,是登录的形状,不是密钥。
一个 spec,三个环境
既然账号是以环境为键的,spec 又只引用环境变量名,同一个文件走到哪都能跑:
# local
BASE_URL=http://localhost:5173 npx playwright test
# staging
BASE_URL=https://staging.example.com npx playwright test
把 BASE_URL 指向某个目标,给上对应的 HOVER_<ENV>_* 值,同一个 spec 就能驱动 local、staging,或者一个 PR 预览环境。没有分叉的文件,没有按环境复制的副本。维护 N 份登录流程、还得让它们彼此同步的那笔税,没了。
CI 不用再玩搬运账号密码的仪式
名字就是契约,所以迁到 CI 全是机械活。扩展能把 HOVER_<ENV>_* 这些名字直接导出到你的 CI secrets,你的 workflow 读它们,跟读任何普通环境变量没两样:
- name: E2E
env:
BASE_URL: ${{ vars.STAGING_URL }}
HOVER_STAGING_EMAIL: ${{ secrets.HOVER_STAGING_EMAIL }}
HOVER_STAGING_PASSWORD: ${{ secrets.HOVER_STAGING_PASSWORD }}
run: npx playwright test __vibe_tests__
这一步里没有一点 AI 在跑,而这正是整套架构的用意。agent 把 spec 写好那一次,顺手把密钥参数化出去,然后就退场了。CI 跑的是纯粹的 @playwright/test,没有模型,也没有 key。
回报
那些我一直想着要遵守的纪律(密钥不进仓库、一条流程一个 spec、同一个产物跨环境复用),如今成了阻力最小的那条路,而不再是我晚上六点图省事砍掉的东西。我说一句 @account,agent 就登录,它留下的文件干干净净。
如果你曾经在自己的仓库里 grep 过泄露的测试密码,就懂这为什么重要。
在你自己的应用上试试 Hover。
把 Hover 的 MCP 加到你已经在用的编码 agent。它探索你的应用,结晶出你自己拥有的纯 Playwright spec。
npm i -g @hover-dev/mcp && claude mcp add hover -- hover-mcp阅读快速开始 →