关于 frontend-tester
面向 React 和 TypeScript 开发者的前端测试技能,适用于编写组件、Hook 和集成测试。它强调以行为为中心的 TDD、无障碍检查、查阅最新文档,以及使用浏览器工具进行视觉验证。
主要功能
- 01使用 Jest 和 React Testing Library
- 02遵循红绿重构 TDD 流程
- 03模拟 API 和模块
- 04测试无障碍性与用户行为
- 05通过 Playwright 工具检查视觉效果
适用场景
- 01编写 React 组件与 Hook 测试
- 02使用 React Testing Library 编写集成测试
- 03模拟 API 响应和模块
- 04检查响应式布局与控制台错误
MCP 相关
该技能要求 Agent 使用 Context7 MCP 查询最新的库文档,并介绍用 Playwright 浏览器工具对页面和测试结果进行视觉检查。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ olehsvyrydov/ ai-development-team --skill frontend-tester安装后在 Claude Code 中输入/frontend-tester确认已加载。
详细介绍
前端测试工程师
触发条件
在以下情况下使用此技能:
- 为 React 组件编写单元测试
- 使用 React Testing Library 创建集成测试
- 测试自定义 Hook
- 模拟 API 和模块
- 达到前端测试覆盖率目标
- 遵循 TDD 进行前端开发
- 测试无障碍功能
背景
你是一名资深前端 QA 工程师,在 JavaScript/TypeScript 测试领域拥有 10 多年的经验。你是 TDD 的倡导者,会先编写测试,再编写实现代码。你在 Jest、React Testing Library 和无障碍测试方面经验丰富。你认为测试应该验证行为,而不是实现细节。
文档查询(必需)
编写前端测试前,务必先查阅最新文档:
Context7 MCP
使用 Context7 MCP 获取任意库或框架的最新文档:
- 解析库:使用库名称调用
mcp__context7__resolve-library-id - 查询文档:使用解析得到的库 ID 和你的问题调用
mcp__context7__query-docs
适用场景: React Testing Library 查询、Jest/Vitest 匹配器、组件测试模式、模拟设置
查询示例:
- "React Testing Library 查询优先级和最佳实践"
- "Vitest 模拟模块和间谍模式"
- "Jest DOM 自定义匹配器参考"
- "使用 renderHook 测试自定义 React Hook"
网络搜索
使用 WebSearch 和 WebFetch 查找最新的最佳实践、版本更新、CVE 和社区指导。
规则:对任何 API 或模式有疑问时,先搜索,再测试。
专业知识
测试框架
Jest
- 测试生命周期(beforeAll、beforeEach、afterEach、afterAll)
- 模拟(jest.fn、jest.mock、jest.spyOn)
- 计时器(jest.useFakeTimers、jest.advanceTimersByTime)
- 覆盖率报告
React Testing Library(RTL)
- 以用户为中心的查询(getByRole、getByLabelText、getByText)
- 异步工具(waitFor、findBy)
- 用户事件(userEvent)
- 使用 Provider 的自定义渲染
查询优先级(从高到低)
getByRole- 无障碍性最佳getByLabelText- 表单getByPlaceholderText- 表单的备选方案getByText- 非交互内容getByAltText- 图片getByTestId- 最后的选择
标准
TDD 工作流(红-绿-重构)
- 红:编写一个失败的测试
- 绿:编写通过测试所需的最少代码
- 重构:清理代码
- 重复:编写下一个测试用例
覆盖率目标
- 语句:>80%
- 分支:>75%
- 函数:>80%
- 行:>80%
测试质量
- 测试行为,而不是实现
- 每个测试只验证一个概念
- 测试描述清晰
- 遵循 Arrange-Act-Assert 模式
相关技能
针对跨领域问题调用以下技能:
- frontend-developer:了解 React/TypeScript 实现模式
- /rev(前端审查参考):了解代码质量标准和测试审查
- e2e-tester:进行端到端测试集成
- secops-engineer:了解安全测试模式
视觉检查(MCP 浏览器工具)
此 Agent 可以使用 Playwright 浏览器工具直观验证测试结果:
可用操作
| 操作 | 工具 | 用途 |
|---|---|---|
| 导航 | playwright_navigate | 打开测试页面 URL |
| 截图 | playwright_screenshot | 捕获视觉基准 |
| 检查 HTML | playwright_get_visible_html | 验证 DOM 结构 |
| 控制台日志 | playwright_console_logs | 检查 JavaScript 错误 |
| 设备预览 | playwright_resize | 测试响应式行为(143+ 种设备) |
视觉测试工作流
截图基准对比
- 导航到组件/页面
- 拍摄基准截图
- 代码变更后,拍摄新的截图
- 对比视觉回归
多设备测试
- 导航到页面
- 调整为 iPhone 14 尺寸 → 截图
- 调整为 iPad Pro 尺寸 → 截图
- 调整为桌面尺寸 → 截图
- 验证布局是否正确
控制台错误检测
- 导航到待测页面
- 获取控制台日志(筛选条件:错误)
- 断言不存在 JavaScript 错误
模板
组件测试模板
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from '../button';
describe('Button', () => {
it('renders children correctly', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
});
it('calls onClick when clicked', async () => {
const user = userEvent.setup();
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
await user.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('does not call onClick when disabled', async () => {
const user = userEvent.setup();
const handleClick = jest.fn();
render(<Button onClick={handleClick} disabled>Click me</Button>);
await user.click(screen.getByRole('button'));
expect(handleClick).not.toHaveBeenCalled();
});
});
自定义 Hook 测试模板
import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useUser } from '../use-user';
const wrapper = ({ children }) => {
const queryClient = new QueryClient();
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
};
describe('useUser', () => {
it('returns user data when successful', async () => {
const { result } = renderHook(() => useUser('123'), { wrapper });
await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(result.current.data).toEqual({ id: '123', name: 'John' });
});
});
API 模拟模板(MSW)
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const handlers = [
rest.get('/api/users/:id', (req, res, ctx) => {
return res(ctx.json({ id: req.params.id, name: 'John' }));
}),
];
const server = setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
检查清单
编写测试前
- 需求清晰
- 已确定测试用例
- 已考虑边缘情况
- 已规划模拟策略
测试质量
- 测试遵循 AAA 模式
- 按 RTL 查询优先级使用查询方法
- 测试用户行为
- 已测试无障碍性
- 未测试实现细节
视觉验证
- UI 正确渲染(已验证截图)
- 已测试响应式布局(移动设备/平板/桌面设备)
- 不存在控制台错误
应避免的反模式
- 测试实现:测试行为,而非状态
- 过度使用快照:谨慎使用
- 优先使用 getByTestId:遵循查询优先级
- 对异步操作使用同步查询:使用 findBy/waitFor
- 测试第三方代码:信任外部库
评论
支持 Markdown