419 lines
12 KiB
Markdown
419 lines
12 KiB
Markdown
# 自动化测试方案讨论
|
||
|
||
## 需求背景
|
||
|
||
`Doc/EPUB_MAINTENANCE.md` 已将“自动化测试”列为 EPUB 阅读器下一阶段的高优先级能力之一。
|
||
|
||
当前阅读器已经具备较完整的主链路能力,包括:
|
||
|
||
1. EPUB 解析与打开
|
||
2. WebView / DTCoreText / fixed-layout 三条正文渲染路径
|
||
3. 目录跳转、阅读位置恢复、主题与字号调整
|
||
4. 高亮、划线、批注、搜索等阅读交互能力
|
||
|
||
但这些能力目前主要依赖手工验证,缺少自动化回归保护。随着横竖屏切换、书签、更多搜索体验和阅读增强能力继续叠加,单靠人工回归会越来越难以稳定覆盖高联动场景。
|
||
|
||
因此,“自动化测试”这项需求的目标不是单纯增加几条测试用例,而是为 EPUB 阅读器建立一套可持续演进的自动化回归体系,优先保护以下核心链路:
|
||
|
||
1. 解析
|
||
2. 分页
|
||
3. 定位恢复
|
||
4. 目录跳转
|
||
5. 标注恢复
|
||
|
||
## 代码事实
|
||
|
||
### 已有基础
|
||
|
||
当前仓库并不是完全没有可测试的基础:
|
||
|
||
1. `Sources/RDReaderView/EPUBCore/` 已经把 parser、resourceResolver、location、readingSession、paginator 等能力拆成了相对独立的模块
|
||
2. `Sources/RDReaderView/EPUBTextRendering/` 已经将 DTCoreText 渲染、fragment 提取、富文本分页等逻辑收敛到明确的工具类型中
|
||
3. `RDEPUBLocation`、`RDEPUBHighlight`、TOC / spine / manifest 等模型本身适合做 deterministic 的断言
|
||
4. `ReadViewSDKDemo` 已经提供真实运行容器,后续可以承载 UI 自动化测试
|
||
|
||
结论:
|
||
|
||
1. 核心逻辑并非不可测
|
||
2. 更缺的是测试 target、测试夹具、断言策略和回归矩阵
|
||
|
||
### 当前实现存在的问题
|
||
|
||
#### 问题 1:工程里还没有测试承载层
|
||
|
||
从 `ReadViewSDKDemo.xcodeproj` 当前 target 配置来看,只有 `ReadViewSDKDemo` app target,没有独立的 `Tests` 或 `UITests` target。
|
||
|
||
这意味着当前并没有:
|
||
|
||
1. 用于跑 XCTest 的基础 target
|
||
2. 用于跑 XCUITest 的 UI 测试 target
|
||
3. 稳定的测试资源加载方式
|
||
|
||
#### 问题 2:关键链路缺少自动回归保护
|
||
|
||
当前高风险能力包括:
|
||
|
||
1. `RDEPUBParser` 解析 EPUB ZIP / OPF / spine / TOC
|
||
2. `RDEPUBResourceResolver.normalizedHref(_:)` 的路径标准化
|
||
3. `RDEPUBPaginator` 与 `RDEPUBTextPaginationSupport` 的分页结果
|
||
4. `RDEPUBReaderController.restoreLocation(_:)` 的定位恢复
|
||
5. 高亮 / 批注 persistence 的恢复链路
|
||
|
||
这些地方一旦回归,通常会表现为:
|
||
|
||
1. 打不开书
|
||
2. 目录跳错
|
||
3. 字号变化后位置飘移
|
||
4. 标注丢失或恢复失败
|
||
|
||
而这些问题都很适合被自动化测试尽早捕获。
|
||
|
||
#### 问题 3:如果直接从 UI 自动化起步,成本和脆弱性都偏高
|
||
|
||
EPUB 阅读器的很多问题发生在 UI 之下,例如:
|
||
|
||
1. TOC href 标准化错误
|
||
2. `fragment -> offset` 映射偏移
|
||
3. 分页结果为空或页数异常
|
||
4. `href + progression` 回落恢复逻辑不稳定
|
||
|
||
如果这些问题都等到 `XCUITest` 才暴露:
|
||
|
||
1. 定位根因会很慢
|
||
2. 测试执行时间会更长
|
||
3. 异步加载、动画、WebView 时序会让用例更脆
|
||
|
||
#### 问题 4:当前还没有固定的样书基线与测试夹具约定
|
||
|
||
要让自动化测试长期稳定,必须明确:
|
||
|
||
1. 哪几本样书是测试夹具
|
||
2. 每本样书用于验证哪种能力
|
||
3. 哪些断言可以依赖“页号”,哪些只能依赖 `href / fragment / progression`
|
||
|
||
如果没有这层约束,测试很容易随着样书变化或样式调整而频繁漂移。
|
||
|
||
## 需求拆解
|
||
|
||
建议把“自动化测试”需求拆成四部分,而不是把所有验证都堆到同一层。
|
||
|
||
### 1. 建立测试基础设施
|
||
|
||
先补齐可执行自动化测试的工程结构,包括:
|
||
|
||
1. `ReadViewSDKDemoTests`
|
||
2. `ReadViewSDKDemoUITests`
|
||
3. 样书 fixtures 目录
|
||
4. 统一的测试资源读取辅助工具
|
||
|
||
这是后续一切测试工作的前提。
|
||
|
||
### 2. 建立逻辑层 XCTest
|
||
|
||
这部分优先覆盖稳定、纯逻辑、可快速执行的能力:
|
||
|
||
1. parser 解析
|
||
2. href 标准化
|
||
3. TOC 路径映射
|
||
4. location / progression / fragment 相关转换
|
||
5. persistence 编解码
|
||
|
||
目标是让每次改动 parser、模型、定位和持久化逻辑时,都有快速反馈。
|
||
|
||
### 3. 建立集成层 XCTest
|
||
|
||
这部分不直接走 UI 自动化,但会驱动真实样书、真实分页和真实恢复链路,重点覆盖:
|
||
|
||
1. reflowable 样书分页
|
||
2. fixed-layout 样书页面模型生成
|
||
3. 字号变化后位置恢复
|
||
4. 目录跳转命中
|
||
5. 标注恢复
|
||
|
||
目标是把“阅读核心链路”在逻辑层和 UI 层之间补上一层更贴近真实运行的保护网。
|
||
|
||
### 4. 建立少量高价值 XCUITest
|
||
|
||
UI 自动化不追求全覆盖,而是做真实用户闭环的冒烟回归,例如:
|
||
|
||
1. 打开样书进入阅读器
|
||
2. 目录跳转
|
||
3. 调整字号
|
||
4. 创建高亮并重新进入验证恢复
|
||
5. 横竖屏切换后继续阅读
|
||
|
||
目标是证明“用户真的能完成关键操作”,而不是把所有细节都放进 UI 测试里。
|
||
|
||
## 技术路线对比
|
||
|
||
### 路线 A:优先建设 XCUITest
|
||
|
||
思路:
|
||
|
||
1. 先搭 UI 自动化
|
||
2. 用点击、滑动、旋转和断言可见文本的方式覆盖主要能力
|
||
|
||
优点:
|
||
|
||
1. 结果直观,容易贴近真实用户行为
|
||
2. 可以较快形成“端到端可用”的感知
|
||
|
||
风险:
|
||
|
||
1. 调试成本高
|
||
2. 受动画、异步、WebView 时序影响大
|
||
3. 很难快速判断问题出在 parser、分页还是 UI
|
||
4. 执行时间更长,不适合作为最早期主回归层
|
||
|
||
### 路线 B:优先建设 XCTest
|
||
|
||
思路:
|
||
|
||
1. 先为逻辑与集成层补单元测试
|
||
2. 把解析、分页、定位恢复等能力尽量在非 UI 层验证
|
||
|
||
优点:
|
||
|
||
1. 稳定性更高
|
||
2. 运行更快
|
||
3. 更利于问题定位
|
||
4. 更适合作为日常改动的主回归层
|
||
|
||
风险:
|
||
|
||
1. 不能完全证明 UI 交互链路没问题
|
||
2. 覆盖不到真实点击、WebView 手势和界面状态同步问题
|
||
|
||
### 路线 C:分层推进
|
||
|
||
思路:
|
||
|
||
1. 先建立测试基础设施
|
||
2. 以 XCTest 为主搭建核心保护网
|
||
3. 再补少量 XCUITest 做端到端闭环
|
||
|
||
优点:
|
||
|
||
1. 投入与收益平衡更好
|
||
2. 能优先保护最容易回归的核心能力
|
||
3. 既兼顾稳定性,也兼顾真实用户路径
|
||
|
||
风险:
|
||
|
||
1. 初期需要先设计测试层次和夹具约定
|
||
2. 需要控制 UI 测试范围,避免后续无节制膨胀
|
||
|
||
### 推荐结论
|
||
|
||
建议采用:
|
||
|
||
**主路线:路线 C,分层推进,XCTest 为主,XCUITest 为辅**
|
||
|
||
原因:
|
||
|
||
1. 当前最需要保护的是解析、分页、定位恢复这些高风险核心链路
|
||
2. 仓库当前还没有测试 target,先从更稳定的 XCTest 起步更合适
|
||
3. 少量 XCUITest 足以证明关键阅读流程可用,不必一开始追求全面 UI 覆盖
|
||
|
||
## 推荐方案
|
||
|
||
### 方案总览
|
||
|
||
自动化测试第一阶段建议形成如下结构:
|
||
|
||
```text
|
||
ReadViewSDKDemoTests
|
||
- ParserTests
|
||
- ResourceResolverTests
|
||
- LocationRestoreTests
|
||
- TextPaginationTests
|
||
- HighlightPersistenceTests
|
||
|
||
ReadViewSDKDemoUITests
|
||
- ReaderSmokeTests
|
||
- ReaderNavigationTests
|
||
- ReaderAnnotationTests
|
||
- ReaderRotationTests
|
||
```
|
||
|
||
同时建立一套最小样书夹具集:
|
||
|
||
1. `reflowable-basic.epub`
|
||
2. `fixed-layout-basic.epub`
|
||
3. `image-heavy.epub`
|
||
4. `toc-fragment.epub`
|
||
|
||
每本样书都应明确“它用来验证什么”,而不是仅作为示例文件存在。
|
||
|
||
### 关键改动建议
|
||
|
||
#### Task T1:建立测试 target 与基础资源加载能力
|
||
|
||
文件范围:
|
||
|
||
1. `ReadViewSDKDemo/ReadViewSDKDemo.xcodeproj`
|
||
2. 新增 `ReadViewSDKDemoTests/`
|
||
3. 新增 `ReadViewSDKDemoUITests/`
|
||
4. 新增测试夹具目录
|
||
|
||
改动:
|
||
|
||
1. 增加 unit test target
|
||
2. 增加 UI test target
|
||
3. 为测试 target 挂载样书与辅助资源
|
||
4. 提供统一 `TestBookLoader` / `FixtureLocator` 之类的测试辅助工具
|
||
|
||
完成定义:
|
||
|
||
1. 工程可以直接运行测试
|
||
2. 测试代码可以稳定读取样书资源
|
||
|
||
#### Task T2:补第一批逻辑层 XCTest
|
||
|
||
建议首批覆盖:
|
||
|
||
1. `RDEPUBParser` 能解析有效样书并产出非空 spine
|
||
2. `RDEPUBResourceResolver.normalizedHref(_:)` 能正确处理相对路径、父级路径和 fragment
|
||
3. TOC href 能统一映射到与 spine 一致的标准化路径
|
||
4. `RDEPUBHighlight` persistence 编解码结果一致
|
||
5. 定位模型在常见输入下不会丢 fragment 或 progression
|
||
|
||
完成定义:
|
||
|
||
1. parser / resolver / persistence / location 改动有自动回归保护
|
||
|
||
#### Task T3:补第一批集成层 XCTest
|
||
|
||
建议首批覆盖:
|
||
|
||
1. reflowable 样书分页结果非空
|
||
2. fixed-layout 样书能建立页模型
|
||
3. 字号变化后仍能按 `href + progression` 恢复到原章节附近
|
||
4. 目录跳转可命中预期 spine 资源
|
||
5. 高亮恢复后仍能定位到对应资源
|
||
|
||
完成定义:
|
||
|
||
1. 核心阅读链路具备非 UI 层的真实运行回归能力
|
||
|
||
#### Task T4:补第一批冒烟型 XCUITest
|
||
|
||
建议首批覆盖:
|
||
|
||
1. 打开样书并进入阅读器
|
||
2. 打开目录并跳转章节
|
||
3. 调整字号后继续阅读
|
||
4. 创建一条高亮并重进验证恢复
|
||
5. 横竖屏切换后继续阅读
|
||
|
||
完成定义:
|
||
|
||
1. 至少有一条真实用户闭环可以证明主功能未损坏
|
||
|
||
## 断言策略建议
|
||
|
||
为了降低测试漂移,建议统一以下断言原则:
|
||
|
||
### 1. 少依赖固定页号
|
||
|
||
页号非常容易受以下因素影响:
|
||
|
||
1. 字号
|
||
2. 行距
|
||
3. 视口尺寸
|
||
4. 图片加载时序
|
||
|
||
因此,自动化测试不应过度依赖“必须是第 N 页”这种断言。
|
||
|
||
### 2. 优先依赖稳定语义锚点
|
||
|
||
更推荐的断言对象包括:
|
||
|
||
1. `href`
|
||
2. `fragment`
|
||
3. `progression` 所在区间
|
||
4. spine index
|
||
5. 高亮所属资源
|
||
|
||
### 3. UI 测试只验证关键闭环
|
||
|
||
XCUITest 中更适合验证:
|
||
|
||
1. 页面是否成功进入
|
||
2. 关键按钮是否可操作
|
||
3. 操作后阅读器状态是否变化
|
||
4. 重进后状态是否可恢复
|
||
|
||
而不适合在 UI 测试中承载大量底层分页细节断言。
|
||
|
||
## 验收矩阵建议
|
||
|
||
自动化测试第一阶段至少要覆盖以下维度:
|
||
|
||
1. `webInteractive`
|
||
2. `webFixedLayout`
|
||
3. `textReflowable`
|
||
4. TOC 跳转
|
||
5. 字号变化后恢复
|
||
6. 高亮恢复
|
||
7. 横竖屏切换
|
||
8. 一到两本问题样书回归
|
||
|
||
如果资源有限,建议先保证“三条渲染路径 + 两条恢复链路”:
|
||
|
||
1. 三条渲染路径:`webInteractive` / `webFixedLayout` / `textReflowable`
|
||
2. 两条恢复链路:阅读位置恢复 / 标注恢复
|
||
|
||
## 风险与注意点
|
||
|
||
### 风险 1:测试一开始就绑定大量脆弱 UI 细节
|
||
|
||
如果测试过度依赖:
|
||
|
||
1. 动画时长
|
||
2. 可见文案位置
|
||
3. 某个具体页号
|
||
4. WebView 内即时渲染完成时机
|
||
|
||
后续维护成本会非常高。
|
||
|
||
### 风险 2:测试夹具过多但目标不清晰
|
||
|
||
样书数量不是越多越好。更重要的是:
|
||
|
||
1. 每本样书验证哪类能力
|
||
2. 哪些样书是主回归集
|
||
3. 哪些样书只在专项验证时使用
|
||
|
||
### 风险 3:横竖屏与字号变化断言过于绝对
|
||
|
||
这两类场景更适合验证:
|
||
|
||
1. 是否仍在同一章节或邻近语义位置
|
||
2. 是否仍保留原始 `href / fragment`
|
||
3. progression 是否在合理偏差范围内
|
||
|
||
而不适合验证“必须恢复到完全相同页号”。
|
||
|
||
## 推荐实施顺序
|
||
|
||
如果目标是“最小投入换最大稳定性提升”,建议按以下顺序推进:
|
||
|
||
1. 建立 `Tests` / `UITests` target
|
||
2. 补 parser / resolver / location / persistence 的 XCTest
|
||
3. 补分页、目录跳转、定位恢复的集成测试
|
||
4. 补 3 到 5 条高价值 XCUITest
|
||
5. 将横竖屏、问题样书和新增功能逐步并入回归矩阵
|
||
|
||
## 推荐结论
|
||
|
||
“自动化测试”这项需求,建议最终收敛为下面这句话:
|
||
|
||
**为 EPUB 阅读器建立一套分层自动化测试体系,以 XCTest 保护解析、分页、定位恢复、目录跳转和标注恢复等核心链路,再以少量 XCUITest 验证真实阅读闭环。**
|
||
|
||
这样做的好处是:
|
||
|
||
1. 能尽快为最容易回归的核心能力建立保护网
|
||
2. 不会过早陷入脆弱的全量 UI 自动化
|
||
3. 能为横竖屏、书签、搜索和后续阅读增强功能提供稳定回归基础
|