Skip to content

22.7 插件测试与调试

概述

测试与调试是插件开发过程中的重要环节,确保插件质量和稳定性。本章节将详细介绍 Claude Code 插件的测试策略、调试技术和最佳实践。

测试策略

1. 测试金字塔

插件测试应遵循测试金字塔原则:

    bash


              UI 测试
            /
          集成测试
        /
      单元测试


  * **单元测试** :测试最小的功能单元(函数、方法)
  * **集成测试** :测试插件内部组件之间的交互
  * **UI 测试** :测试插件与用户界面的交互

### 2\. 测试类型

#### 单元测试

单元测试关注插件的最小功能单元:

python
    typescript


    // 单元测试示例
    import { CalculatorTool } from './calculator-tool';

    describe('CalculatorTool', () => {
      let tool: CalculatorTool;

      beforeEach(() => {
        tool = new CalculatorTool();
      });

      describe('add', () => {
        it('should add two numbers', async () => {
          const result = await tool.execute({ operation: 'add', a: 2, b: 3 });
          expect(result).toBe(5);
        });

        it('should handle negative numbers', async () => {
          const result = await tool.execute({ operation: 'add', a: -2, b: 3 });
          expect(result).toBe(1);
        });
      });

      describe('validate', () => {
        it('should validate required parameters', () => {
          const result = tool.validate({});
          expect(result.valid).toBe(false);
          expect(result.error).toBe('Operation is required');
        });
      });
    });

#### 集成测试

集成测试关注插件内部组件之间的交互:

python
    typescript


    // 集成测试示例
    import { UserPlugin } from './user-plugin';
    import { DatabaseService } from './database-service';

    describe('UserPlugin', () => {
      let plugin: UserPlugin;
      let databaseService: DatabaseService;

      beforeEach(() => {
        databaseService = new DatabaseService();
        plugin = new UserPlugin({ databaseService });
      });

      it('should create user and store in database', async () => {
        const user = await plugin.createUser({ name: 'John', email: 'john@example.com' });

        const storedUser = await databaseService.getUser(user.id);
        expect(storedUser).toBeDefined();
        expect(storedUser.name).toBe('John');
      });
    });

#### 端到端测试

端到端测试关注插件与系统的交互:

python
    typescript


    // 端到端测试示例
    import { PluginManager } from '@claude-code/plugin-sdk';

    describe('UserPlugin E2E', () => {
      let pluginManager: PluginManager;

      beforeAll(async () => {
        pluginManager = new PluginManager();
        await pluginManager.loadPlugin('user-plugin');
      });

      afterAll(async () => {
        await pluginManager.unloadPlugin('user-plugin');
      });

      it('should create user through plugin API', async () => {
        const result = await pluginManager.executeCommand('user:create', {
          name: 'John',
          email: 'john@example.com'
        });

        expect(result.success).toBe(true);
        expect(result.data.user.id).toBeDefined();
      });
    });

## 测试框架与工具

### 1\. Jest

Jest 是一个流行的 JavaScript 测试框架:

    json


    // package.json
    {
      "devDependencies": {
        "jest": "^29.0.0",
        "@types/jest": "^29.0.0"
      },
      "scripts": {
        "test": "jest",
        "test:watch": "jest --watch",
        "test:coverage": "jest --coverage"
      }
    }

### 2\. Mocha

Mocha 是一个灵活的 JavaScript 测试框架:

    json


    // package.json
    {
      "devDependencies": {
        "mocha": "^10.0.0",
        "chai": "^4.0.0",
        "sinon": "^15.0.0"
      },
      "scripts": {
        "test": "mocha",
        "test:watch": "mocha --watch"
      }
    }

### 3\. Vitest

Vitest 是一个快速的 Vite-native 测试框架:

    json


    // package.json
    {
      "devDependencies": {
        "vitest": "^0.30.0"
      },
      "scripts": {
        "test": "vitest",
        "test:ui": "vitest --ui"
      }
    }

## 调试技术

### 1\. 日志调试

使用日志记录插件运行时信息:

python
    typescript


    // 日志调试示例
    class UserPlugin {
      async createUser(userData) {
        this.logger.debug('Creating user', { userData });

        try {
          const user = await this.database.create(userData);
          this.logger.info('User created', { userId: user.id });
          return user;
        } catch (error) {
          this.logger.error('Failed to create user', { error: error.message });
          throw error;
        }
      }
    }

### 2\. 断点调试

使用 VS Code 进行断点调试:

    json


    // .vscode/launch.json
    {
      "version": "0.2.0",
      "configurations": [
        {
          "name": "Debug Plugin",
          "type": "node",
          "request": "launch",
          "program": "${workspaceFolder}/src/plugin.ts",
          "args": ["--debug"],
          "outFiles": ["${workspaceFolder}/dist/**/*.js"]
        }
      ]
    }

### 3\. 远程调试

插件支持远程调试:

    typescript


    // 启用远程调试
    if (process.env.NODE_ENV === 'development') {
      require('inspector').open(9229, '0.0.0.0', true);
    }

## 测试环境搭建

### 1\. 测试数据库

使用测试数据库进行集成测试:

javascript
    typescript


    // 测试数据库配置
    const testConfig = {
      database: {
        type: 'sqlite',
        database: ':memory:',
        synchronize: true,
        logging: false
      }
    };

### 2\. 测试替身

使用测试替身模拟外部依赖:

python
    typescript


    // 使用 Sinon 模拟依赖
    import sinon from 'sinon';

    describe('UserPlugin', () => {
      it('should send welcome email', async () => {
        const emailService = { send: sinon.stub().resolves(true) };
        const plugin = new UserPlugin({ emailService });

        await plugin.createUser({ name: 'John', email: 'john@example.com' });

        expect(emailService.send.calledOnce).toBe(true);
        expect(emailService.send.calledWith('john@example.com', 'Welcome')).toBe(true);
      });
    });

### 3\. 测试数据

使用测试数据进行测试:

python
    typescript


    // 测试数据生成
    function generateTestUser() {
      return {
        name: `Test User ${Math.random().toString(36).substring(2, 10)}`,
        email: `test-${Math.random().toString(36).substring(2, 10)}@example.com`,
        password: 'password123'
      };
    }

    // 批量生成测试数据
    function generateTestUsers(count: number) {
      return Array.from({ length: count }, () => generateTestUser());
    }

## 持续集成

### 1\. GitHub Actions

使用 GitHub Actions 进行持续集成:

yaml
    yaml


    # .github/workflows/test.yml
    name: Test

    on: [push, pull_request]

    jobs:
      test:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - uses: actions/setup-node@v3
            with:
              node-version: 18
          - run: npm install
          - run: npm test
          - run: npm run lint

### 2\. GitLab CI

使用 GitLab CI 进行持续集成:

yaml
    yaml


    # .gitlab-ci.yml
    stages:
      - test

    unit_test:
      stage: test
      image: node:18
      script:
        - npm install
        - npm test

## 性能测试

### 1\. 基准测试

使用基准测试评估插件性能:

python
    typescript


    // 基准测试示例
    import { suite } from 'benchmark';
    import { CalculatorTool } from './calculator-tool';

    const tool = new CalculatorTool();

    const bench = new suite('CalculatorTool');

    bench
      .add('add', async (deferred) => {
        await tool.execute({ operation: 'add', a: 2, b: 3 });
        deferred.resolve();
      }, { defer: true })
      .add('multiply', async (deferred) => {
        await tool.execute({ operation: 'multiply', a: 2, b: 3 });
        deferred.resolve();
      }, { defer: true })
      .on('cycle', (event) => {
        console.log(String(event.target));
      })
      .run();

### 2\. 负载测试

使用负载测试评估插件在高并发下的性能:

python
    typescript


    // 负载测试示例
    import http from 'k6/http';
    import { sleep } from 'k6';

    export const options = {
      vus: 100,
      duration: '30s'
    };

    export default function () {
      http.post('http://localhost:3000/api/users', JSON.stringify({
        name: 'Test User',
        email: 'test@example.com'
      }), {
        headers: { 'Content-Type': 'application/json' }
      });
      sleep(1);
    }

## 测试覆盖率

### 1\. 覆盖率报告

使用 Jest 生成覆盖率报告:

    json


    // package.json
    {
      "scripts": {
        "test:coverage": "jest --coverage"
      }
    }

### 2\. 覆盖率阈值

设置覆盖率阈值确保测试质量:

    json


    // jest.config.js
    module.exports = {
      coverageThreshold: {
        global: {
          branches: 80,
          functions: 80,
          lines: 80,
          statements: 80
        }
      }
    };

## 调试技巧

### 1\. 日志级别

使用不同的日志级别调试:

javascript
    typescript


    // 日志级别配置
    const logger = createLogger({
      level: process.env.NODE_ENV === 'development' ? 'debug' : 'info'
    });

### 2\. 调试工具

使用 Chrome DevTools 调试:

    bash


    # 启动调试模式
    node --inspect-brk plugin.js

### 3\. 错误追踪

使用 Sentry 进行错误追踪:

python
    typescript


    // Sentry 配置
    import * as Sentry from '@sentry/node';

    Sentry.init({
      dsn: 'your-sentry-dsn',
      environment: process.env.NODE_ENV
    });

## 最佳实践

### 1\. 测试驱动开发

采用测试驱动开发(TDD):

  1. 编写失败的测试
  2. 编写足够的代码使测试通过
  3. 重构代码
  4. 重复

2. 测试隔离

确保测试之间相互隔离:

javascript
    typescript


    // 测试隔离示例
    beforeEach(() => {
      // 重置状态
      database.clear();
      cache.clear();
    });

### 3\. 测试命名

使用清晰的测试命名规范:

javascript
    typescript


    // 测试命名示例
    describe('UserPlugin', () => {
      describe('createUser', () => {
        it('should create user with valid data', async () => {
          // ...
        });

        it('should throw error with invalid data', async () => {
          // ...
        });
      });
    });

### 4\. 测试文档

为测试编写文档:

javascript
    typescript


    // 测试文档示例
    /**
     * 测试用户创建功能
     * 1. 验证必填字段
     * 2. 验证数据存储
     * 3. 验证错误处理
     */
    describe('UserPlugin.createUser', () => {
      // ...
    });

## 常见问题

### Q: 如何测试异步代码?

A: 使用 async/await 测试异步代码:

    typescript


    it('should handle async operation', async () => {
      const result = await asyncFunction();
      expect(result).toBe(true);
    });

### Q: 如何测试错误情况?

A: 使用 expect.toThrow 测试错误情况:

    typescript


    it('should throw error with invalid data', async () => {
      await expect(plugin.createUser({})).rejects.toThrow('Invalid data');
    });

### Q: 如何测试定时器?

A: 使用 Jest 的定时器模拟:

    typescript


    it('should execute after delay', async () => {
      jest.useFakeTimers();

      const callback = jest.fn();
      setTimeout(callback, 1000);

      jest.runAllTimers();
      expect(callback).toHaveBeenCalled();
    });

## 总结

测试与调试是插件开发过程中的重要环节。通过采用合适的测试策略、使用测试框架和工具、遵循最佳实践,可以确保插件的质量和稳定性。

下一章将介绍插件性能优化技术,帮助开发者提高插件性能和响应性。

基于 MIT 许可发布 | 永久导航