---
title: 测试文档
order: 4
category: pro
---

# PisellSort 测试文档

## 测试策略

PisellSort 组件的测试应覆盖以下几个方面：

1. **基础渲染**: 组件能否正常渲染
2. **属性传递**: 属性是否正确传递给子组件
3. **表单集成**: Form 集成是否正常工作
4. **交互行为**: 用户交互是否符合预期
5. **边界情况**: 异常输入的处理

## 测试用例

### 1. 基础渲染测试

#### 1.1 默认渲染

**测试目标**: 验证组件能否正常渲染

```
import { render } from '@testing-library/react';
import { PisellSort } from '@pisell/materials';

test('应该正常渲染', () => {
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
  ];

  const { container } = render(<PisellSort list={sortList} />);
  expect(container.firstChild).toBeInTheDocument();
});
```

#### 1.2 空列表渲染

**测试目标**: 验证空列表时的渲染

```
test('应该能渲染空列表', () => {
  const { container } = render(<PisellSort list={[]} />);
  expect(container.firstChild).toBeInTheDocument();
});
```

### 2. 属性传递测试

#### 2.1 自定义字段名

**测试目标**: 验证自定义字段名是否生效

```
test('应该支持自定义字段名', () => {
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
  ];

  const { container } = render(
    <PisellSort list={sortList} name="customSort" />
  );

  // 验证表单项的 name 属性
  const formItem = container.querySelector('.ant-form-item');
  expect(formItem).toBeInTheDocument();
});
```

#### 2.2 样式属性传递

**测试目标**: 验证样式属性是否正确传递

```
test('应该支持自定义样式', () => {
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
  ];

  const customStyle = { backgroundColor: 'red' };
  const { container } = render(
    <PisellSort list={sortList} style={customStyle} />
  );

  const form = container.querySelector('.ant-form');
  expect(form).toHaveStyle(customStyle);
});
```

### 3. 交互测试

#### 3.1 排序值变化

**测试目标**: 验证排序值变化时的回调

```
import { fireEvent, render, screen } from '@testing-library/react';

test('应该在排序改变时触发回调', async () => {
  const handleChange = jest.fn();
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
  ];

  render(
    <PisellSort
      list={sortList}
      onChange={handleChange}
    />
  );

  // 模拟点击排序按钮
  const sortButton = screen.getByRole('button');
  fireEvent.click(sortButton);

  // 验证回调被调用
  // 注意：这里需要根据实际的 Sort 组件实现来编写测试
});
```

#### 3.2 受控模式

**测试目标**: 验证受控模式下的值更新

```
test('应该支持受控模式', () => {
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
  ];

  const { rerender } = render(
    <PisellSort list={sortList} value="price_asc" />
  );

  // 更新 value
  rerender(<PisellSort list={sortList} value="price_desc" />);

  // 验证值已更新
  // 注意：需要根据实际的 Sort 组件实现来验证
});
```

### 4. 表单集成测试

#### 4.1 表单值获取

**测试目标**: 验证能否正确获取表单值

```
test('应该能通过 Form 获取排序值', async () => {
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
  ];

  const FormWrapper = () => {
    const [form] = Form.useForm();

    return (
      <>
        <PisellSort list={sortList} name="sort" />
        <button onClick={() => {
          const values = form.getFieldsValue();
          console.log(values);
        }}>
          获取值
        </button>
      </>
    );
  };

  const { getByText } = render(<FormWrapper />);

  // 模拟获取表单值
  const button = getByText('获取值');
  fireEvent.click(button);
});
```

### 5. 边界情况测试

#### 5.1 缺少必需属性

**测试目标**: 验证缺少 list 属性时的处理

```
test('应该能处理缺少 list 属性的情况', () => {
  // @ts-expect-error 故意不传 list 属性
  const { container } = render(<PisellSort />);
  expect(container.firstChild).toBeInTheDocument();
});
```

#### 5.2 无效的排序类型

**测试目标**: 验证无效排序类型的处理

```
test('应该能处理无效的排序类型', () => {
  const sortList = [
    {
      // @ts-expect-error 故意使用无效类型
      type: 'invalid',
      label: '无效字段',
      name: 'invalid',
      isCustom: false,
      columnKey: 'invalid',
    },
  ];

  const { container } = render(<PisellSort list={sortList} />);
  expect(container.firstChild).toBeInTheDocument();
});
```

## 快照测试

### 基础快照

```
test('应该匹配快照', () => {
  const sortList = [
    {
      type: 'number',
      label: '价格',
      name: 'price',
      isCustom: false,
      columnKey: 'price',
    },
    {
      type: 'date',
      label: '创建时间',
      name: 'created_at',
      isCustom: false,
      columnKey: 'created_at',
    },
  ];

  const { container } = render(<PisellSort list={sortList} />);
  expect(container).toMatchSnapshot();
});
```

## 测试覆盖率目标

- **语句覆盖率**: ≥ 80%
- **分支覆盖率**: ≥ 80%
- **函数覆盖率**: ≥ 80%
- **行覆盖率**: ≥ 80%

## 运行测试

```bash
# 运行所有测试
pnpm test

# 运行单个组件测试
pnpm test pisellSort

# 运行测试并生成覆盖率报告
pnpm test:coverage

# 监听模式运行测试
pnpm test:watch
```

## 测试工具

- **测试框架**: Jest
- **测试库**: @testing-library/react
- **断言库**: Jest (内置)
- **Mock 工具**: Jest (内置)

## 注意事项

1. **异步测试**: 涉及异步操作时使用 `async/await` 或 `waitFor`
2. **清理工作**: 每个测试后清理 DOM 和状态
3. **隔离性**: 每个测试应该独立，不依赖其他测试
4. **可读性**: 测试描述应该清晰明确
5. **实际场景**: 测试应该模拟真实使用场景

## 持续集成

测试应该集成到 CI/CD 流程中：

1. **PR 检查**: 每个 PR 必须通过所有测试
2. **覆盖率门槛**: 维持或提高测试覆盖率
3. **性能监控**: 监控测试执行时间
4. **失败通知**: 测试失败时及时通知

## 相关资源

- [Jest 文档](https://jestjs.io/)
- [Testing Library 文档](https://testing-library.com/docs/react-testing-library/intro/)
- [Ant Design 测试指南](https://ant.design/docs/react/testing-cn)
