mcpField
T
test-generator

test-generator

github.com/oimiragieo测试与质量44122 次安装17 周前更新
代码仓库

关于 test-generator

面向开发流程的测试生成技能,可根据规格、代码和项目既有约定生成测试,并检查覆盖与可运行性。适用于需要补充单元、集成、API 或端到端测试的开发者。

主要功能

  1. 01按项目测试惯例生成测试
  2. 02支持单元、集成、API 和端到端测试
  3. 03分析边界条件与错误场景
  4. 04检查语法、运行配置和覆盖情况

适用场景

  1. 01为新组件或函数补充单元测试
  2. 02为 API 端点创建测试
  3. 03为用户流程编写端到端测试
  4. 04检查现有代码的测试覆盖

安装

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

$npx skills add https://github.com/oimiragieo/agent-studio --skill test-generator

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

commands/
test-generator.md
hooks/
post-execute.cjs
pre-execute.cjs
references/
research-requirements.md
rules/
test-generator.md
schemas/
input.schema.json
output.schema.json
scripts/
main.cjs
templates/
implementation-template.md

详细介绍

模式:认知/提示词驱动 — 不使用独立的实用脚本;通过 Agent 上下文使用。

测试生成技能 - 根据规格说明、组件和 API 端点生成测试代码,并遵循项目的测试模式和约定。 - 为新组件生成测试 - 为 API 端点创建测试 - 为用户流程生成 E2E 测试 - 创建集成测试 - 为现有代码补充测试覆盖
步骤 1:确定测试类型

判断需要哪种类型的测试:

  • 单元测试:组件/函数测试
  • 集成测试:服务/API 集成
  • E2E 测试:完整用户流程测试
  • API 测试:端点测试
步骤 2:分析目标代码

检查要测试的代码(使用并行 Read/Grep/Glob):

  • 阅读组件/函数代码
  • 确定测试用例
  • 了解依赖项
  • 留意边缘情况
步骤 3:分析测试模式

检查现有测试:

  • 阅读类似的测试文件
  • 确定测试模式
  • 留意测试框架的用法
  • 了解模拟策略
步骤 4:生成测试代码

遵循现有模式创建测试:

  • 使用适当的测试框架
  • 遵循项目约定
  • 确保覆盖全面
  • 添加边缘情况和错误场景
步骤 5:覆盖率分析

生成测试后,分析覆盖率:

  1. 检查生成的测试是否覆盖所有要求:

    • 验证是否测试了所有函数/方法
    • 检查是否覆盖所有分支(if/else、switch 等)
    • 确保测试了所有边缘情况
    • 验证是否覆盖了错误场景
  2. 验证测试能否运行:

    • 检查测试语法是否有效
    • 验证导入是否正确
    • 确保测试框架已正确配置
    • 验证测试设置/拆卸是否正确
  3. 报告覆盖率百分比:

    • 计算行覆盖率(如可行)
    • 计算分支覆盖率(如可行)
    • 报告未覆盖的代码路径
    • 为未覆盖区域建议补充测试
  4. 覆盖率验证清单:

    • 所有公开函数/方法都有测试
    • 已测试所有错误路径
    • 已覆盖所有边缘情况
    • 测试语法有效
    • 测试可成功执行
    • 覆盖率达到项目阈值(如有定义) </execution_process>
**单元测试(React 组件)**
import { render, screen, waitFor } from '@testing-library/react'
import { describe, it, expect, vi } from 'vitest'
import { UserProfile } from './user-profile'

describe('UserProfile', () => {
  it('renders user information', async () => {
    const mockUser = { id: '1', name: 'John', email: '[email protected]' }

    render(<UserProfile user={mockUser} />)

    await waitFor(() => {
      expect(screen.getByText('John')).toBeInTheDocument()
      expect(screen.getByText('[email protected]')).toBeInTheDocument()
    })
  })

  it('handles loading state', () => {
    render(<UserProfile user={null} loading />)
    expect(screen.getByTestId('loading')).toBeInTheDocument()
  })

  it('handles error state', () => {
    render(<UserProfile user={null} error="Failed to load" />)
    expect(screen.getByText('Failed to load')).toBeInTheDocument()
  })
})

</code_example>

<code_example> 集成测试(API)

import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { createTestClient } from './test-client';

describe('Users API', () => {
  let client: TestClient;

  beforeAll(() => {
    client = createTestClient();
  });

  afterAll(async () => {
    await client.cleanup();
  });

  it('creates a user', async () => {
    const response = await client.post('/api/users', {
      email: '[email protected]',
      name: 'Test User',
    });

    expect(response.status).toBe(201);
    expect(response.data).toHaveProperty('id');
    expect(response.data.email).toBe('[email protected]');
  });

  it('validates required fields', async () => {
    const response = await client.post('/api/users', {});

    expect(response.status).toBe(400);
    expect(response.data).toHaveProperty('errors');
  });
});

</code_example>

<code_example> E2E 测试(Cypress)

describe('User Authentication Flow', () => {
  beforeEach(() => {
    cy.visit('/login');
  });

  it('allows user to login', () => {
    cy.get('[data-testid="email-input"]').type('[email protected]');
    cy.get('[data-testid="password-input"]').type('password123');
    cy.get('[data-testid="login-button"]').click();

    cy.url().should('include', '/dashboard');
    cy.get('[data-testid="user-menu"]').should('be.visible');
  });

  it('shows error for invalid credentials', () => {
    cy.get('[data-testid="email-input"]').type('[email protected]');
    cy.get('[data-testid="password-input"]').type('wrong');
    cy.get('[data-testid="login-button"]').click();

    cy.get('[data-testid="error-message"]')
      .should('be.visible')
      .and('contain', 'Invalid credentials');
  });
});

</code_example>

**与 Developer Agent 集成**: - 在开发过程中生成测试 - 确保测试覆盖率 - 验证实现

与 QA Agent 集成:

  • 创建全面的测试套件
  • 生成测试计划
  • 验证测试质量

<best_practices>

  1. 遵循模式:匹配现有测试结构
  2. 全面覆盖:测试正常流程和边缘情况
  3. 清晰的测试名称:使用描述性测试说明
  4. 隔离测试:每个测试都应相互独立
  5. 模拟依赖项:使用适当的模拟策略 </best_practices>
**命令示例**:
# Generate tests for a file
node .claude/skills/test-generator/scripts/main.cjs src/components/UserProfile.tsx

# The tool will analyze the file and generate appropriate tests

</usage_example>

铁律

  1. 始终先分析现有测试模式和框架约定,再生成任何测试代码
  2. 绝不生成检查实现细节的测试——只测试公开行为和输出
  3. 始终包含边缘情况:对每个被测单元测试 null/undefined 输入、边界值和错误场景
  4. 绝不生成具有共享可变状态的测试——使用 beforeEach/afterEach 隔离每个测试
  5. 始终验证生成的测试语法有效且可运行,然后再标记生成完成

反模式

反模式为什么会失败正确做法
测试实现细节即使行为没有变化,重构后测试也会失败测试公开 API 的行为和可观察到的输出
测试主体中没有断言测试总是通过,无法发现任何问题为每个测试用例添加明确的断言
测试间共享可变状态测试会因执行顺序不同而失败使用 beforeEach/afterEach 实现完全隔离
断言中使用魔法数字预期值不明确,测试脆弱使用命名常量或描述性测试数据
缺少错误路径测试覆盖率不足,生产环境中会出现静默故障同时测试成功和失败场景

记忆协议(强制)

开始前: 阅读 .claude/context/memory/learnings.md

完成后:

  • 新模式 -> .claude/context/memory/learnings.md
  • 发现问题 -> .claude/context/memory/issues.md
  • 做出决策 -> .claude/context/memory/decisions.md

假设任务可能中断:如果没有记录在记忆中,就等于没有发生。

评论

支持 Markdown