大数跨境

Opencode Day21:OpenCode+Playwright,让AI做测试

Opencode Day21:OpenCode+Playwright,让AI做测试 创见AI实验室
2026-03-28
1
导读:如果你也在写自动化测试,肯定懂这个感觉:查文档、翻API、写选择器、调等待……写一套用例比手点还慢。最近试了个组合——OpenCode + Playwright,发现一个简单的事实:我只需要说人话,A
图片

如果你也在写自动化测试,肯定懂这个感觉:查文档、翻API、写选择器、调等待……写一套用例比手点还慢。

最近试了个组合——OpenCode + Playwright,发现一个简单的事实:我只需要说人话,AI就能把测试代码写好。


一、先搞清楚这俩是什么

Playwright 是干啥的?

微软开源的浏览器自动化框架,能模拟人在浏览器里干的事:

  • 点击、输入、滚动、截图
  • 支持 Chromium、Firefox、WebKit
  • 还能测 API、录屏、无头运行

简单说,你想让浏览器自动干活,它就行。

OpenCode 是干啥的?

开源的 AI 编程助手,跑在终端里。它可以:

  • 理解你的项目结构(跑一下 /init 就行)
  • 用 Plan 模式只出方案,用 Build 模式直接改代码
  • 引用文件、撤销修改、分享会话

重点是——它听得懂中文需求。

这篇讲什么?

用 OpenCode 生成 Playwright 测试代码。你不用记 page.fill、不用写 selector,把需求告诉它,它帮你写。


二、真实场景:我是怎么用的

下面是我实际用 OpenCode 写测试的几个片段,都是真实对话。

场景1:登录页面测试

我在 OpenCode 聊天窗口里说:

“给我的登录页面写个测试,URL 是 http://localhost:8080/tenant/login”

它返回了这样的代码:

  
  
  

import { test, expect } from'@playwright/test';

test.describe('登录测试'() => {
test('登录成功'async ({ page }) => {
await page.goto('http://localhost:8080/tenant/login');
await page.fill('input[name="phone"]''13800138000');
await page.fill('input[name="password"]''123456');
await page.click('button[type="submit"]');
await page.waitForURL('http://localhost:8080/tenant/dashboard');
  });

test('密码错误'async ({ page }) => {
await page.goto('http://localhost:8080/tenant/login');
await page.fill('input[name="phone"]''13800138000');
await page.fill('input[name="password"]''wrong');
await page.click('button[type="submit"]');
awaitexpect(page.locator('.el-message--error')).toBeVisible();
  });
});

保存到 login.spec.ts,运行 npx playwright test,测试就过了。我一行代码没写。

场景2:补充测试场景

我接着说:

“再加几个测试:手机号格式不对要提示错误,账号被禁用不能登录,首次登录要跳转修改密码”

它立刻补上了:

  
  
  

test('手机号格式错误'async ({ page }) => {
await page.goto('http://localhost:8080/tenant/login');
await page.fill('input[name="phone"]''invalid');
await page.fill('input[name="password"]''123456');
await page.click('button[type="submit"]');
awaitexpect(page.locator('.el-form-item__error')).toBeVisible();
});

test('账号被禁用'async ({ page }) => {
await page.goto('http://localhost:8080/tenant/login');
await page.fill('input[name="phone"]''13800138001');
await page.fill('input[name="password"]''123456');
await page.click('button[type="submit"]');
awaitexpect(page.locator('.el-message--error')).toContainText('账号已被禁用');
});

test('首次登录跳转修改密码'async ({ page }) => {
await page.goto('http://localhost:8080/tenant/login');
await page.fill('input[name="phone"]''13800138002');
await page.fill('input[name="password"]''123456');
await page.click('button[type="submit"]');
await page.waitForURL('http://localhost:8080/tenant/change-password');
});

场景3:Dashboard 页面测试

我换了个页面:

“给 Dashboard 页面写测试,URL 是 http://localhost:8080/tenant/dashboard,需要先登录”

它生成了包含 beforeEach 的完整测试:

  
  
  

import { test, expect } from'@playwright/test';

test.describe('Dashboard 测试'() => {
  test.beforeEach(async ({ page }) => {
await page.goto('http://localhost:8080/tenant/login');
await page.fill('input[name="phone"]''13800138000');
await page.fill('input[name="password"]''123456');
await page.click('button[type="submit"]');
await page.waitForURL('http://localhost:8080/tenant/dashboard');
  });

test('显示统计数据'async ({ page }) => {
awaitexpect(page.locator('text=小程序 AppID')).toBeVisible();
awaitexpect(page.locator('text=可用时长')).toBeVisible();
awaitexpect(page.locator('text=已用时长')).toBeVisible();
  });

test('快捷入口'async ({ page }) => {
await page.click('text=视频管理');
await page.waitForURL('http://localhost:8080/tenant/video');
  });
});

三、完整的实战案例

我实际用它给一个租户管理系统写了整套测试套件。

第1轮:登录测试

我说:“给租户管理系统写测试,先写登录的。”

它生成登录测试(成功、失败、格式验证、账号禁用、首次登录跳转)。

第2轮:Dashboard 测试

我说:“继续写 Dashboard 的测试。”

它生成 Dashboard 测试(统计数据、快捷入口、图表展示)。

第3轮:视频管理测试

我说:“视频管理页面的测试。”

它生成视频管理测试(列表展示、筛选、审核、预览)。

第4轮:整合代码

我说:“把这些测试放到不同的文件里,按功能分。”

它建议了这样的目录结构:

  
  
  

admin/tests/
├── tenant/
│   ├── login.spec.ts
│   ├── dashboard.spec.ts
│   └── video.spec.ts
└── admin/
    ├── login.spec.ts
    └── dashboard.spec.ts

我把文件建好,把代码复制进去,测试套件就齐了。


四、跟OpenCode聊天的正确姿势

推荐这样说

  • “给 XX 页面写个测试”
  • “再加一个 XX 场景的测试”
  • “把重复代码提取成函数”
  • “把这些测试按功能分到不同文件”

不要这样

❌ 太长:“我有一个 Vue 3 项目,用了 Element Plus,现在需要为登录页面写测试,登录页面有手机号输入框、密码输入框、登录按钮,需要测试登录成功、登录失败、格式验证三个场景...”

❌ 过于细节:“用 page.goto 导航,然后用 page.fill 填写 input[name="phone"],再用 page.click 点击 button[type="submit"]...”

OpenCode 自己知道怎么分析页面、怎么选选择器。你只需要说“要什么”,不用教“怎么做”。


五、几个有用的提示词模板

你想做什么

一句话怎么说

新页面测试

“给 XX 页面写个测试”

补充场景

“再加一个 XX 场景的测试”

重构

“把重复代码提取成函数”

组织文件

“把这些测试按功能分到不同文件”

添加等待

“不要用固定等待,用 waitForSelector”


六、跑起来就三步

  
  
  

# 1. 装依赖
cd admin
npm install -D @playwright/test
npx playwright install chromium

# 2. 把 AI 生成的代码保存到 .spec.ts 文件

# 3. 运行
npx playwright test

# 想看浏览器怎么跑的
npx playwright test --headed

七、一点感想

以前写测试,总觉得自己在跟 Playwright 的 API 较劲。查 page.fill 的用法,查 expect 的写法,查怎么等元素出现。

现在,我只要想清楚“要测什么”,剩下的交给 OpenCode。它懂页面结构、懂等待策略、懂怎么选选择器。

效率不说翻倍吧,至少不用再翻文档了。


你用过 OpenCode 写测试吗?或者有什么更好用的 AI 测试组合?评论区聊聊。

OpenCode系列精选
Opencode Day20:干货必看!我用这套组合拳零手写代码上线小程序(附全流程)
Opencode Day19:有了Superpowers,我的OpenCode终于不“乱写”了
Opencode Day18:MiniMax出Skills了:前端、后端、安卓、iOS,一套技能全搞定
同一套Skill,要在OpenCode、Claude Code、Codex、Cursor里各配一遍?这个工具治好了我的精神内耗
OpenCode Day16:效率翻倍!我用两个月总结的实战小技巧
OpenCode Day15:实战必看!3小时给娃做了个“早餐小铺”,再也不愁明天吃啥
OpenCode Day14:干货!让AI走流程,不瞎干,效率翻倍
Impeccable实战:OpenCode+自然语言,你只要会说话就能写出专业界面
OpenCode Day12:手把手教你开发第一个自定义插件(从0到发布)
OpenCode Day11:5个让OpenCode记住一切的Memory插件
OpenCode Day10:Skills才是真正的效率核弹,让AI学会替你干活
开发者必看!这7个OpenCode插件,让你的编码效率原地起飞(附完整配置)
Shift+Enter不能换行?OpenCode终端的坑,这一篇全填了(附快捷键大全)
独家拆解:OpenCode真正值钱的,是这3个架构设计
OpenCode vs Trae:AI编程工具终极对决,你选哪一把刷子?
OpenCode Day5:这些让同事直呼“真香”的插件,你装了几个?
OpenCode Day4:2026年如果只学一个功能的话,那就是Skills!

【声明】内容源于网络
0
0
创见AI实验室
创见AI实验室,我们不只是介绍工具,我们共同创造工作方式的未来。
内容 147
粉丝 0
创见AI实验室 创见AI实验室,我们不只是介绍工具,我们共同创造工作方式的未来。
总阅读20
粉丝0
内容147