重置高压发生器功能测试方案.md 13 KB

重置高压发生器功能 E2E 测试方案

功能概述

重置高压发生器功能允许用户通过界面上的RESET按钮重置设备参数,将高压发生器恢复到初始状态。

功能实现分析

数据流

UI Button (RESET)
  ↓
handleResetParameters()
  ↓
dispatch(resetDevices()) [Redux Thunk]
  ↓
resetAllDevices() [API]
  ↓
POST /auth/device/action
  ↓
设备重置完成

技术架构

  • UI层: ContentAreaLarge.tsx 组件
  • 状态管理: Redux Toolkit (deviceSlice)
  • 异步处理: createAsyncThunk
  • API调用: axios + interceptor

Redux状态管理

interface DeviceState {
  status: 'idle' | 'loading' | 'succeeded' | 'failed';
  error: string | null;
  deviceError: string | null;
}

API请求格式

POST /auth/device/action
{
  "deviceUri": "DIOS/DEVICE/Generator",
  "reqName": "RESET",
  "reqParam": "",
  "reqTransaction": "",
  "reqClientID": ""
}

API响应格式

成功响应:

{
  "code": "0x000000",
  "description": "Success",
  "data": {}
}

失败响应:

{
  "code": "0x010001",
  "description": "设备通信失败",
  "solution": "检查设备连接"
}

测试套件设计

测试套件:重置高压发生器功能

文件路径: cypress/e2e/exam/reset-generator.cy.ts


TC-RESET-01: 成功重置设备

测试目标: 验证正常重置流程

前置条件:

  • 已登录系统
  • 已进入检查页面
  • Mock所有依赖API(quota、i18n等)

测试步骤:

  1. Mock设备重置API成功响应
  2. 定位RESET按钮
  3. 验证按钮初始状态为可用
  4. 点击RESET按钮
  5. 验证按钮变为禁用状态(loading)
  6. 等待API调用完成
  7. 验证按钮恢复为可用状态
  8. 验证Redux状态更新为'succeeded'

验证点:

  • ✅ 按钮可点击
  • ✅ 点击后按钮禁用(disabled=true)
  • ✅ API调用成功(code='0x000000')
  • ✅ 按钮恢复可用状态
  • ✅ Redux状态: status='succeeded'
  • ✅ 无错误提示

Mock配置:

cy.intercept('POST', '/auth/device/action', (req) => {
  if (req.body.reqName === 'RESET') {
    req.reply({
      statusCode: 200,
      body: {
        code: '0x000000',
        description: 'Success',
        data: {}
      }
    });
  }
}).as('resetDevice');

TC-RESET-02: API失败处理

测试目标: 验证重置失败时的错误处理

前置条件:

  • 已登录系统
  • 已进入检查页面

测试步骤:

  1. Mock设备重置API失败响应
  2. 点击RESET按钮
  3. 等待API调用完成
  4. 验证Redux状态更新为'failed'
  5. 验证错误信息存储到state.error
  6. 验证按钮恢复可用
  7. 验证控制台输出错误日志

验证点:

  • ✅ API返回非'0x000000'错误码
  • ✅ Redux状态: status='failed'
  • ✅ 错误信息存储到state.error
  • ✅ 按钮恢复可用
  • ✅ 控制台输出错误日志

Mock配置:

cy.intercept('POST', '/auth/device/action', {
  statusCode: 200,
  body: {
    code: '0x010001',
    description: '设备通信失败',
    solution: '检查设备连接'
  }
}).as('resetDeviceFail');

TC-RESET-03: 按钮禁用状态管理

测试目标: 验证loading期间按钮状态管理

前置条件:

  • 已登录系统
  • 已进入检查页面

测试步骤:

  1. Mock设备重置API延迟响应(2秒)
  2. 点击RESET按钮
  3. 验证按钮立即禁用
  4. 验证disabled属性为true
  5. 等待1秒,验证按钮仍然禁用
  6. 等待API响应完成
  7. 验证按钮恢复可用

验证点:

  • ✅ 点击后按钮立即禁用
  • ✅ disabled属性为true
  • ✅ 响应前按钮保持禁用
  • ✅ 响应后按钮恢复可用
  • ✅ Redux状态正确转换: idle → loading → succeeded

Mock配置:

cy.intercept('POST', '/auth/device/action', (req) => {
  req.reply({
    statusCode: 200,
    body: {
      code: '0x000000',
      description: 'Success',
      data: {}
    },
    delay: 2000
  });
}).as('resetDeviceDelay');

TC-RESET-04: 网络错误处理

测试目标: 验证网络异常场景的错误处理

前置条件:

  • 已登录系统
  • 已进入检查页面

测试步骤:

  1. Mock网络错误
  2. 点击RESET按钮
  3. 等待错误发生
  4. 验证Redux状态更新为'failed'
  5. 验证错误信息被捕获
  6. 验证按钮恢复可用
  7. 验证用户可以重试

验证点:

  • ✅ 捕获网络错误
  • ✅ Redux状态: status='failed'
  • ✅ 错误信息存储
  • ✅ 状态恢复正常
  • ✅ 用户可重试操作

Mock配置:

cy.intercept('POST', '/auth/device/action', {
  forceNetworkError: true
}).as('resetDeviceNetworkError');

TC-RESET-05: 防止重复点击

测试目标: 验证loading状态下防止重复操作

前置条件:

  • 已登录系统
  • 已进入检查页面

测试步骤:

  1. Mock设备重置API延迟响应(3秒)
  2. 点击RESET按钮
  3. 立即再次尝试点击按钮
  4. 验证第二次点击无效
  5. 验证只发送了一次API请求
  6. 等待第一次请求完成
  7. 验证可以再次点击

验证点:

  • ✅ loading时按钮禁用
  • ✅ 再次点击无效
  • ✅ 只发送一次API请求
  • ✅ 完成后才能再次点击
  • ✅ 防抖机制有效

Mock配置:

let requestCount = 0;
cy.intercept('POST', '/auth/device/action', (req) => {
  requestCount++;
  req.reply({
    statusCode: 200,
    body: {
      code: '0x000000',
      description: 'Success',
      data: {}
    },
    delay: 3000
  });
}).as('resetDeviceMultiple');

// 验证requestCount === 1

Page Object Model 设计

ExamPage 扩展

文件: cypress/support/pageObjects/ExamPage.ts

class ExamPage {
  // ... 现有方法

  /**
   * 获取重置高压发生器按钮
   */
  getResetGeneratorButton() {
    return cy.get('[data-testid="reset-generator-btn"]');
  }

  /**
   * 点击重置按钮
   */
  clickResetGenerator() {
    this.getResetGeneratorButton().click();
  }

  /**
   * 验证重置按钮为启用状态
   */
  verifyResetButtonEnabled() {
    this.getResetGeneratorButton()
      .should('be.visible')
      .should('not.be.disabled');
  }

  /**
   * 验证重置按钮为禁用状态
   */
  verifyResetButtonDisabled() {
    this.getResetGeneratorButton()
      .should('be.visible')
      .should('be.disabled');
  }

  /**
   * 等待重置操作完成
   */
  waitForResetComplete() {
    cy.wait('@resetDevice');
    this.verifyResetButtonEnabled();
  }

  /**
   * 验证Redux设备状态
   * @param expectedStatus - 期望的状态: 'idle' | 'loading' | 'succeeded' | 'failed'
   */
  verifyDeviceStatus(expectedStatus: string) {
    cy.window().its('store').invoke('getState')
      .its('device').its('status')
      .should('eq', expectedStatus);
  }

  /**
   * 验证设备错误信息
   * @param expectedError - 期望的错误信息,null表示无错误
   */
  verifyDeviceError(expectedError: string | null) {
    cy.window().its('store').invoke('getState')
      .its('device').its('error')
      .should('eq', expectedError);
  }
}

Mock Handlers 设计

文件结构

文件: cypress/support/mock/handlers/deviceActions.ts

/**
 * Mock设备重置成功响应
 */
export const mockResetDeviceSuccess = () => {
  cy.intercept('POST', '/auth/device/action', (req) => {
    if (req.body.reqName === 'RESET') {
      req.reply({
        statusCode: 200,
        body: {
          code: '0x000000',
          description: 'Success',
          data: {}
        }
      });
    }
  }).as('resetDevice');
};

/**
 * Mock设备重置失败响应
 * @param errorCode - 错误码,默认为'0x010001'
 * @param description - 错误描述
 */
export const mockResetDeviceFail = (
  errorCode: string = '0x010001',
  description: string = '设备通信失败'
) => {
  cy.intercept('POST', '/auth/device/action', {
    statusCode: 200,
    body: {
      code: errorCode,
      description: description,
      solution: '检查设备连接'
    }
  }).as('resetDeviceFail');
};

/**
 * Mock网络错误
 */
export const mockResetDeviceNetworkError = () => {
  cy.intercept('POST', '/auth/device/action', (req) => {
    if (req.body.reqName === 'RESET') {
      req.reply({ forceNetworkError: true });
    }
  }).as('resetDeviceNetworkError');
};

/**
 * Mock设备重置延迟响应
 * @param delayMs - 延迟毫秒数
 */
export const mockResetDeviceDelay = (delayMs: number) => {
  cy.intercept('POST', '/auth/device/action', (req) => {
    if (req.body.reqName === 'RESET') {
      req.reply({
        statusCode: 200,
        body: {
          code: '0x000000',
          description: 'Success',
          data: {}
        },
        delay: delayMs
      });
    }
  }).as('resetDeviceDelay');
};

/**
 * Mock所有设备操作(用于其他测试场景)
 */
export const mockAllDeviceActions = () => {
  cy.intercept('POST', '/auth/device/action', (req) => {
    req.reply({
      statusCode: 200,
      body: {
        code: '0x000000',
        description: 'Success',
        data: {}
      }
    });
  }).as('deviceAction');
};

UI组件修改

ContentAreaLarge.tsx 修改点

在RESET按钮添加测试标识:

<Button
  data-testid="reset-generator-btn"  // 新增测试标识
  style={{ width: '1.5rem', height: '1.5rem' }}
  icon={
    <Icon
      module="module-exam"
      name="btn_ResetGenerator"
      userId="base"
      theme="default"
      size="2x"
      state="normal"
    />
  }
  title="重置参数"
  onClick={handleResetParameters}
  disabled={isResetting}
/>

测试数据准备

前置条件Mock

每个测试用例都需要以下Mock:

  1. 多语言资源(必需)

    mockI18nSuccess('zh_CN');           // 获取中文翻译资源
    mockGetLanguageListSuccess();        // 获取语言列表
    mockAllRequiredAPIs('zh_CN');       // Mock软件信息和日志API
    
    1. 登录相关
    2. 用户认证 - LoginPage已处理
    3. 权限检查 - LoginPage已处理

    4. 配额检查

    5. Quota API Mock - LoginPage已处理

    6. 检查页面数据

    7. 患者信息 - WorklistPage已处理

    8. 体位列表 - 进入检查页面后自动加载

    9. APR配置 - 进入检查页面后自动加载

    Redux State初始化

    // 测试前重置Redux状态
    beforeEach(() => {
    cy.window().its('store').invoke('dispatch', {
    type: 'device/resetState'
    });
    });
    

测试执行计划

第一阶段:核心功能测试(优先级高)

  • ✅ TC-RESET-01: 成功重置设备
  • ✅ TC-RESET-02: API失败处理
  • ✅ TC-RESET-03: 按钮禁用状态管理

第二阶段:异常处理测试(优先级中)

  • ✅ TC-RESET-04: 网络错误处理
  • ✅ TC-RESET-05: 防止重复点击

第三阶段:集成测试(优先级低)

  • 与其他功能的集成测试
  • 性能测试

测试覆盖率目标

  • 功能覆盖: 100% - 所有重置相关功能
  • 代码覆盖: 90%+ - 核心业务逻辑代码
  • 边界测试: 包含成功、失败、网络异常等场景
  • 状态测试: 验证所有Redux状态转换

验收标准

功能验收

  • ✅ 所有5个测试用例通过
  • ✅ 成功和失败场景都能正确处理
  • ✅ UI状态与Redux状态同步
  • ✅ 错误处理机制完善
  • ✅ 按钮状态管理正确

性能验收

  • ✅ 按钮响应及时(<100ms)
  • ✅ API调用正确(请求体符合规范)
  • ✅ loading状态管理准确
  • ✅ 无内存泄漏

用户体验验收

  • ✅ 按钮禁用时有视觉反馈
  • ✅ 操作结果有明确提示
  • ✅ 错误时可重试
  • ✅ 防止误操作

常见错误场景

错误码对照表

错误码 描述 解决方案
0x000000 成功 -
0x010001 设备通信失败 检查设备连接
0x010002 设备忙碌 等待设备空闲后重试
0x010003 参数错误 检查请求参数
0x010004 超时 检查网络连接

附录

相关文件清单

新建文件:

  1. docs/测试/重置高压发生器功能测试方案.md - 本文档
  2. cypress/e2e/exam/reset-generator.cy.ts - 测试用例
  3. cypress/support/mock/handlers/deviceActions.ts - Mock处理器

修改文件:

  1. cypress/support/pageObjects/ExamPage.ts - 扩展POM
  2. src/pages/exam/ContentAreaLarge.tsx - 添加data-testid

API接口文档

接口: POST /auth/device/action

请求参数:

interface DeviceActionMessage {
  deviceUri: string;      // 设备URI
  reqName: string;        // 请求名称
  reqParam: string;       // 请求参数
  reqTransaction: string; // 事务ID
  reqClientID: string;    // 客户端ID
}

响应格式:

interface DeviceActionResponse {
  code: string;          // 状态码
  description: string;   // 描述信息
  solution?: string;     // 解决方案(可选)
  data?: any;           // 响应数据(可选)
}

文档版本

  • 版本: 1.0.0
  • 创建日期: 2025-10-10
  • 最后更新: 2025-10-10
  • 作者: Cline AI Assistant
  • 审核: 待审核