专栏文章 移动 H5 广告的性能自动化测试方案 (续)

360Qtest团队 · 2018年11月19日 · 最后由 simple 回复于 2018年12月28日 · 219 次阅读

书接上文

上篇文章《移动 H5 广告的性能自动化测试方案》末尾我提到了几个问题,是我们在探索移动端 H5 性能自动化测试遇到的几个比较棘手的坑:

  1. Tcpdump 需要 root 权限,而我们的任务需要分布式执行,且目前高版本的手机 root 失败率非常高,而且还存在 root 被还原的情况 。
  2. JS 注入以什么方式进行?
  3. pcap 文件的解析对 https 的请求束手无策,而我们的广告请求都是 https 的。
  4. 白屏时间是否是标准答案?

本文主要介绍我们的解决思路,以供读者参考,如有问题欢迎大家轻喷。。

一些前端性能的背景知识

在介绍新方案之前,想先扯一些前端的背景知识。

关于移动浏览器

目前手机上的浏览器可谓琳琅满目,譬如 360 安全浏览器,UC 浏览器,QQ 浏览器,欧朋浏览器,百度手机浏览器,谷歌浏览器,搜狗手机浏览器,猎豹浏览器等等,给测试同学的适配带来了巨大的工作量。另外最近 “原创的红芯浏览器” 可谓刷爆了各大朋友圈,在此也想小科普一些浏览器内核的知识。
早期全球仅有四个独立的浏览器内核,分别为微软 IE 的 Trident、网景最初研发后卖给 Mozilla 基金会并演化成火狐的 Gecko、KDE 的开源内核 Webkit 以及 Opera(欧朋) 的 Presto。其中,Presto 是历史最悠久的内核。
早期的时候 chrome 和 safari 都采用了 webkit 内核,不过 Google 发布了 chrome 浏览器后,将使用的浏览器内核更名为 chromium,是 webkit 开源项目的一个分支,随后中2013年4月3日,谷歌的 Chromium Blog 发表了一篇博客,表示后续 Chromium 项目将采用 Blink 渲染引擎。

Android 原生浏览器、苹果的 Safari、谷歌的 Chrome(Android4.0 使用) 都是基于 Webkit 开源内核开发的。

浏览器的核心组件

用户界面: 包括地址栏、前进/后退按钮、书签菜单等。除了浏览器主窗口显示的您请求的页面外,其他显示的各个部分都属于用户界面。
浏览器引擎: 在用户界面和呈现引擎之间传送指令。
渲染引擎: 负责显示请求的内容。如果请求的内容是 HTML,它就负责解析 HTML 和 CSS 内容,并将解析后的内容显示在屏幕上。
网络层: 用于网络调用,比如 HTTP 请求。其接口与平台无关,并为所有平台提供底层实现。
用户界面后端: 用于绘制基本的窗口小部件,比如组合框和窗口。其公开了与平台无关的通用接口,而在底层使用操作系统的用户界面方法。
JavaScript 解释器: 用于解析和执行 JavaScript 代码。
数据存储: 这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie。新的 HTML 规范 (HTML5) 定义了 “网络数据库”,这是一个完整(但是轻便)的浏览器内数据库。

  • 以 WebKit 内核为例,看一下浏览器渲染的过程

  • W3C performance API
    前文有提到影响用户体验的三个性能指标分别是:

    • Start Render
    • DOM Ready
    • Page Load

这几个关键时间节点,可以通过 W3C performance API 中的 Navigation Timing API 来获得。

W3C 组织在 2010 年成立了 web 性能工作组,专门开发了一个支持将浏览器暴露给 JavaScript 的 API,该 API 为浏览器开发人员提供了一种精确度量和分析 web 页面性能的有效手段。整套 performance API 有 10 种

  • Navigation Timing: 能够帮助网站开发者检测真实用户数据(RUM),例如带宽、延迟或主页的整体页面加载时间。
  • Resource Timing: 对单个资源的计时,主要统计比如 DNS、TCP 链接、wating 等具体的耗时。

我们需要统计的时间指标可以通过以下公式换算出来:

DNS查询耗时 domainLookupEnd - domainLookupStart
TCP链接耗时 connectEnd - connectStart
request请求耗时 responseEnd - responseStart
解析dom树耗时  domComplete - domInteractive
白屏时间 responseStart - navigationStart
DOMReady时间 domContentLoadedEventEnd - navigationStart
onload时间 loadEventEnd - navigationStart
关于白屏时间的争议

负责性能数据监控的同学在开发过程中发现,白屏数据按照上面时间点抓取存在问题,不太准确,有的时候拿到的截图已经开始有 dom 数据加载了,为此还发生过争论,带着这个问题仔细的考证了一下,从 W3C 开源项目的 issue 列表中看到了项目成员的解答:

为什么没把first paint time 写进标准里呢希望您能把他加进去。

因为不能准确定义它这个时间标准是模糊的比如一些网页他本来就是空白的啊怎么来定义这个paint的时间呢而且很多人并不在乎什么时候画出第一个像素他们想跟踪一下具体某个元素是什么时候画出来的但是每个网站都不一样我们不可能来定义太细的接口所以不能加。
Frame Timing 可以让你跟踪画出来的时间如果你真想追踪first paint(白屏) time你得等我们有一些 Houdini pieces(巧妙的规避办法 -牛津大字典) 才能有比较好的解决办法

那为什么DevTools里面有呢为什么不加个时间戳(从hidden到visible)? 我就是想知道从点击进去到看到内容用户等了多久这个值是模糊的么
在DevTools里有并不是意味着他是一个好的标准如果想加时间戳来记录你自己加就行了呗我只是认为first paint 不够分量来写进标准frame Timing 应该更有意义但是需要时间

如果读者有不错的白屏时间计算方法,欢迎做文章下面留言。

移动端 H5 性能测试方案比较

以下几种方案是我们内部讨论过程中梳理过的几种可能性,有些方案可能不适合我们当前的需求,但是适合读者自身,所以观点仅仅给大家作为参考。

1. Fiddler/Charles 进行性能抓包
  • 优点:测试人员熟悉功能,上手快,UI 功能完善友好,可以通过 script 扩展
  • 缺点:性能自动化方案实施成本比较高,跨平台支持比较差
2. PhantomJS 抓包
  • 优点:PhantomJS(http://phantomjs.org/ ;)是一个可编程的无界面浏览器。它通过 JavaScript 和 CoffeeScript 控制 webkit 的各个模块,比如 CSS Selector,JSON,Canvas、SVG 和 HTTP 网络等等,它通过 netsniff.js 监控网络请求并生成 HAR 文件,拿到 HAR 文件后续将很好办了。
  • 缺点:基于 PC 端出的性能数据
3.Chrome remote debug 远程调试
  • 优点:通过 Chrome DevTools Protocol 来打通 PC 浏览器和移动设备,功能强大毋庸置疑,我们开发基本上采用这种方式来进行移动端调试和优化
  • 缺点:无法自动化运行,需要翻樯,因为 chrome inspect 需要访问 appspot.com 地址

4. Tcpdump&Mimtproxy
  • Tcpdump 优点 相信需要测试移动网络抓包场景的同学一定有接触过 tcpdump 吧?Tcpdump 是 Linux 系统中使用的比较广泛的一款抓包工具,其利用的是 libpcap 工具,通过监听和记录网卡接口的特定端口的网络数据来实施抓包,生成的文件以 pcap 结尾。用 wireshark 直接读取或者通过解析 pcap2har 工具来生成需要的性能数据,是比较接近真实移动设备环境的一种测试手段。具体的操作方式可以自行搜索,也可以参考我写的上一篇文章的用法介绍。
  • Tcpdump 缺点:需要 root、高版本手机 root 成功率极低、容易被还原导致自动化测试任务无法进行,无法解析 https 请求。

  • MimtProxy 优点
    MitmProxy 是什么这里就不做赘述,读者可以自己看一下官网介绍 (https://mitmproxy.org; ),它本来是被黑客拿来做 “中间人攻击” 用的利器,我们主要用到的是它对 https 数据截获的功能。不同于 tcpdump 的是我们可以对 mitmproxy 抓取到的数据做高度定制化处理。

  • MimtProxy 缺点
    由于其代理的特征,会对传输数据有一定性能上的损耗,不过从版本横向比较的角度来说可以忽略不计;另外 mitmproxy 获取不到 UDP 数据包;另外还有一些其他坑就不铺开说了。

关于浏览器的打开方式

监控 WebView 获取页面的性能数据

灵感来自 (https://github.com/jwcqc/WebViewMonitor;) 项目;

  • 操作流程很简单:
  • 通过在被测手机端安装 APP,接收服务端下发测试指令集告诉客户端开始进行 H5 测试
  • 客户端根据指令打开指定浏览器内核的 WebView,在访问浏览器之前注入监控 js 到页面头部
  • 客户端执行完成页面访问后,在本地记录测试数据,回传到服务端
  • 目前支持 chrome 内核和 QQ 内核

  • 设计流程图

  • 基于 STFService APK 的改造
    由于我们整体的测试方案是基于 OpenSTF 进行定制的,所以我们选择在 STFService APK 上进行改造,当然我们在开发过程中做了解耦,方便以后升级。
    注入代码如下:

    public void onProgressChanged(int newProgress) {
            if (newProgress == 100) {
                try {
                    if (mTimerFinish != null) {
                        mTimerFinish.cancel();
                        mTimerFinish = null;
                    }
                } catch (Exception e) {
                }
                if (!isDone) {
                    mTimerFinish = new Timer();
                    mTimerFinish.schedule(new TimerTask() {
                        @Override
                        public void run() {
                            //TODO collector.js文件的地址,收集的功能主要在这里面实现
                            String injectJs = "https://thisis.inject.js";
                            String js = "javascript:" +
                                    "   (function() { " +
                                    "       var script=document.createElement('script');  " +
                                    "       script.setAttribute('type','text/javascript');  " +
                                    "       script.setAttribute('src', '" + injectJs + "'); " +
                                    "       document.head.appendChild(script); " +
                                    "       script.onload = function() {" +
                                    "           startWebViewMonitor();" +
                                    "       }; " +
                                    "    }" +
                                    "    )();";
    
                            onLoadInjectJS(js);
                        }
                    }, 10000);
                }
            }
        }
    
  • 性能数据处理代码

    public long[] parsePerformanceData(String data) {
        long[] result = null;
        try {
            JSONObject jsonObject = new JSONObject(data);
            jsonObject = jsonObject.getJSONObject("payload");
            JSONObject timeJsonObj = jsonObject.getJSONObject("navigationTiming");
    
            final long timeStart = timeJsonObj.optInt("navigationStart");
            final long timeWhite = timeJsonObj.optInt("responseStart") - timeStart;
            final long timeLoad = timeJsonObj.optInt("loadEventEnd") - timeStart;
            final long timeDNS = timeJsonObj.optInt("domainLookupEnd") - timeJsonObj.optInt("domainLookupStart");
            final long timeTCP = timeJsonObj.optInt("connectEnd") - timeJsonObj.optInt("connectStart");
            final long timeDOMParse = timeJsonObj.optInt("domComplete") - timeJsonObj.optInt("domInteractive");
            final long timeDOMReady = timeJsonObj.optInt("domContentLoadedEventEnd") - timeJsonObj.optInt("navigationStart");
    
            result = new long[]{timeWhite, timeLoad, timeDNS, timeTCP, timeDOMParse, timeDOMReady};
        } catch (Exception e) {
            result = null;
        }
        return result;
    }
    
  • 针对 OpenSTF 服务端做了扩展

    • 在 STFService/wire.proto 中扩展了消息事件
    • 修改了/lib/units/device/plugins/service.js 部分逻辑,增加了部分事件监听和接口
    • 增加了服务端和客户端定制接口和数据处理逻辑 event 事件
性能数据的 Timline 瀑布图

通过以上方式拿到性能数据后,需要对 pacap 文件进行转化,一开始用的是开源工具 python 版本的 pcap2har,开源地址(https://github.com/andrewf/pcap2har; )后来为了更好的集成到平台中,我们尝试写了一套 node 版本的,具体参考公众号之前的文章《nodejs 实现 pcap 转换 har》,没错,上面的技术方案也是团队两个小伙子捣鼓出来的,是不是非常棒?

通过开源项目 harviewer(地址请参考我上篇文章)将 json 格式的结果文件快速转换成前端 timline 格式的报告,当然为了满足我们项目的需要,一样对 harview 进行了大量的改造,代码细节就不截图了。

测试报告如下:


结束语

前端性能优化

前端性能优化方案,请关注我们部门前端团队奇舞团的公众号,有专业的文章讲解,比如 l 来自 W3C 成员的文章《CSS 性能优化的 8 个技巧》等等。

一些疑问
  • 项目历时大半年时间
  • 基于开源项目 openstf,对其做了部分重构(前端和数据库)
  • 大家遇到的问题我们也多数碰到了,比如性能问题、掉线问题、offline 问题等等
参考文献

https://blog.csdn.net/TMQ1225/article/details/53204476
https://segmentfault.com/a/1190000004010453
http://www.cocoachina.com/ios/20170717/19882.html?utm_source=itdadao&utm_medium=referral
https://github.com/jwcqc/WebViewMonitor
https://github.com/w3c/navigation-timing/issues/21
https://www.w3.org/Submission/first-screen-paint/
https://www.cnblogs.com/littlelittlecat/p/6810294.html

共收到 2 条回复 时间 点赞

作者你好,我想知道你们这个项目是开发人员做的?还是测试人员做的?这个项目的人数是多少?

xiwunongyue 回复

2 个测试同学兼职弄的

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册