mcpField
U
using-tests

using-tests

github.com/andrelandgraf测试与质量2398 次安装20 周前更新
代码仓库

关于 using-tests

using-tests 是面向应用开发团队的测试工作流技能,帮助选择 Playwright、集成测试或单元测试,并说明并行测试的数据隔离做法。

主要功能

  1. 01测试类型选择指导
  2. 02Playwright UI 测试模式
  3. 03API 集成测试指导
  4. 04独立逻辑的单元测试
  5. 05并行测试数据隔离
  6. 06测试命令与调试提示

适用场景

  1. 01为新功能选择测试类型
  2. 02测试 UI 流程和 API 行为
  3. 03使用隔离数据库数据运行测试
  4. 04排查 Playwright 测试失败

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/andrelandgraf/fullstackrecipes --skill using-tests

安装后在 Claude Code 中输入/using-tests确认已加载。

详细介绍

编写测试

测试策略和工作流。测试会并行运行,每个测试套件使用隔离的数据。UI 测试优先使用 Playwright,API 测试使用集成测试,逻辑测试使用单元测试。

测试策略

决定编写哪种测试时,请遵循以下层级:

  1. Playwright 测试(浏览器)——大多数功能的首选
  2. 集成测试(API)——Playwright 不适用时
  3. 单元测试(纯函数)——仅用于复杂的独立逻辑

何时使用各类测试

Playwright 测试(默认选项)

在功能涉及以下内容时编写 Playwright 测试:

  • 用户交互(点击、输入、导航)
  • 视觉反馈(提示消息、加载状态、错误消息)
  • 表单提交和验证
  • 多步骤 UI 工作流
  • 受保护的路由和重定向
  • 无障碍行为

最适合用 Playwright 测试的功能示例:

  • 带错误处理的登录流程
  • 通过确认对话框创建和删除聊天
  • 主题切换
  • 表单验证消息
  • 页面之间的导航
集成测试

在以下情况下编写集成测试:

  • 直接测试 API 响应(状态码、JSON 结构)
  • 验证操作后的数据库状态
  • 不涉及 UI 的服务端逻辑测试
  • 对该场景而言,Playwright 速度太慢或过于复杂

最适合用集成测试的功能示例:

  • API 路由返回正确的状态码
  • 用户创建后正确写入数据库
  • 登录时设置会话 Cookie
  • 受保护的 API 路由返回 401/403
单元测试

仅在以下情况下编写单元测试:

  • 测试包含复杂逻辑的纯函数
  • 测试包含许多边界情况的代码
  • 测试类型收窄和错误消息
  • 函数没有外部依赖

最适合用单元测试的功能示例:

  • 断言辅助函数
  • 配置架构验证
  • 数据转换函数
  • 工具函数

运行测试

所有测试都针对隔离的 Neon 数据库分支运行,该分支会在 1 小时后自动删除。

bun run test              # All tests with isolated Neon branch
bun run test:playwright   # Browser tests only
bun run test:integration  # Integration tests only
bun run test:unit         # Unit tests only

文件夹结构

src/
├── lib/
│   ├── common/
│   │   ├── assert.ts
│   │   └── assert.test.ts      # Unit test (co-located)
│   └── config/
│       ├── schema.ts
│       └── schema.test.ts      # Unit test (co-located)
tests/
├── integration/
│   ├── llms.test.ts            # Integration test
│   ├── r.test.ts
│   ├── mcp/
│   │   └── route.test.ts
│   └── recipes/
│       └── [slug]/
│           └── route.test.ts
└── playwright/
    ├── auth.spec.ts            # Playwright test
    ├── chat.spec.ts
    ├── home.spec.ts
    └── lib/
        └── test-user.ts        # Playwright-specific helpers

为新功能编写测试

第 1 步:确定测试类型

问自己:“用户会如何验证此功能正常工作?”

  • 通过 UI → Playwright 测试
  • 通过 API 调用 → 集成测试
  • 直接调用函数 → 单元测试
第 2 步:创建测试文件

Playwright 测试: tests/playwright/{feature}.spec.ts

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

test.describe("Feature Name", () => {
  test("should do expected behavior", async ({ page }) => {
    await page.goto("/feature");
    // Test implementation
  });
});

集成测试: tests/integration/{feature}.test.ts

对于 API 路由,直接导入处理程序,让测试更快、更可靠:

import { describe, it, expect } from "bun:test";
import { GET } from "@/app/api/feature/route";

describe("GET /api/feature", () => {
  it("should return expected response", async () => {
    const response = await GET();

    expect(response.status).toBe(200);
    const data = await response.json();
    expect(data.value).toBeDefined();
  });
});

单元测试: src/lib/{domain}/{file}.test.ts(与源文件放在一起)

import { describe, it, expect } from "bun:test";
import { myFunction } from "./my-file";

describe("myFunction", () => {
  it("should do expected behavior", () => {
    expect(myFunction()).toBe("expected");
  });
});

测试数据管理

数据库隔离

测试针对隔离的 Neon 分支运行。每次测试运行都会:

  1. 创建一个全新的、仅包含架构的分支
  2. 针对该分支运行测试
  3. 分支在 1 小时后自动删除

这样可确保测试不会影响生产数据。

并行测试隔离

测试默认并行运行。每个测试套件必须使用自己的测试数据,以避免冲突:

  • 使用不同的测试用户——每个 spec 文件都应创建电子邮件地址各不相同的唯一用户
  • 使用不同的资源——创建聊天、会话等的测试不应依赖共享状态
  • 无需清理——分支的 TTL 会自动处理清理
// auth.spec.ts - uses auth-specific test user
const testUser = await createTestUser({
  email: `auth-test-${uuid}@example.com`,
});

// chat.spec.ts - uses chat-specific test user
const testUser = await createTestUser({
  email: `chat-test-${uuid}@example.com`,
});

避免依赖全局状态或假设其他测试已在数据库中创建特定内容的模式。


常见模式

测试受保护的路由(Playwright)
test("should redirect unauthenticated user", async ({ page }) => {
  await page.goto("/protected-page");
  await expect(page).toHaveURL(/sign-in/);
});
测试错误状态(Playwright)
test("should show error for invalid input", async ({ page }) => {
  await page.goto("/form");
  await page.getByRole("button", { name: /submit/i }).click();

  await expect(page.getByText(/error|required/i)).toBeVisible({
    timeout: 5000,
  });
});
测试 API 响应(集成测试)

直接导入路由处理程序,让测试更简洁:

import { GET } from "@/app/api/endpoint/route";

it("should return 200 for valid request", async () => {
  const response = await GET();
  expect(response.status).toBe(200);
});

调试失败的测试

Playwright
bunx playwright test --headed              # Watch browser
bunx playwright test --debug               # Step through test
bunx playwright show-report                # View HTML report
集成测试/单元测试
bun test --only "test name"                # Run single test
bun test --watch                           # Re-run on changes
查看测试产物

失败的 Playwright 测试会将屏幕截图和跟踪记录保存到 test-results/。CI 失败时,请检查此文件夹。

评论

支持 Markdown