在微信读书 App [1] 中,排版引擎负责把书源文件解析、渲染至屏幕,是最常用、最复杂的组件之一。而开发同学对排版引擎的日常修改,可能影响了海量书籍的排版结果。对排版引擎修改的测试耗时多、难度大、容易漏测。本文介绍了为解决测试的难题,如何逐步将人工测试步骤自动化,最终构建了一套微信读书排版引擎自动化测试流程,以确保微信读书排版引擎的质量。
" 排版引擎(layout engine,也称为浏览器内核(web browser engine)、页面渲染引擎(rendering engine)或样版引擎)是一种软件组件,负责获取标记式内容(如HTML、XML及图像文件等等)、整理信息(如CSS及XSL等),并将排版后的内容输出至显示器或打印机。所有网页浏览器、电子邮件客户端以及其它需要根据表示性的标记语言(Presentational markup)来显示内容的应用程序都需要排版引擎。 [2]"
在微信读书 App 中,排版引擎负责解析 EPUB 或 TXT 格式的书籍源文件,将排版后的书籍内容,如文字、图像、注解等元素,在屏幕上渲染。
为了获得极致的阅读体验,产品同学经常会提出细致的排版需求,交给开发同学修改。而排版引擎的修改,往往牵一发动全身,大量书籍排版结果都会受影响。
举个例子,有个需求是增加正文段落的 margin:
再举个极端的例子,有个需求要把章节标题往右移动1个像素:
那么,如何确保微信读书的排版质量?最开始,我们用人工测试的方法来确保质量。
当开发按需求修改排版引擎、自测后,会把代码提交到 svn,然后交给测试同学进行测试。
测试同学使用持续集成工具编译打包,得到排版引擎修改后的 App 安装包;然后在两台设备安装排版引擎修改前、后两个版本的 App,同时打开需要测试的书籍,翻页,对比,通过肉眼观察排版差异是否符合预期。
人工测试方法比较耗时,需要打开每本书,一页一页地翻页、对比,而且无法覆盖很多书籍,存在漏测的风险。
另外,通过人眼检查两台设备上的排版结果有没有差异,是很困难的任务,一是容易疲惫导致判断失误,二是对细致的排版变更(如第二个例子)很难判断是否符合预期。
前面提到,人工测试费时耗力,且容易漏测。
此外,排版需求的特点是细节多、变更快,且修改影响范围大,全网书籍上万本,无法一一验证。一旦出错,直接影响口碑。这些因素都增加了人工测试的工作量和压力。
除了精细化的排版需求会对排版引擎代码做修改,在日常的维护中,也会重构排版引擎、修改排版引擎相关但不影响排版结果的代码。每次重构、修改后,也会交给测试同学验证此次修改对排版结果没有影响。由于人工测试比较耗时、无法一一验证,每次重构排版引擎代码压力很大,轻易不敢改动。
还有一种情况,是在开发其他需求、修复缺陷时,意外地导致排版结果受影响。这种错误一旦发布到现网,后果很严重。
所以,把人工测试流程自动化十分有必要。自动化以后,可以大大减少人工测试的时间,同时方便开发同学自测。开发同学对排版引擎也可以大胆重构、持续改进代码质量。最终,达到确保排版引擎质量的目的。
首先,我们要分析一下,在人工测试中,主要有哪些步骤?每个步骤是否能自动化?
在人工测试中,对每次变更的测试,有步骤如下:
1 需要把变更前、变更后的 App 包安装到两台设备2 打开 App,登录,把要测试的书购买、加入到书架3 打开要测试的书,设置排版偏好,翻页,用眼睛查看屏幕上的排版结果,对比屏幕中的排版结果是否有差异4 如果有差异,根据需求判断差异是否符合预期
其中步骤 1、2 利用自动化测试工具是比较容易完成的。步骤 3 借助算法能够使其自动化,会在后面详细展开。步骤 4 自动化的难度比较大,可能需要借助非常高阶的人工智能完成,我们把这个步骤交给测试和开发同学。
那么,如何完成步骤 3 的自动化,让机器做人类的事情呢?我们把它再细分成三个步骤:
首先,需要找到一种机器能读懂的数据表示,这种数据表示要既能够表示排版的结果、反映代码的修改,也能够通过算法来对比,对比的结果要便于可视化的展示,方便开发、测试同学判断差异是否符合预期。
我们的选择有:
考虑到 2 容易计算差异,可视化输出效果较好,我们选取阅读器屏幕截图作为数据表示。
选择了图像作为排版结果的数据表示,那么如何对比图像差异呢?
首先,我们要选取图像特征,然后才能对比图片差异。图像的特征,从视觉认知概念上,有低、中、高级特征:
这里我们希望每个像素的差异都能检测到,所以选取像灰度化处理过的图像矩阵作为特征。
有了特征后,我们需要定义差异,就是两个图像矩阵的距离函数,如:
我们关心有多少像素点不一致,所以我们这里取 L0距离,即两个图像有多少个像素点不一样,作为差异衡量的指标。
当距离大于10时,我们认为这一页的排版结果有差异,把它可视化输出,给开发或者测试同学作为参考。
检测到差异后,我们把两个图像矩阵灰度化后相减,得到一个新的矩阵,把它归一化得到差异图像,如右图所示:
人工测试步骤 2、3 的书籍购买、加入书架、打开书籍、翻页、截图等任务,可以利用 Instrument UI Automation [9] 自动测试脚本来模拟人工点击来完成任务。
但是考虑到 Automation 模拟翻页、截图速度慢,且 UI 变更频繁导致 Automation 脚本后续维护麻烦等问题,所以我们通过提供一个测试 scheme 接口来完成这个任务。
在 App 设置彩蛋的『执行 Scheme 页面』中,输入 scheme 并执行后,App 会在后台对指定书籍购买、加入书架、排版、生成排版结果截图,并把结果保存在本地磁盘。用户也可以选择 AirDrop 到 Mac 上。
scheme 格式如下:
12345678 | weread://typeset?books=三体,乔布斯传,失控,1984,乌兰拖拉机简史&indent=1&fontSize=2&font=2&theme=3&folder=f1223 输出排版结果到目录/Libary/[vid]/[folder]/[bookId].zip @param books 需要排版的书单 @param indent 0首行不缩进 1首行缩进,默认0 @param fontSize 1,2,3,4,5,6,7 字体大小,默认4 @param font 字体 1系统字体 2 3 4 为对应选项字体,默认1 @param bgcolor 背景颜色 1白 2黄 3绿色 4夜间,默认1 @param folder 输出文件夹名,默认"cropImage" |
---|
通过这个 scheme,在真机或者模拟器都可以随时得到排版结果,而且速度比模拟翻页要快10x。
下面,将介绍我们完整的排版引擎自动化测试流程。
首先,用户需要确定参数:待生成排版结果的 svn 版本范围 r1~rn
、书单、阅读偏好设置(字体、缩进、主题模式)。把这些参数传给脚本batch_scan.py
,然后自动化流程开始,脚本会执行以下步骤:
执行 scheme
,生成排版结果得到排版结果后,执行脚本 batch_diff.py
,对相近的版本,每本书的每一页通过 diffimg.py
对比,如果有差异,则输出可视化的差异结果。
自动化流程结束后,我们得到排版结果差异,需要人工去检查差异是否符合预期。
我们以文件夹的形式组织展示差异的可视化结果:版本 r1
(修改前)与 r2
(修改后),对书籍 book1
排版差异可视化结果,保存在文件夹 diff_result_r1_r2/book1
中。
可视化结果图像中,深色字体是 r1
(修改前)的排版结果,浅色字体是 r2
(修改后)的排版结果。
另外,排版性能变化也纳入了监控。
以前人工测试排版引擎,费时耗力且容易漏测;且排版引擎的需求细节多、变更快、修改影响范围广,每次修改都要投入大量的时间测试。由于测试的代价大,开发同学不敢随意重构代码。
有了自动化测试,对于任何代码修改,而导致样本书籍、每一页、每个像素点的排版结果变更,都能够纳入我们的监控。
开发同学借助自动化测试,能大胆重构代码,拥抱快速变更的需求。
自动化测试比人工测试的时间减少了 95%,对 20 本书籍生成排版结果仅需 10 分钟,一次对比耗时 2 分钟;覆盖的书籍更多,差异对比的结果评估更可靠。
最终,借助自动化测试流程,达到确保微信读书排版引擎质量的目的。
目前,自动化测试工具已经投入使用。未来会持续优化、增加特性,以满足测试、开发同学的需求。
未来工作包括但不限于:
本文介绍了微信读书排版引擎的日常修改时,人工测试所面临的问题,以及为什么需要自动化测试的原因。
然后本文分析了人工测试的流程,以及这些流程改造成自动化的可能性。
最后,介绍了我们整套自动化测试流程,以及应用自动化测试以后所来的好处,最终达到确保微信读书排版引擎质量的目的。