测试
这个技能提供了全面的测试能力,包括测试策略、自动化设置、测试驱动开发(TDD)、测试编写最佳实践、覆盖率分析、持续集成/持续部署(CI/CD)集成以及使用Playwright进行Web应用程序测试。
何时使用这个技能
- 当为项目设置测试基础设施时
- 当创建测试策略和测试计划时
- 当编写单元、集成或端到端测试时
- 当实施TDD/测试先行开发时
- 当分析测试覆盖率和质量时
- 当将测试集成到CI/CD管道中时
- 当使用Playwright测试Web应用程序时
- 当调试测试失败或提高测试可靠性时
- 当编写测试夹具、模拟数据或工厂函数时
- 当模拟外部依赖项(API、数据库、文件系统)时
- 当组织测试文件结构和测试套件时
- 当测试异步代码、Promise或事件驱动行为时
- 当为UI组件实施快照测试时
- 当配置测试覆盖率阈值时
这个技能做什么
- 测试策略:设计全面的测试策略(单元、集成、端到端)
- 测试自动化:设置测试框架和自动化工具
- TDD方法论:实施测试驱动开发工作流程(红-绿-重构)
- 测试编写:编写专注、可维护的测试与适当模式
- 覆盖率分析:分析和提高测试覆盖率
- CI/CD集成:将测试集成到持续集成管道中
- Web应用测试:使用Playwright测试Web应用程序
- 测试质量:提高测试的可靠性和可维护性
测试策略
测试金字塔
推荐分布:
- 单元测试:70% - 快速、隔离、测试单个函数
- 集成测试:20% - 测试组件交互
- 端到端测试:10% - 测试完整的用户工作流
测试类型:
- 功能测试(正常路径、边缘情况、错误处理)
- 非功能测试(性能、安全、可访问性)
- 回归测试(防止破坏性变更)
- 冒烟测试(关键路径验证)
框架选择
JavaScript/TypeScript:
- Jest, Vitest, Mocha用于单元/集成
- Playwright, Cypress用于端到端
- React Testing Library用于组件测试
Python:
- pytest用于单元/集成
- Selenium, Playwright用于端到端
- unittest用于标准库测试
Java:
- JUnit用于单元测试
- TestNG用于集成
- Selenium用于端到端
Go:
- 内置测试包
- Testify用于断言
Rust:
- 内置测试框架
- Cargo test用于运行测试
测试驱动开发(TDD)
TDD是一种设计技术,不仅仅是测试技术。它通过小而有纪律的步骤产生更好的设计、更易于维护的代码。
核心原则
先写测试,再写代码。总是。 TDD迫使你思考:
- 我需要什么行为?
- 我怎么知道它有效?
- 最简单的实现是什么?
三定律(永不违反)
- 不写生产代码,除非先有一个失败的测试
- 只写足够的测试来展示一个失败
- 只写足够的代码来通过那个测试
红-绿-重构周期
阶段1:红色 - 编写失败的测试
- 编写一个测试来定义所需行为
- 运行测试 - 验证它失败
- 验证它失败的原因是正确的(不是语法错误)
- 尚未编写实现
阶段2:绿色 - 最小实现
- 编写最小代码使测试通过
- 抵制添加额外功能的冲动
- 运行测试 - 验证它通过
- 如果测试仍然失败,修复实现(不是测试)
阶段3:重构 - 清理代码
- 移除代码重复(DRY)
- 改善命名以提高清晰度
- 将复杂逻辑提取到函数中
- 运行所有测试 - 必须在整个过程中保持绿色
- 检查更改行的测试覆盖率
重构后,开始下一个红色阶段的新行为。
测试编写模式
安排-行动-断言(AAA)
结构:
- 安排:设置测试数据和条件
- 行动:执行被测试的代码
- 断言:验证预期结果
示例:
describe('UserService', () => {
it('should create user with valid data', async () => {
// 安排
const userData = { email: 'test@example.com', name: 'Test User' };
// 行动
const result = await userService.createUser(userData);
// 断言
expect(result).toHaveProperty('id');
expect(result.email).toBe(userData.email);
});
});
给定-当-那么(BDD风格)
结构:
- 给定:初始上下文/前提条件
- 当:触发行为的动作/事件
- 那么:预期结果
测试组织
文件结构:
project/
├── src/
│ └── components/
│ └── User.jsx
├── tests/
│ ├── unit/
│ │ └── User.test.jsx
│ ├── integration/
│ │ └── UserAPI.test.js
│ └── e2e/
│ └── user-flow.spec.js
├── jest.config.js
└── playwright.config.js
覆盖率分析
覆盖率目标
推荐阈值:
- 行:80%+
- 函数:80%+
- 分支:80%+
- 语句:80%+
关键路径:
- 始终瞄准关键业务逻辑的100%覆盖率
- 认证和授权
- 支付处理
- 数据验证
覆盖率差距
常见差距:
- 错误处理路径
- 边缘情况
- 边界条件
- 集成点
改进策略:
- 识别未测试的代码路径
- 为错误场景添加测试
- 测试边缘情况和边界
- 增加集成测试覆盖率
CI/CD集成
测试管道
阶段:
- 单元测试:快速反馈,每次提交时运行
- 集成测试:在拉取请求时运行
- 端到端测试:在合并到主分支前运行
- 性能测试:在主分支上运行
质量门:
- 所有测试必须通过
- 覆盖率必须达到阈值
- 没有关键安全问题
- 性能基准达到
使用Playwright进行Web应用程序测试
辅助脚本
这个技能包括Python辅助脚本在scripts/:
-
with_server.py- 管理服务器生命周期(支持多个服务器)。总是先用--help查看用法。# 单个服务器 python scripts/with_server.py --server "npm run dev" --port 5173 -- python your_automation.py # 多个服务器(例如,后端+前端) python scripts/with_server.py \ --server "cd backend && python server.py" --port 3000 \ --server "cd frontend && npm run dev" --port 5173 \ -- python your_automation.py
决策树:选择你的方法
用户任务 → 是否是静态HTML?
├─ 是 → 直接读取HTML文件以识别选择器
│ ├─ 成功 → 使用选择器编写Playwright脚本
│ └─ 失败/不完整 → 作为动态处理(如下)
│
└─ 否(动态Web应用)→ 服务器已经在运行吗?
├─ 否 → 运行:python scripts/with_server.py --help
│ 然后使用助手+编写简化的Playwright脚本
│
└─ 是 → 侦察然后行动:
1. 导航并等待networkidle
2. 截图或检查DOM
3. 从渲染状态中识别选择器
4. 使用发现的选择器执行操作
Playwright最佳实践
- 将捆绑脚本作为黑盒使用 - 使用
--help查看用法,然后直接调用 - 使用
sync_playwright()进行同步脚本 - 完成后始终关闭浏览器
- 使用描述性选择器:
text=,role=, CSS选择器或ID - 添加适当的等待:
page.wait_for_selector()或page.wait_for_timeout() - 关键:在动态应用上检查之前等待
page.wait_for_load_state('networkidle')
示例:基本Playwright脚本
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto('http://localhost:5173')
page.wait_for_load_state('networkidle') # 关键:等待JS执行
# ...你的自动化逻辑
browser.close()
示例
查看examples/目录:
element_discovery.py- 在页面上发现按钮、链接和输入static_html_automation.py- 使用file:// URLs进行本地HTMLconsole_logging.py- 在自动化期间捕获控制台日志
参考文件
需要时加载参考文件以获取详细的测试模式和工作流程:
references/framework_workflows.md- Python(pytest)、JavaScript(Jest, Vitest)、Java(JUnit)、Go、Rust的框架特定TDD工作流程和示例references/test_patterns.md- 常见测试模式、测试组织、命名约定、测试双(模拟、存根、间谍)、参数化和反模式references/webapp_testing.md- Web应用程序测试模式、Playwright最佳实践和端到端测试策略TESTING_REPORT.template.md- 测试质量报告模板,包含覆盖率指标、审计发现和建议
当使用特定框架或需要详细模式时,加载相应的参考文件。
最佳实践
测试质量
- 隔离:测试应该是独立的,并且可以按任意顺序运行
- 确定性:测试应该产生一致的结果
- 快速:单元测试应该快速运行(<100ms每个)
- 清晰:测试名称应该描述它们测试的内容
- 可维护:测试应该在代码变化时易于更新
TDD最佳实践
- 每个测试一个行为:每个测试验证一个行为
- 描述性名称:测试名称描述正在测试的行为
- 独立测试:测试不依赖于彼此
- 快速测试:模拟外部依赖以保持测试快速
- 清晰的断言:断言清楚地显示正在验证的内容
常见错误避免
- ❌ 一次编写多个测试(一次写一个测试)
- ❌ 跳过重构阶段(在绿色后总是重构)
- ❌ 实现在测试之前(删除代码,从测试开始)
- ❌ 在绿色中过度工程(最简单的通过事物)
- ❌ 立即通过的测试编写(必须首先失败)
测试维护
- 在需求变化时审查和更新测试
- 移除过时的测试
- 重构测试以减少重复
- 保持测试数据工厂更新
- 监控测试执行时间
与其他技能的集成
- 调试:在测试意外失败时使用
- 代码审查:TDD产生更容易审查的代码
- 死代码移除:测试有助于识别未使用的代码
- 性能:用于性能测试策略
元原则
TDD是一种设计技术,不是一种测试技术。
周期永不改变:红色 → 绿色 → 重构 → 重复
首先编写测试迫使你思考:
- 我需要什么行为?
- 我怎么知道它有效?
- 最简单的实现是什么?
这产生了更好设计、更易于维护的代码。