xlx_teacher_app/.task/dom-rendering-test-guide.md

11 KiB
Raw Blame History

DOM 渲染功能测试指南

🎯 测试目标

验证从 Konva Canvas 迁移到 DOM 渲染后,所有功能正常工作,特别是在微信小程序环境中。

🔧 测试环境

浏览器环境

  • Chrome/Edge (开发调试)
  • Safari (iOS 兼容性)
  • 微信开发者工具 (小程序环境)

设备

  • 桌面端 (鼠标操作)
  • 移动端 (触摸操作)
  • 平板 (双指缩放)

功能测试清单

1. 基础绘制功能

1.1 矩形工具

测试步骤:

  1. 选择矩形工具
  2. 在画布上按下鼠标/手指
  3. 拖动到目标位置
  4. 释放鼠标/手指

预期结果:

  • 矩形正确绘制
  • 矩形位置、大小准确
  • 矩形颜色、边框宽度符合设置
  • 可以绘制负方向矩形(从右下往左上拖)

测试数据:

// 预期数据结构
{
  id: "shape_xxx",
  type: "rect",
  x: 100,
  y: 100,
  width: 200,
  height: 150,
  stroke: "#ff0000",
  strokeWidth: 2
}

1.2 笔工具(线条)

测试步骤:

  1. 选择笔工具
  2. 在画布上绘制任意路径
  3. 释放鼠标/手指

预期结果:

  • 线条流畅,无断点
  • 线条颜色、粗细符合设置
  • 线条端点圆滑lineCap: round
  • 快速绘制时不丢失点

测试数据:

{
  id: "shape_xxx",
  type: "line",
  x: 0,
  y: 0,
  points: [100, 100, 105, 102, 110, 105, ...],
  stroke: "#ff0000",
  strokeWidth: 2
}

1.3 文本注释

测试步骤:

  1. 选择文本工具
  2. 点击画布位置
  3. 输入文本内容
  4. 确认

预期结果:

  • 弹出输入框
  • 文本正确显示在点击位置
  • 文本大小、颜色符合设置
  • 支持多行文本
  • 支持特殊字符

测试用例:

  • 普通文本: "扣1分"
  • 数字: "123"
  • 特殊字符: "+5", "-2"
  • 多行文本: "第一行\n第二行"

1.4 特殊标记

正确标记 ✓:

  • 显示红色勾号
  • 位置准确
  • 大小适中20x20

错误标记 ✗:

  • 显示红色叉号
  • 位置准确
  • 大小适中20x20

半对标记:

  • 显示勾号+斜线组合
  • 位置准确
  • 大小适中20x20

2. 擦除功能

2.1 点击擦除

测试步骤:

  1. 绘制多个不同类型的标记
  2. 选择擦除工具
  3. 点击各个标记

预期结果:

  • 点击矩形内部,矩形被删除
  • 点击线条附近5px内线条被删除
  • 点击特殊标记,标记被删除
  • 点击文本,文本被删除
  • 点击空白处,无反应

碰撞检测测试:

// 矩形边界测试
点击 (100, 100) -> 在矩形内 
点击 (99, 99) -> 在矩形外 
点击 (300, 250) -> 在矩形内 
点击 (301, 251) -> 在矩形外 

// 线条距离测试
点击距离线条 3px -> 命中 
点击距离线条 10px -> 未命中 

// 特殊标记测试(中心点 100, 100
点击 (100, 100) -> 命中 
点击 (90, 90) -> 命中 
点击 (110, 110) -> 命中 
点击 (89, 89) -> 未命中 

2.2 拖动擦除

测试步骤:

  1. 绘制多个标记
  2. 选择擦除工具
  3. 按住鼠标/手指拖动经过标记

预期结果:

  • 经过的标记被连续删除
  • 擦除流畅,无卡顿

3. 撤销/重做功能

3.1 撤销操作

测试步骤:

  1. 依次绘制:矩形 -> 线条 -> 文本
  2. 点击撤销按钮 3 次

预期结果:

  • 第1次撤销文本消失
  • 第2次撤销线条消失
  • 第3次撤销矩形消失
  • 第4次撤销按钮禁用无反应

命令栈验证:

// 初始状态
commandStack: []
currentIndex: -1
canUndo: false

// 绘制矩形后
commandStack: [AddShapeCommand(rect)]
currentIndex: 0
canUndo: true

// 绘制线条后
commandStack: [AddShapeCommand(rect), AddShapeCommand(line)]
currentIndex: 1
canUndo: true

// 撤销一次后
commandStack: [AddShapeCommand(rect), AddShapeCommand(line)]
currentIndex: 0
canUndo: true
canRedo: true

3.2 重做操作

测试步骤:

  1. 绘制标记
  2. 撤销
  3. 点击重做

预期结果:

  • 标记重新出现
  • 位置、样式与原来一致

3.3 撤销后新建

测试步骤:

  1. 绘制A -> B -> C
  2. 撤销 2 次(剩下 A
  3. 绘制新标记 D

预期结果:

  • B、C 从命令栈中移除
  • 不能重做 B、C
  • 可以撤销 D
// 撤销2次后
commandStack: [A, B, C]
currentIndex: 0

// 绘制D后
commandStack: [A, D]  // B、C被截断
currentIndex: 1
canRedo: false

3.4 清空所有标记

测试步骤:

  1. 绘制多个标记
  2. 点击"清空"按钮
  3. 点击撤销

预期结果:

  • 所有标记消失
  • 撤销后所有标记恢复

4. 缩放功能

4.1 手动缩放

测试步骤:

  1. 设置缩放比例为 0.5
  2. 绘制标记
  3. 设置缩放比例为 2.0

预期结果:

  • 图片大小正确变化
  • 标记跟随图片缩放
  • 标记位置相对图片不变
  • 新绘制的标记坐标正确

坐标转换验证:

// 缩放 0.5 时点击屏幕 (100, 100)
实际坐标 = (100 / 0.5, 100 / 0.5) = (200, 200)

// 缩放 2.0 时点击屏幕 (100, 100)
实际坐标 = (100 / 2.0, 100 / 2.0) = (50, 50)

4.2 自适应宽度模式

测试步骤:

  1. 启用自适应宽度
  2. 调整浏览器窗口宽度

预期结果:

  • 图片宽度自动适应容器
  • 高度按比例缩放
  • 标记位置正确

4.3 双指缩放(触摸设备)

测试步骤:

  1. 在触摸设备上打开
  2. 双指捏合/展开

预期结果:

  • 图片跟随手势缩放
  • 显示缩放百分比提示
  • 标记跟随缩放

5. 快捷打分功能

5.1 加分模式

测试步骤:

  1. 设置快捷打分:加分模式,分值 2
  2. 启用快捷打分点击模式
  3. 点击画布

预期结果:

  • 显示 "+2" 文本标记
  • 分数增加 2 分
  • 文本颜色为红色
  • 不能超过满分

边界测试:

满分: 10
当前: 9
点击加2 -> 分数变为 10 
再次点击 -> 无反应 

5.2 减分模式

测试步骤:

  1. 设置快捷打分:减分模式,分值 1
  2. 启用快捷打分点击模式
  3. 点击画布

预期结果:

  • 显示 "-1" 文本标记
  • 分数减少 1 分
  • 文本颜色为蓝色
  • 不能低于 0 分

6. 多图片场景

6.1 多图片渲染

测试步骤:

  1. 加载包含 3 张图片的题目
  2. 在每张图片上绘制不同标记

预期结果:

  • 每张图片独立渲染
  • 标记数据互不干扰
  • 撤销操作针对最后操作的图片

6.2 横向/纵向布局

测试步骤:

  1. 切换图片布局模式

预期结果:

  • 横向布局:图片水平排列
  • 纵向布局:图片垂直排列
  • 标记位置不受影响

7. 只读模式

7.1 历史记录查看

测试步骤:

  1. 打开已批改的试卷
  2. 查看标记

预期结果:

  • 所有标记正确显示
  • 不响应点击事件
  • 不显示工具栏

8. 数据持久化

8.1 数据导出

测试步骤:

  1. 绘制多种标记
  2. 导出数据

预期结果:

{
  "version": "1.0",
  "shapes": [
    {
      "id": "shape_xxx",
      "type": "rect",
      "x": 100,
      "y": 100,
      "width": 200,
      "height": 150,
      "stroke": "#ff0000",
      "strokeWidth": 2
    }
  ],
  "specialMarks": [
    {
      "id": "mark_xxx",
      "type": "correct",
      "x": 300,
      "y": 200
    }
  ],
  "annotations": [
    {
      "id": "text_xxx",
      "x": 400,
      "y": 300,
      "text": "扣1分",
      "fontSize": 14,
      "color": "#000000"
    }
  ]
}

8.2 数据导入

测试步骤:

  1. 导入上述 JSON 数据
  2. 查看渲染结果

预期结果:

  • 所有标记正确恢复
  • 位置、样式一致

9. 性能测试

9.1 大量标记渲染

测试步骤:

  1. 导入包含 100+ 标记的数据
  2. 观察渲染性能

预期结果:

  • 初始渲染 < 1s
  • 滚动流畅,无卡顿
  • 内存占用合理

9.2 快速连续绘制

测试步骤:

  1. 快速绘制多条线条

预期结果:

  • 线条流畅,无延迟
  • 不丢失点
  • 不出现重复标记

10. 兼容性测试

10.1 微信小程序

测试步骤:

  1. 在微信开发者工具中运行
  2. 测试所有功能

预期结果:

  • 所有功能正常
  • 触摸事件响应正常
  • 无控制台错误

10.2 不同分辨率

测试设备:

  • iPhone SE (375x667)
  • iPhone 14 Pro (393x852)
  • iPad (768x1024)
  • Desktop (1920x1080)

预期结果:

  • 布局自适应
  • 标记大小合适
  • 触摸区域足够大

🐛 Bug 报告模板

### Bug 描述
简要描述问题

### 复现步骤
1. 步骤1
2. 步骤2
3. 步骤3

### 预期行为
应该发生什么

### 实际行为
实际发生了什么

### 环境信息
- 设备: iPhone 14
- 系统: iOS 16.0
- 浏览器: 微信开发者工具
- 版本: 1.0.0

### 截图/录屏
如果可能,提供截图或录屏

### 相关数据
如果涉及数据问题,提供 JSON 数据

📊 测试报告模板

# DOM 渲染功能测试报告

## 测试概况
- 测试日期: 2024-01-01
- 测试人员: XXX
- 测试环境: 微信开发者工具 / Chrome
- 测试版本: 1.0.0

## 测试结果汇总
| 功能模块 | 测试用例数 | 通过 | 失败 | 通过率 |
|---------|-----------|------|------|--------|
| 基础绘制 | 10 | 10 | 0 | 100% |
| 擦除功能 | 5 | 5 | 0 | 100% |
| 撤销重做 | 8 | 8 | 0 | 100% |
| 缩放功能 | 6 | 6 | 0 | 100% |
| 快捷打分 | 4 | 4 | 0 | 100% |
| 多图片 | 3 | 3 | 0 | 100% |
| 只读模式 | 2 | 2 | 0 | 100% |
| 数据持久化 | 4 | 4 | 0 | 100% |
| 性能测试 | 3 | 3 | 0 | 100% |
| 兼容性 | 5 | 5 | 0 | 100% |
| **总计** | **50** | **50** | **0** | **100%** |

## 详细测试结果
[详细记录每个测试用例的结果]

## 发现的问题
[列出发现的所有问题]

## 建议
[提出改进建议]

## 结论
✅ 通过 / ❌ 不通过

🎯 自动化测试(可选)

单元测试示例

import { describe, it, expect } from 'vitest'
import { useSimpleDomLayer } from './useMarkingDom'

describe('useMarkingDom', () => {
  it('should add shape correctly', () => {
    const layer = useSimpleDomLayer({...})
    
    // 模拟绘制矩形
    layer.handleMouseDown(mockEvent, mockRect)
    layer.handleMouseMove(mockEvent, mockRect)
    layer.handleMouseUp()
    
    expect(layer.markingData.value.shapes).toHaveLength(1)
    expect(layer.markingData.value.shapes[0].type).toBe('rect')
  })
  
  it('should undo correctly', () => {
    const layer = useSimpleDomLayer({...})
    
    // 添加标记
    layer.handleMouseDown(mockEvent, mockRect)
    layer.handleMouseUp()
    
    expect(layer.markingData.value.shapes).toHaveLength(1)
    
    // 撤销
    layer.undo()
    
    expect(layer.markingData.value.shapes).toHaveLength(0)
  })
})

📝 测试记录

测试日期: ___________

测试人员: ___________

测试项 状态 备注
绘制矩形
绘制线条
文本注释
特殊标记
擦除功能
撤销操作
重做操作
清空标记
手动缩放
自适应宽度
快捷打分
多图片
只读模式
数据导出
数据导入
性能测试
小程序兼容

签名: ___________