跳转到内容

阶段7: 测试与质量

目标: 核心业务逻辑有测试覆盖,CI 自动跑测试,测试失败阻止合并。

模块内容
阶段 0测试基础(单元/集成/E2E、测试金字塔、TDD)

用表驱动测试覆盖纯业务逻辑。

请帮我为酒店预订系统编写 Go 单元测试,使用表驱动测试风格:
1. 价格计算测试(services/pricing_test.go):
- 普通日期:标准间 ¥300/晚 × 3 晚 = ¥900
- 周末加价:周五周六 ×1.2 倍
- 节假日加价:国庆 ×1.5 倍
- 长住折扣:>=7 晚打 9 折
- 边界值:0 晚、负数晚、超过 365 晚
2. 日期验证测试(services/booking_test.go):
- CheckIn 在今天之前 → 拒绝
- CheckOut <= CheckIn → 拒绝
- 入住时间超过 1 年后 → 拒绝
- 正常日期范围 → 通过
3. 预订状态机测试(models/booking_test.go):
- pending → confirmed(支付成功)→ 合法
- pending → cancelled(用户取消)→ 合法
- confirmed → checked_in → checked_out → 合法
- checked_out → confirmed → 非法
- cancelled → confirmed → 非法
4. JWT 工具测试(utils/jwt_test.go):
- 正常生成和解析
- 过期 token → 返回错误
- 篡改 token → 返回错误
- 空 token → 返回错误
要求:
- 每个测试函数用 t.Run() 子测试
- 用 testify/assert 断言
- 测试文件放在同包下
- 运行命令:go test ./... -v -count=1
给出完整的测试代码。

测试 API 端到端行为,使用测试数据库。

请帮我为酒店预订系统编写 Go 集成测试:
测试环境搭建:
- 使用独立的测试数据库(test_hotel_booking)
- 每个测试前清空相关表,插入测试数据
- 写一个 TestMain 函数统一初始化数据库连接
- 使用 httptest 发起 HTTP 请求
测试用例:
1. 搜索 API 测试(handlers/search_test.go):
- 按城市搜索 → 返回该城市的房间
- 按日期搜索 → 排除已被预订的房间
- 按价格区间搜索 → 只返回范围内的房间
- 无结果 → 返回空数组而非 null
- 无参数 → 返回 400
2. 预订 API 测试(handlers/booking_test.go):
- 正常预订 → 201 + 返回预订详情
- 房间已被预订(日期冲突)→ 409
- 房间不存在 → 404
- 未登录 → 401
- 参数不完整 → 400
3. 取消预订 API 测试:
- 本人取消 pending 状态 → 200
- 取消他人预订 → 403
- 取消已入住预订 → 400
- 预订不存在 → 404
4. 并发预订测试:
- 10 个协程同时预订同一房间同一日期
- 只有 1 个成功,其余返回 409
- 用 sync.WaitGroup 并行发请求
给出完整的测试代码,包括 TestMain 和辅助函数。

使用 Playwright 测试用户完整流程。

请帮我为酒店预订系统编写 Playwright E2E 测试:
环境准备:
- 安装 @playwright/test
- 配置 playwright.config.ts(baseURL: http://localhost:5173)
- 测试前确保后端和前端都在运行
测试流程(tests/booking-flow.spec.ts):
1. 搜索房间:
- 打开首页
- 输入城市"杭州",选择入住/离店日期
- 点击搜索
- 断言:显示搜索结果列表,至少有 1 个房间
2. 预订房间:
- 点击第一个搜索结果的"预订"按钮
- 如未登录,先完成登录(用测试账号)
- 填写入住人信息
- 确认预订
- 断言:显示预订成功页,有预订编号
3. 查看预订:
- 进入"我的预订"页面
- 断言:列表中有刚才的预订,状态为 pending
4. 取消预订:
- 点击"取消预订"按钮
- 确认取消
- 断言:状态变为 cancelled
辅助:
- 写一个 login 辅助函数,复用登录逻辑
- 测试数据用 API 直接创建(不依赖 UI seed)
- 截图保存到 test-results/
给出完整的测试代码和配置文件。

配置 GitHub Actions,push 自动跑测试。

请帮我为酒店预订系统配置 GitHub Actions CI:
文件:.github/workflows/ci.yml
要求:
1. 触发条件:push 到 main 和 PR 到 main
2. Go 后端测试 Job:
- 启动 PostgreSQL service container
- 启动 Redis service container
- 安装 Go 1.22
- 运行 go vet ./...
- 运行 go test ./... -v -race -coverprofile=coverage.out
- 上传覆盖率报告
3. 前端测试 Job(并行):
- 安装 Node.js 20
- npm ci
- npm run lint
- npm run build(确保构建不报错)
4. 规则:
- 任一 Job 失败则整个 CI 失败
- PR 必须 CI 通过才能合并(branch protection rule)
- 缓存 Go modules 和 npm 依赖加速
给出完整的 ci.yml 文件和 branch protection 配置说明。

  • 价格计算、日期验证、状态机有表驱动单元测试
  • 搜索/预订/取消 API 有集成测试,覆盖正常和异常路径
  • 并发预订测试确认只有一个成功
  • Playwright E2E 测试覆盖搜索→预订→取消流程
  • GitHub Actions CI 配置完成,push 自动跑测试
  • PR 必须 CI 通过才能合并

  1. 集成测试污染开发数据库: 测试必须使用独立的测试数据库(如 test_hotel_booking),并在 TestMain 中通过环境变量切换。千万不要在生产或开发数据库上跑测试——清表操作会删掉所有数据。

  2. 并发测试不稳定: 并发预订测试偶尔全部失败或多个成功,原因是数据库没有正确的唯一约束或行锁。确认 bookings 表有 (room_id, date) 的唯一索引,且预订逻辑使用了 SELECT ... FOR UPDATE

  3. CI 中 PostgreSQL 连接失败: GitHub Actions 的 service container 需要时间启动。在测试步骤前加 pg_isready 等待,或在连接代码中加重试逻辑。环境变量用 ${{ secrets.DATABASE_URL }} 或直接用 service container 的连接信息。

  4. E2E 测试在 CI 中跑不起来: Playwright 需要浏览器二进制文件,CI 中用 npx playwright install --with-deps 安装。另外 E2E 依赖前后端都运行,CI 中需要在 background 启动服务后再跑测试,或者先跳过 E2E 只在本地跑。