mcpField
T
test-coverage-improver

test-coverage-improver

github.com/onewave-ai测试与质量393296 次安装1 周前更新
代码仓库

关于 test-coverage-improver

Test Coverage Improver 是用于发现测试缺口并补充测试、提升覆盖率的技能,提供覆盖率报告命令、测试示例以及分支和边界情况清单。

主要功能

  1. 01生成覆盖率报告
  2. 02优先处理测试缺口
  3. 03单元与异步测试示例
  4. 04模拟与组件测试示例
  5. 05分支和边界情况清单

适用场景

  1. 01查找未覆盖的关键代码路径
  2. 02为错误处理和边界情况添加测试
  3. 03提升 Jest 或 Vitest 项目的覆盖率

安装

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

$npx skills add https://github.com/onewave-ai/claude-skills --skill test-coverage-improver

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

详细介绍

测试覆盖率改进器

说明

提高测试覆盖率时:

  1. 运行覆盖率报告,找出覆盖缺口
  2. 优先关注关键和复杂的代码路径
  3. 编写测试,覆盖未覆盖的代码
  4. 验证覆盖率已提高

生成覆盖率报告

# Jest
npx jest --coverage

# Vitest
npx vitest --coverage

# NYC (Istanbul) for any test runner
npx nyc npm test

# View HTML report
open coverage/lcov-report/index.html

覆盖率目标

类型最低良好优秀
行70%80%90%+
分支60%75%85%+
函数70%80%90%+
语句70%80%90%+

测试模板

单元测试(Jest/Vitest)
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { calculateTotal, formatCurrency } from './utils';

describe('calculateTotal', () => {
  it('should sum all item prices', () => {
    const items = [
      { price: 10, quantity: 2 },
      { price: 5, quantity: 1 },
    ];
    expect(calculateTotal(items)).toBe(25);
  });

  it('should return 0 for empty array', () => {
    expect(calculateTotal([])).toBe(0);
  });

  it('should handle decimal prices', () => {
    const items = [{ price: 10.99, quantity: 1 }];
    expect(calculateTotal(items)).toBeCloseTo(10.99);
  });
});
测试异步函数
describe('fetchUser', () => {
  it('should return user data', async () => {
    const user = await fetchUser(1);
    expect(user).toEqual({
      id: 1,
      name: expect.any(String),
      email: expect.stringContaining('@'),
    });
  });

  it('should throw for non-existent user', async () => {
    await expect(fetchUser(999)).rejects.toThrow('User not found');
  });
});
模拟依赖项
import { vi } from 'vitest';
import { sendEmail } from './email';
import { createUser } from './user';

vi.mock('./email', () => ({
  sendEmail: vi.fn().mockResolvedValue({ success: true }),
}));

describe('createUser', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should send welcome email after creating user', async () => {
    await createUser({ name: 'John', email: '[email protected]' });

    expect(sendEmail).toHaveBeenCalledWith({
      to: '[email protected]',
      template: 'welcome',
    });
  });
});
React 组件测试
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { Button } from './Button';

describe('Button', () => {
  it('should render children', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByText('Click me')).toBeInTheDocument();
  });

  it('should call onClick when clicked', async () => {
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>Click</Button>);

    await userEvent.click(screen.getByRole('button'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('should be disabled when loading', () => {
    render(<Button isLoading>Submit</Button>);
    expect(screen.getByRole('button')).toBeDisabled();
  });
});
API 路由测试
import { createMocks } from 'node-mocks-http';
import handler from './api/users';

describe('GET /api/users', () => {
  it('should return users list', async () => {
    const { req, res } = createMocks({ method: 'GET' });

    await handler(req, res);

    expect(res._getStatusCode()).toBe(200);
    expect(JSON.parse(res._getData())).toHaveProperty('users');
  });
});

分支覆盖率检查清单

确保测试覆盖:

  • If/else 分支
  • 三元运算符
  • Switch 分支(包括 default)
  • Try/catch 块
  • 提前返回
  • 空值合并(??)
  • 可选链结果(?.)
  • 循环条件(0、1、多次迭代)

覆盖率配置

// vitest.config.ts
export default {
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html', 'lcov'],
      exclude: [
        'node_modules/',
        '**/*.d.ts',
        '**/*.test.ts',
        '**/types/',
      ],
      thresholds: {
        lines: 80,
        branches: 75,
        functions: 80,
        statements: 80,
      },
    },
  },
};

测试优先级

  1. 关键路径:身份验证、支付、数据变更
  2. 复杂逻辑:算法、状态机、计算
  3. 错误处理程序:Catch 块、错误边界
  4. 边缘情况:空数组、null 值、边界条件
  5. 集成点:API 调用、数据库查询

评论

支持 Markdown