CentOS 7 搭建 STF 环境,实现手机群控管理

OpenSTF 是一个Web应用程序,用于从浏览器的舒适性中远程调试智能手机,智能手表和其他小工具。

依赖

yum install gcc  gcc-c++ libtool -y

ADB

ADB 是Android的命令行调试工具。

下载并解压:

wget https://dl.google.com/android/repository/platform-tools_r29.0.5-linux.zip

unzip platform-tools_r29.0.5-linux.zip

链接adb命令:

mv ./platform-tools /usr/local/

ln -s /usr/local/platform-tools/adb /usr/bin/adb

使用adb,查看版本:

adb version

Android Debug Bridge version 1.0.41
Version 29.0.5-5949299
Installed as /usr/local/platform-tools/adb

RethinkDB

这里有官方的安装说明:https://rethinkdb.com/docs/install/centos/

直接 yum 安装:

wget https://download.rethinkdb.com/centos/7/`uname -m`/rethinkdb.repo -O /etc/yum.repos.d/rethinkdb.repo

yum install -y rethinkdb

查看版本

rethinkdb -v

rethinkdb 2.4.0 (GCC 4.8.5)

GraphicsMagick

GraphicsMagick 号称图像处理领域的瑞士军刀, 短小精悍的代码却提供了一个鲁棒、高效的工具和库集合。

wget https://jaist.dl.sourceforge.net/project/graphicsmagick/graphicsmagick/1.3.34/GraphicsMagick-1.3.34.tar.gz  

tar -zxvf GraphicsMagick-1.3.34.tar.gz 
cd GraphicsMagick-1.3.34
./configure --prefix=/usr/local/GraphicsMagick
make && make install

protobuf

ProtoBuf (Google Protocol Buffer)是由google公司用于数据交换的序列结构化数据格式,具有跨平台、跨语言、可扩展特性,类型于常用的XML及JSON,但具有更小的传输体积、更高的编码、解码能力,特别适合于数据存储、网络数据传输等对存储体积、实时性要求高的领域。

wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protobuf-cpp-3.11.2.tar.gz
tar -zxvf protobuf-cpp-3.11.2.tar.gz   

cd protobuf-3.11.2/
./configure --prefix=/usr/local/protobuf
make
make install

pkgconfig

yum install -y pkgconfig

加入环境变量:

vim /etc/profile.d/pkgconfig.sh

加入以下代码:

export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

使其生效:

source /etc/profile

ZeroMQ

ZeroMQ 是一个开源的消息队列库,它依赖libsodium

先安装libsodium

wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz
tar -zxvf libsodium-1.0.18.tar.gz 
cd libsodium-1.0.18/

./configure
make && make check
make install

ldconfig

安装ZeroMQ

wget https://archive.org/download/zeromq_4.1.4/zeromq-4.1.4.tar.gz
tar -zxvf zeromq-4.1.4.tar.gz 

cd zeromq-4.1.4

./autogen.sh
./configure --prefix=/usr/local/zeromq
make -j 4 && make install

ln -s /usr/local/zeromq/lib/libzmq.* /usr/local/lib/
ln -s /usr/local/zeromq/include/zmq* /usr/local/include/

yasm

安装:

wget https://github.com/yasm/yasm/releases/download/v1.3.0/yasm-1.3.0.tar.gz
tar -zxvf yasm-1.3.0.tar.gz 

cd yasm-1.3.0/
./configure --prefix=/usr/local/yasm 
make && make install

加入环境变量

vim /etc/profile.d/yasm.sh

粘贴进去:

export PATH=$PATH:/usr/local/yasm/bin/

立即生效:

source /etc/profile
echo "/usr/local/lib">>/etc/ld.so.conf
ldconfig

Node.js

Node.js 安装参考:https://tech1024.com/original/3014 建议安装node的版本最好为8.x,高版本可能不兼容。

# node -v
v8.17.0

STF

npm install -g stf  --unsafe-perm

如果没有报错,就算安装成功了;

启动

先启动rethinkdb,终端不要关闭;

rethinkdb

接着,新开一个终端,运行stf:

stf local --public-ip 192.168.226.11

192.168.226.11 为本机ip; 浏览器打开http://192.168.226.11:7100/ 就可以看到 stf的管理界面了;

手机USB连接电脑,打开手机调试模式;然后在电脑上开启adb查看连接的设备:

# adb devices
List of devices attached
HMMBFQWW99999999        device

再次刷新STF后台,就可以控制手机了。

CentOS7+STF环境搭建

一、简介

OpenSTF是一个手机设备管理平台,可以对手机进行远程管理、调试、远程手机桌面监控等操作,可以批量对大量设备进行WEB端管理。
STF (or Smartphone Test Farm) is a web application for debugging smartphones, smartwatches and other gadgets remotely, from the comfort of your browser.
二、环境搭建
1、基本命令安装
安装wget、zip等命令
yum install wget
yum install -y unzip zip
2、java环境配置
(1)下载jdk安装包并上传至Linux
因为在linux中直接使用curl或者wget下载jdk安装包会被重定向,所以我们要先在windows里先下载好所需的安装包再上传到linux中 jdk1.8官网下载地址 jdk1.9官网下载地址
我这里下载的包是:jdk-8u161-linux-x64.tar.gz

(2).解压安装
对安装包执行解压

[root@localhost ~]tar -zxvf jdk-8u161-linux-x64.tar.gz
解压出来一个文件夹jdk1.8.0_161
[root@localhost ~]# mv jdk1.8.0_161/ /usr/local/java
(3).配置环境变量
vi /etc/profile
在文件中增加如下内容:
export JAVA_HOME=/usr/local/java/jdk1.8.0_151
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
验证环境是否ok:
java -version

3.android SDK环境配置

首先下载SDK
cd /usr/local 
mkdir android 
cd android 
wget https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip 
unzip sdk-tools-linux-3859397.zip
配置环境变量
vi /etc/profile
在文件中增加如下内容
export PATH=$PATH:/usr/local/android/tools/bin
然后执行
source profile 
查看已安装信息
sdkmanager --list
安装platform-tools
sdkmanager "platform-tools"
配置环境变量
vi /etc/profile
在文件中增加如下内容:
export PATH=$PATH:/usr/local/android/platform-tools
执行
source profile sdkmanager --list
验证环境是否ok:
adb --version

4.node安装

cd /usr/local 
mkdir node 
cd node
wget https://nodejs.org/download/release/v9.0.0/node-v9.0.0-linux-x64.tar.gz 
tar xvf node-v9.0.0-linux-x64.tar.gz 
ln -s /usr/local/node/node-v9.0.0-linux-x64/bin/node /usr/local/bin/node 
ln -s /usr/local/node/node-v9.0.0-linux-x64/bin/npm /usr/local/bin/npm
检查环境
node -v 
npm -v

5.rethinkdb安装

执行:
cd /opt/dong -----即在opt新建一个目录用来用来其他依赖 
wget http://download.rethinkdb.com/centos/7/`uname -m`/rethinkdb.repo -O /etc/yum.repos.d/rethinkdb.repo
yum install rethinkdb
检查环境是否ok:
rethinkdb -v

6.GraphicsMagick安装

1.安装依赖
[root@localhost ~]# yum install -y gcc libpng libjpeg libpng-devel libjpeg-devel ghostscript libtiff libtiff-devel freetype freetype-devel
2、执行:
cd /opt/dong 
wget https://iweb.dl.sourceforge.net/project/graphicsmagick/graphicsmagick/1.3.26/GraphicsMagick-1.3.26.tar.gz 
tar xvf GraphicsMagick-1.3.26.tar.gz 
cd GraphicsMagick-1.3.26 
./configure 
make 
make install
验证环境是否ok:
gm

7.yasm安装

执行:
cd /opt/dong 
wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz 
tar xvf yasm-1.3.0.tar.gz 
cd yasm-1.3.0 
./configure 
make 
make install
验证环境是否ok:
yasm --version

8.libsodium安装

执行:
cd /opt/dong 
wget https://download.libsodium.org/libsodium/releases/libsodium-1.0.15.tar.gz 
tar xvf libsodium-1.0.15.tar.gz 
./configure 
make 
make install
验证环境是否ok:
whereis libsodium

9.zeromq安装

执行:
cd /opt/dong 
wget https://github.com/zeromq/libzmq/releases/download/v4.2.2/zeromq-4.2.2.tar.gz tar xvf zeromq-4.2.2.tar.gz 
cd zeromq-4.2.2 
./configure 
遇到报错,yum install gcc-c++ 
make 
make install

10.protobuf安装

执行:
cd /opt/dong 
wget https://github.com/google/protobuf/releases/download/v3.5.0/protobuf-cpp-3.5.0.tar.gz 
tar xvf protobuf-cpp-3.5.0.tar.gz 
cd protobuf-3.5.0 
./configure --prefix=/usr/local/protobuf 
make 
make install
配置变量:
vi /etc/profile
在文件中增加如下内容:
export PATH=$PATH:/usr/local/protobuf/bin/ 
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/
执行
source profile
验证环境是否ok:
protoc --version

11.pkg-config安装

执行:
cd /opt/dong 
wget http://pkgconfig.freedesktop.org/releases/pkg-config-0.29.2.tar.gz 
tar xvf pkg-config-0.29.2.tar.gz 
cd pkg-config-0.29.2 
./configure --prefix=/usr/local/pkg-config --with-internal-glib 
make 
make install
验证环境是否ok:
pkg-config --version

12.stf安装

执行:
npm install -g stf
如果安装失败,先执行如下命令,再安装
npm config set unsafe-perm=true
下载完成后,进入:
cd /usr/local/node/node-v9.0.0-linux-x64/lib/node_modules/stf/bin 
./stf doctor

检查结果

[root@localhost bin]# ./stf doctor
INF/cli:doctor 10067 [*] OS Arch: x64
INF/cli:doctor 10067 [*] OS Platform: linux
INF/cli:doctor 10067 [*] OS Platform: 3.10.0-327.el7.x86_64
INF/cli:doctor 10067 [*] Using Node 8.9.1
INF/cli:doctor 10067 [*] Using ZeroMQ 4.2.2
INF/cli:doctor 10067 [*] Using RethinkDB 2.3.6
INF/cli:doctor 10067 [*] Using GraphicsMagick 1.3.26
INF/cli:doctor 10067 [*] Using ADB 1.0.39
INF/cli:doctor 10067 [*] Using ProtoBuf 3.5.0
ok,至此环境搭建成功

启动stf

进入stf目录:
cd /usr/local/node/node-v9.0.0-linux-x64/lib/node_modules/stf/bin 
./stf local --public-ip 111.67.203.89 --allow-remote (172.31.3.243位centos服务器地址即stf服务器地址)
在其他地址的电脑上,打开浏览器,输入
http://111.67.203.89:7100
即可访问stf

遇到的问题

1、zmq.node文件错误
转到stf工程根目录执行:
npm rebuild
备注:
如果上述命令失败,可能会出现一个死循环,按Ctrl+C停止,执行npm config set unsafe-perm=true,再执行上述命令

2、libzmq.so.5 not found

cd /etc
vi /etc/ld.so.conf
#新增一行:
/usr/local/zeromq/lib
ldconfig

3、远程访问失败
可能是防火墙未关闭,关闭方法

#检查防火墙状态
firewall-cmd --state
#关闭防火墙
systemctl stop firewalld.service
#禁止开机启动
systemctl disable firewalld.service

从0到1开发自动化测试框架

一、序言

随着项目版本的快速迭代、APP测试有以下几个特点:

  • 首先,功能点多且细,测试工作量大,容易遗漏;
  • 其次,代码模块常改动,回归测试很频繁,测试重复低效;
  • 最后,数据环境多样,用户场景复杂,功能回归覆盖难全面。

为节省成本,保证高效及高质量迭代,我们需采用更高效的测试方式,App自动化测试是较高效的手段。

之前自动测试实践过程中遇到的诸多问题(代码复用率低,Case开发及数据构造繁琐,问题定位困难,学习成本高等),为解决相关痛点问题,我们重新实现了一套APP自动测试框架。本文将着重介绍技术选型、设计思路及百度外卖App的具体实践。

二、自动化测试框架技术选型

一个项目中自动化测试是否能有效的展开,自动化测试框架是关键所在。因此,如何如何构建稳定的、易扩展的自动化的测试项目对于敏捷测试有重要的意义。在设计框架的时候应该尽可能的沿用自动化测试工具已提供的功能,避免重复开发,以减少开发成本。

通过对现有自动化测试工具的原理进行深入分析及优缺点比较,并基于Appium和TestNG两类自动化测试框架解决上述自动化测试中遇到的问题。

  • 首先,通过利用TestNG结合csv的使用,将测试用例数据转化为测试代码中的数据,减少了测试人员录入数据和准备数据的工具;
  • 再次,通过对appium的封装,按照面向对象的思想将测试中用到的页面元素封装成对象,增强测试代码的复用率,并减轻测试人员对底层代码实现的负担,提高测试代码编写效率;
  • 最后,引入失败重跑、失败截屏,并通过reportng生成测试报告的方式,逐步完善测试过程,提高定位问题的速度;
TestNG

Testng是一个开源自动化测试框架,引入了许多新的创新功能,如依赖测试,分组概念,使测试更强大,更容易做到。 旨在涵盖所有类别的测试:单元,功能,端到端,集成等。TestNG框架可以很好地帮我们完成WebDriver+java的页面自动化工作,通过各种注释的灵活运行,可以使你的测试用例更加完美,定制符合要求的测试用例

  1. TestNG是一个设计用来简化广泛的测试需求的测试框架,从单元测试到集成测试。
    这个是TestNG设计的出发点,不仅仅是单元测试,而且可以用于集成测试。设计目标的不同,对比junit的只适合用于单元测试,TestNG无疑走的更远。可以用于集成测试,这个特性是我选择TestNG的最重要的原因。
  2. 测试的过程的三个典型步骤,和junit(4.0)相比,多了一个将测试信息添加到testng.xml文件。
    测试信息尤其是测试数据不再写死在测试代码中,好处就是修改测试数据时不需要修改代码/编译了,从而有助于将测试人员引入单元测试/集成测试。
  3. 基本概念,相比junit的TestCase/TestSuite,TestNG有suite/test/test method三个级别,即将test/test method明确区分开了。
Appium

Appium一个开源、跨平台的测试框架,可以用来测试原生及混合的移动端应用。Appium支持iOS、Android及FirefoxOS平台测试。Appium使用WebDriver的json wire协议,来驱动Apple系统的UIAutomation库、Android系统的UIAutomator框架。
相比其他的移动自动化测试工具,Appium测试由于调用了Selenium的client库使其可以使用任意的语言,包括Python、Ruby、Node.js、Objective-C等。

三、自动化测试框架的设计思路

测试设计过程和测试自动化框架必须作为两个单独的实体来开发。
测试框架应该独立于应用程序;
测试框架应该易于扩展 、维护和增强;
测试策略/设计应该对测试者隐藏测试框架的复杂性。

四、自动化框架介绍

该框架基于Selenium WebDriver开源技术开发。本框架使用Maven工具进行Project管理,采用TestNG工具组织测试,应用CSV文件存储测试数据,实现测试数据与测试用例的分离,方便测试数据管理,降低自动化脚本的维护成本,实现数据驱动。此外,该框架还封装了丰富的Selenium方法关键字,借鉴了QTP语法结构,实现了直观清晰的结构化代码语法,如:Page.Item.Operate,降低自动化代码的冗余与重复。借助Jenkins 进行CI测试,实现测试任务的Schedule 和Report功能,通过Jenkins Master/Slave模式管理虚拟机节点,实现多任务多机器分布式并发的执行管理,从而提高测试效率。

  • 该框架的好处在于:
    1、构建可复用的、稳定的代码集。通过封装appium实现用例执行与数据调用分离,参数化配置常用信息,并提供统一接口;

2、模块化管理自动化测试用例。主要根据TestNG工具的支持参数测试和依赖测试的特点实现;
3、测试结果分析和统计。利用jenkins工具建立持续集成,定期运行自动化测试项目,并将测试结果以定制化的形式展现。

测试框架分层

基于UI测试,我们希望除了支持web测试,还能支持app的测试,可能还需要接口测试,我们就需要考虑分层问题,将测试框架分为三层。上层是管理整个自动化测试的开发,执行以及维护,在比较庞大的项目中,它体现重要的作用,它可以管理整个自动测试,包括自动化测试用例执行的次序、测试脚本的维护、以及集中管理测试用例、测试报告和测试任务等。下层主要是测试脚本的开发,充分的使用相关的测试工具,构建测试驱动,并完成测试业务逻辑。

第一层:数据层

即执行用例时所需要的测试数据,如商户名、空间名、URL等,这些数据用来支撑整个脚本的执行。针对数据层,这里采了用数据驱动的方式。

第二层:驱动层

这一层主要封装各种driver。比如我们针对网页测试,使用selenium-webdriver开发包,针对app测试,我们使用appium开发包。我们在这一层进行封装,通过调用selenium-webdriver,appium提供的原生方法,封装成可读性很强的方法且加上容错机制。以后就算我们要换用其他的第三方包,我们的测试案例层和支持层的方法也不需要做任何的修改。只需要修改driver层实现的方式就可以了。在一层,我们主要实现两个方面的封装,一个是driver的封装,一个是基于基类自然语言函数的封装。

driver封装

我们需要封装,根据参数确实是基于web测试还是基于app测试。比如:

基类封装

主要是封装各种可读性很很强的方法以及将元素定位标识及driver也封装进去。为了支持网页测试和app测试,我们需要两个基类,一个是针对网页操作基类,一个是针对app操作基类。同时为了web和app操作的一致性,我们要求对外提供的方法,必须要将常用的方法保持一致的名字和一样的参数类型及参数个数。
APP基类示例如下:

通过对driver和基类的封装,driver层实现了对网页测试和app测试的支持,并且针对两种测试,都提供了统一的方法,能够方便使用者,使用相同的方法,测试app和web。

第三层:测试案例层
该层是测试案例的具体实现,就像上面写的case那样,用接近自然语言的方式,来实现测试案例。

第四层:支持层
该层主要提供workflow,通用工具,元素库的支持,便于测试案例层直接调用。

  • Workflow:主要封装测试项目中需要经常使用的针对项目的公用方法,供测试案例层直接调用。比如用户登录,注册一个用户,搜索出用户等等经常使用的动作;
  • 通用工具:提供一些通用方法,比如生成指定Page类,文件读取操作,DB操作,http操作支持等等;
  • 元素库:每一个页面元素的定位表达式(xpath,id,name,css,link_text等等表达式)。
    我们的测试案例,都是针对一个个元素进行操作的。将每一个页面的每一个元素,都看成一个继承了基类的特定类。所以,我们的第一步,就需要找到这个元素,定位到这个元素。测试项目的所有元素都放到这里。

第五层:结果保存层
将测试脚本的日志和结果以自定义的方式展示,这里使用了ReportNG,它可以丰富测试结果的展现形式,帮助团队更快定位和解决问题。

五、框架技术要点解析

5.1、PO模式

5.1.1、遇到的问题

使用webdriver做过一段时间的测试就会发现一个对某一个页面的元素进行定位的时候,程序行间充斥着id()、name()、xpath()等方法,这样会造成测试程序的可读性较差,不便于后期的维护以及修改。
虽然我们可以通过添加注释的方法使程序便于理解,但是还是不可以从根本上解决这种问题。我们可以通过对这些方法进行二次封装来避免每次对这些方法的直接调用,通过方法的封装虽然可以实现复用。但是我们发现通过封装无法实现页面元素的逻辑处理和测试数据的独立。

5.1.2、问题的解决办法:引入PO

Page Object模式是Selenium中的一种测试设计模式,是指UI界面上用于与用户进行交互的对象。主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通过调用页面类来获取页面元素,这样巧妙的避免了当页面元素id或者位置变化时,需要改测试页面代码的情况。 当页面元素id变化时,只需要更改测试页Class中页面的属性即可。通过对界面元素的封装减少冗余代码,提高测试用例的可维护性。

一般情况下,对于一个Page Objects对象,它有两个方面的特征:
• 自身元素(WebElement)
• 实现功能 (Services)

仔细分析测试场景,抽出UI测试的核心行为,无非就是:
1、检查点:
页面元素是否存在;
页面元素显示内容是否正确;
页面元素是否可用;
……
2、辅助功能:
等待元素出现;
点击某页面元素;
给元素输入内容;
……

分析抽出来的核心行为,发现这些行为基本都是针对一个个页面元素进行的操作。那么我们就可以做如下的动作:
将页面元素看成一个对象,封装成一个类;
将上面分析得到的核心行为都封装成基类方法。然后确保,任何一个页面元素都继承该基类;
该基类提供类似于自然语言的方法名字,调用这些方法,就能很明确的知道测试案例在做什么检查,在做什么行为,这样就能极大的提高测试案例的可读性。
该基类主要目的是在UI测试中,对元素共性的检查点和辅助方法进行抽取,将它们封装成一个个非常容易读懂的方法,且具有异常处理能力。
经过上述思路的整理,测试用例可以改写成如下:

在实际的使用过程中,可以让不太熟悉代码的QA专门负责测试案例的实现,底层的方法包装可以由经验丰富一些的同学做。

5.2、数据驱动

数据驱动的自动化测试框架是这样的一个框架,从某个数据文件(例如ODBC源文件、Excel文件、Csv文件、ADO对象文件等)中读取输入、输出的测试数据,然后通过变量传入事先录制好的或手工编写的测试脚本中。其中,这些变量被用作传递(输入/输出)用来验证应用程序的测试数据。在这个过程中,数据文件的读取、测试状态和所有测试信息都被编写进测试脚本里;测试数据只包含在数据文件中,而不是脚本里,测试脚本只是一个“驱动”,或者说是一个传送数据的机制。
1、在数据文件中填写测试数据:

2、生成Page类:

3、Page类中初始化页面元素:

基于数据驱动的好处在于:
在应用程序开发的同时就可以同步建立测试脚本,而且当应用功能变动时,只需要修改业务功能部分的脚本;
利用模型化的设计,避免重复的脚本,减少建立或维护脚本的成本。

5.3、失败重跑与失败截图机制

自动化测试过程中,常常由于网络、服务器响应过慢、JS特效及页面渲染时间较长,导致自动化测试失败。针对此类场景,本框架设计了一套NRetry机制,即某个case运行失败后,重跑N次,N可自定义。N次中有一次成功,则继续运行,若N次均失败,则截图、抛错,停止运行。NRetry机制,一定程度上可以降低由于网络、服务器响应过慢导致的自动化执行的不稳定性。

5.3.1、失败自动截图

1、新建一个Java类继承TestListenerAdapter:

2、重写onTestFailure、onTestSkipped等方法,在这些方法中加入截图操作:

3、在testng.xml文件中配置自己编写的监听器类:

5.3.2、失败自动重跑

在运行自动化测试用例的时候,经常会出现一些异常的情况的情况导致用例失败的问题。所以我们可能会希望对于失败的测试用例再重新运行一次,框架中我们结合TestNG来实现这个功能。

  1. 新建TestNGRetry类,实现用例失败自动重跑逻辑:
  2. 添加用例重跑监听器RetryListener,用例失败自动重跑功能:
  3. 在testng.xml文件中配置自己编写的监听器:

5.4、ReportNG

TestNG默认的HTML报表,其默认的报表虽然信息全面,但不易于理解。因此,我们利用ReportNG来替代TestNG默认的report。
ReportNG提供了一种简单的方式来查看测试结果,并能够对结果代码进行着色。还可以通过修改CSS文件来替换默认的输出样式。此外ReportNG还能够生成Junit格式的XML输出。
由于我们使用的是maven,所以我们主要来看看pom.xml的情况:

maven-surefire-plugin 这个插件主要是用于testng的。我们通过该插件,在对应的目录下./target/${timestamp}生成我们的测试报告目录。我们可以看到这个目录的结构。

这里实际上就是reportng的测试报告的生成路径。但是我们想要通过邮件发送会很难,因为html的内容需要加在额外的css,以及js文件。而邮件实际上是不支持外部的css以及js文件的。
HTML的生成

1、定义HTML模版

查看indexMain.html.vm:

下面我们看下生成报告的部分核心代码:

在使用ReportNG替换TestNG自带报告时如果报告中含中文,由于ReportNG 里面Log 是不支持中文的,所以通过修改ReportNG.jar源码来支持报告内中文展示。

生成定制化后的最终报告,如下图所示:

5.5、日志收集

日志是软件开发的重要组成部分。自动化执行过程的日志信息,对于失败用例的分析定位以及全过程的跟踪记录是十分重要的。
相对于简单的输出打印,本框架集成了主流的日志收集工具log4j。Log4j是高度可配置的,并可通过在运行时的外部文件配置。通过配置log4j.properties文件,定义日志级别内容及日志输出路径收集日志信息(诸如:数据库,文件,控制台,UNIX系统日志等),提供快速的调试,维护方便,以及应用程序的运行时信息结构化存储。
配置文件
Log4j可以通过java程序动态设置,该方式明显缺点是:如果需要修改日志输出级别等信息,则必须修改java文件,然后重新编译,很是麻烦;log4j也可以通过配置文件的方式进行设置,目前支持两种格式的配置文件:
xml文件;
properties文件(推荐)。
下面是一个log4j配置文件的完整内容:

5.6、邮件发送

测试报告的发送可以结合Jenkins来实现,通过简单的配置即可实现。可是如果团队没有搭建jenkins或者有时jenkins不可用,我们应该如何去处理这部分的内容呢?
既然邮件不能够依赖jenkins,那肯定得自己去实现这部分的内容了。所以我们还是得依赖一些第三方的jar包。我们在pom.xml配置。

具体的发送邮件的部分代码如下:

六、后续TODO

在后续的版本演进中,将把自动化测试、代码安全扫描、多机并行测试、持续发布都加入了整体过程,真正的做到全过程持续交付。

6.1、夜间构建加入自动化测试

夜间构建会按计划定期触发自动化构建过程,但这种构建只是简单的代码编译,没有可靠的或可重复的功能测试。后续考虑Appium结合Jenkins来实现构建后自动化测试工作。
无论任何时候,只要代码更新提交到git中,构建服务器就会触发一个构建,构建运行脚本去编译应用程序并且运行一系列的自动化单元测试和/或集成测试。通过自动化测试结果能够清晰的展示出那些功能特性是通过的,哪些是失败的。不管是有改动提交,还是定期在夜间触发构建,应用程序都会被自动部署到测试环境当中以便QA团队进行测试。

6.2、Jenkins与STF结合,实现多机并行测试

Jenkins构建脚本完成后,将没有安装stf组件电脑上连接的android设备,添加映射到装有stf平台服务的机器上,将集成测试用例push到STF平台,再由STF分发到可运行设备上,进行多机并行测试。
STF执行APPIUM测试带来的优势

第一、可以在真机上执行并行的Appium测试。由于最初的Appium使用对象是模拟器上或只是以每次一台设备的测试方法执行测试,而STF在原有的基础上扩展了Appium,最多可在数百台真机上同时执行测试的能力。
第二,不需要配置任何设备的Desired Capabilities。这种方式既简便,且减少了因为编辑脚本而产生的不同类型的错误。
第三,在STF上执行测试可以让用户即时浏览测试状况。也就是说,可以查看到测试执行的进度,即时的错误反馈,以及保留和查阅所有测试项目,测试脚本和测试结果(测试截图,测试日志,性能数据等)

6.3、代码质量度量

6.3.1、为什么要分析代码

对代码质量关注时,安排人工进行code review是需要的,但100%的code review却需要投入人员,消耗大量的工作量,而工具自动检查只需少量人工配置。
最主要的原因就是提高代码质量,了解RD在编码过程中犯过的错误可能对功能逻辑产生的影响,同时也推动RD让自己的代码更具有可读性和维护性,所以我们借鉴持续改进的流程,希望能够在这个过程中有所收获。

6.3.2、Jenkins引入Sonarqube进行代码持续审查

Sonar是一个用于代码质量管理的开源平台,用于管理Java源代码的质量。通过插件机制,Sonar 可以集成不同的测试工具,代码分析工具,以及持续集成工具,比如pmd-cpd、checkstyle、findbugs、Jenkins。通过不同的插件对这些结果进行再加工处理,通过量化的方式度量代码质量的变化,从而可以方便地对不同规模和种类的工程进行代码质量管理。

6.4、email-ext实现Jenkins邮件通知功能

在Jenkins中配置实现邮件通知,Jenkins提供了两种方式的配置。
一种是Jenkins内置默认的邮件通知,但是它本身有很多局限性,比如它的邮件通知无法提供详细的邮件内容、无法定义发送邮件的格式、无法定义灵活的邮件接收配置等等。
在这样的情况下,后续考虑可以通过Email Extension Plugin来实现自定义邮件通知的方方面面,比如在发送邮件的同时可以自定义发送给谁,发送具体什么内容等等。

python+minicap的使用

说起Minicap,不得不提到STF,STF (Smartphone Test Farm) 是一个开源的web架构应用,用户可通过浏览器远程操作Android设备、调试Android应用、在设备上进行测试,实现真正意义云端使用、调试、测试、管理真机器。STF出现以后,国内几个大互联网公司也纷纷跟进效仿,出现了类似的真机调试、管理平台,较为知名的有腾讯Wetest、阿里MQC、百度MTCTestIn等。可见远程真机调试在移动研发领域的作用还是受到了比较高的重视,也能为公司以及用户带来比较直接的收益。下面是STF官方的介绍动画。

STF

minicap简介

minicap属于STF框架的一个工具,由STF团队自身开发,属于较为核心的一部分,minicap运行于android设备端,负责设备屏幕视频的实时采集并通过socket接口发送,github下载地址:https://github.com/openstf/minicapmicicap。minicap采集屏幕的原理很简单:通过ndk的截屏接口不停的截屏并通过socket接口实时发送,这样客户端便可以得到一序列的图片流,图片流合成后就成为视频;

构建minicap

micicap由Android ndk开发,包含一个可执行的二进制文件以及一个so文件,运行minicap前,需要通过adb命令将设备对应CPU架构以及设备对应SDK版本的minicap文件拷贝到设备后,再执行。由于github上并没有上传编译完成后的产物,因此我们需要自行编译。

编译依赖环境:

1)、NDK;

2)、make;

3)、git;

环境依赖较为简单,如果没有NDK以及make环境的,可自行百度安装;

构建过程:

1)、通过git下载minicamp源码:

git clone https://github.com/openstf/minicap.git

2)、micicap项目还依赖于libjpeg-turbo,首先我们需要在minicap引入libjpeg-turbo项目源码:

git submodule init

git submodule update

3)、执行ndk-build,构建完成后,minicap编译后的产物将会在libs目录下找到;

ndk-build

运行minicap

1)、获取设备CPU支持的ABI,minicap针对4种不同的ABI构建了不同的so文件和可执行文件,分别是:x86_64/x86/arm64-v8a/armeabi-v7a;

ABI=$(adb shell getprop ro.product.cpu.abi|tr -d’\r’)

2)、拷贝对应ABI版本的文件到设备,这里使用的是adb push;

adb push libs/$ABI/minicap /data/local/tmp/

3)、获取设备对应的SDK版本;

SDK=$(adb shell getprop ro.build.version.sdk|tr -d’\r’)

4)、只有可执行文件是不够的,我们还需要拷贝对应sdk版本的共享库到设备;

adb push jni/minicap-shared/aosp/libs/android-$SDK/$ABI/minicap.so /data/local/tmp/

5)、每次启动minicap,我们都需要设置LD_LIBRARY_PATH,不然会提示找不到公共库,-P后面的参数为:{RealWidth}x{RealHeight}@{VirtualWidth}x{VirtualHeight}/{Orientation},可以指定采集的实际大小、虚拟大小以及屏幕方向,实际大小一般设置成设备物理分辨率大小,虚拟大小是通过socket接口发送的大小,屏幕实际窗口大小我们可以通过adb命令获取;

adb shell dumpsys window | grep -Eo ‘init=\d+x\d+’ | head -1 | cut -d= -f 2

6)、启动minicap,下面我们假设获取到的实际屏幕大小是1080×1920,需要发送的虚拟窗口大小是540×960,采集的屏幕方向是纵向;

adb shell LD_LIBRARY_PATH=/data/local/tmp /data/local/tmp/minicap -P 1080×1920@1080×1920/0

7)、端口转发,通过adb forward命令,可以把minicap端口映射到我们PC指定的端口,localabstract:minicap是UNIX域名的SOCKET名称,把minicap的socket端口映射到PC的1313端口,这样我们就可以在PC通过连接1313端口获取到设备的实时视频流;

adb forward tcp:1313 localabstract:minicap

minicap协议解析

minicap启动并用adb forward命令映射端口后,我们就可以通过socket与minicap建立连接。

1)、Global header

minicap协议是一种简单的二进制流推送流协议,一旦与minicap建立连接,minicap首先会推送长度为24字节的global header,global header只会推送一次,后续推送的数据不会再包括global header,而是不断的推送实时图片流数据,直到客户端关闭socket连接。

Global header binary format

Global header说包含了基本的一些信息,如minicap的版本信息、头长度、实际大小以及虚拟大小、设备方向等,这些信息我们可以保存起来,方便后面使用,这里我使用python解析了Global header,代码参考如下:

2)、Frame binary format

接下来,minicap会不断的推送一帧一帧的图片流,每一帧都包含两部分信息:0-3字节,表示这一帧图片的长度n,由4个字节的32位整型小端格式存储;4-(n+4)字节,是具体的图片数据,由JPG格式存储,这部分才是我们想要的最关键数据;

Frame binary format

至此,我们完成了minicap协议的解析,并获取到了minicap推送过来的每一帧图片。需要注意的是,由于minicap是实时推送流,因此流的数据可能会比较大,客户端获取的buffer需要尽可能的大,不然我们在渲染每一帧的时候,可能会出现卡顿的现象,具体多大合适,我们可以稍微推算一下,一张由minicap推送过来的1080×1920大小的png图片,大概是100-200KB,minicap宣称帧率可以达到20 FPS左右,因此我们的buffer可以设置为:200KB * 20 = 4096000字节,每隔一秒recv()一次;

PyQt实时渲染

获取到图片流数据后,我们可以使用PyQt中的paintEvent进行渲染,下面的refreshFrame()方法,关联了获取图片线程中的一个信号槽,一旦获取图片线程从minicap解析到一帧的图片,便会通知refreshFrame()中的self.update()方法,self.update()方法则会调用paintEvent进行界面的刷新:

美团点评云真机平台实践

背景

随着美团点评业务越来越多,研发团队越来越庞大,对测试手机的需求显著增长。这对公司来说是一笔不小的开支,但现有测试手机资源分配不均,利用率也非常有限,导致各个团队开发、测试过程中都很难做到多机型覆盖。怎么样合理、高效利用这些测试手机资源,是摆在我们面前的一道难题。

现有的方案

为了解决这些问题,业内也出现了一些手机管理和在线调试使用的工具或平台,比较常见的有:

  • OpenSTF
  • 百度MTC的远程真机调试
  • Testin的云真机
  • 腾讯WeTest的云真机
  • 阿里MQC的远程真机租用

其中OpenSTF是开源项目,其他的平台大多也都是基于OpenSTF原理实现的。因此,我们对OpenSTF项目进行了深入研究。

遇到的问题

我们首先按照OpenSTF官方的方案进行了搭建,并进行了小规模的应用,但渐渐的我们发现了它的一些问题:

  • 模块过多而且耦合紧密,解耦难度较大,每次修改需要更新所有模块,难以快速迭代开发。
  • 部分技术选型落后。由于OpenSTF出现的时间比较早,部分技术已经落后于目前的主流。例如OpenSTF前端选用AngularJS 1.0进行开发,在生态链方面已经落后于其他流行的框架;数据库方面选用非关系型数据库RethinkDB,在数据计算和性能方面弱于MySQL等关系型数据库,同时RethinkDB资料较少,不便于开发与维护。
  • OpenSTF屏幕图像传输采用图片单张传输的方式进行,而且画质不能由用户来调节,实际应用中占用带宽很高,在网络比较差的情况下会有严重的卡顿现象,体验很差。

我们的方案

架构设计

根据业务场景的需要,并吸取了OpenSTF结构优点,我们采用Agent/Server模型的模块化设计方案。下面分别介绍主要模块的功能:

  • Agent模块。Agent模块与OpenSTF的provider类似,部署在服务器上或者用户的电脑上,Agent连接真实的手机,并且将手机的屏幕图像通过Websocket动态代理到Websocket服务器上,然后通过消息中心来进行消息的传递。
  • Server模块。Server用来集中管理和调度手机,与OpenSTF结构不同的是,我们的Server端包含Web服务器、Websocket服务器、动态代理以及消息处理服务等部分,Server将用户的访问动态代理到对应的Web服务器和Websocket服务器上,并通过消息处理模块向消息中心传递消息,实现用户与Agent端手机的交互。
  • 数据存储模块。数据存储模块用来保存整个平台的数据,例如手机的状态、用户使用记录等。数据存储模块由MySQL数据库和一个RPC服务组成,Server不再直接读写数据库,而是通过一个RPC服务来进行数据的读写操作。
  • 消息中心。与OpenSTF的triproxy功能类似,是连接手机和Server的枢纽,消息中心主要处理屏幕的操作以及手机的状态变更等消息。

通过模块化设计,项目结构比OpenSTF更加清晰。下面是整个系统的设计图:

架构的优势

Agent模块我们直接复用了OpenSTF的provider大部分功能,包括minicap、minitouch等。在此基础上,我们也扩展了一部分OpenSTF缺失的功能,比如:

  • 在provider的基础上进行了二次开发,使其支持画质/帧率调节(下文会有详细说明)。
  • 加入健康检测功能,检测手机网络是否正常、是否设置了网络代理等。
  • 加入Inspector功能,方便获取UI控件树(下文会有详细说明)。
  • 对Agent进行了版本区分,便于Web端根据不同的Agent版本对相应的功能展示和隐藏。

在Server模块中,我们引入了动态代理的机制,并且重新开发了Web部分,采用了Vue 2.0 + iView来实现,数据库采用了MySQL。

相比OpenSTF原生架构,总结下来有以下优势:

  • 模块耦合程度低,开发和部署更方便。OpenSTF各个功能模块不仅数量多而且代码耦合紧密,在此基础上进行二次开发和部署非常困难。而我们将整个项目分为Server、Agent、消息中心、数据存储四个模块,四个模块功能和代码都是独立的,基本上没有耦合关系,支持快速迭代开发,部署也很方便。
  • 前端框架更主流,开发和维护成本低。OpenSTF前端是使用AngularJS 1.0实现的,AngularJS 1.0已经处于废弃阶段,各种第三方组件基本已经停止支持,AngularJS 2.0的社区和生态并未成熟,而我们采用了Vue 2.0前端框架,Vue 2.0相对已经成熟,在美团侧也已经有大量应用,能够快速开发高质量的Web功能。
  • 数据库性能强,设计灵活、维护方便。OpenSTF使用RethikDB作为数据库,RethikDB是一个NoSQL型数据库,它有非常多的缺点,比如处理大量数据时的性能很差,资料非常匮乏,排查问题和数据库维护都非常困难。而我们采用了MySQL数据库,很好的解决了这些问题,并且实现了Server模块与数据读写的分离,这样在更新数据库表结构的时候无须同时修改Server端的代码,只要保证RPC服务的接口格式一致即可,开发和维护更加方便。

除了这些基础的功能之外,我们还开发了一些特色的功能,下面我们来详细介绍。

特色功能

与客户端自动化相结合

为了合理、高效利用测试手机资源,我们与客户端自动化进行了结合,主要有两个方面:

  • 与集团内部的云测平台深度融合。在云测平台的服务器节点上部署Agent代码,为云测平台自动化任务创建者提供自动化过程展示和远程调试功能,同时将云测平台空闲的手机开放给更多人使用。
  • 开放API。我们开放了一些API给普通用户,供用户查询手机状态、占用手机、连接adb调试等,用户可以使用脚本调用API,然后直接在平台的手机上进行自动化测试。

预约功能

当一台手机处于繁忙状态时,用户必须要等待手机空闲后才能使用,由于手机空闲时间不确定,就会给用户带来很大的不便。为了解决这个问题,我们开发了手机预约的功能,用户可以预约处于繁忙状态的手机,当手机空闲时,自动帮预约用户占用15分钟,并通过即时通讯工具通知预约人。

画质调节

远程调试平台的核心是实时获取屏幕图像,由于屏幕传输需要比较大的网络带宽,在网络不佳的情况下就会出现卡顿现象。因此,我们针对不同的网络做了一些流畅度的优化,下面来介绍一下其中的细节。

屏幕获取的原理是通过minicap来高速截图,每秒最高可达60张,然后将这些截图显示在Web上。因此,我们考虑从两个方面来优化网络带宽的占用,第一个是调节截图的质量,minicap本身支持调节画质(OpenSTF固定设置了80%的压缩比),关键代码如下:

var rate =  Number(match[6])
    if (rate > 2 && rate < 100) {
      log.info(rate)
      if (rate > 30) {
        options.screenJpegQuality = 80
      }else if (rate > 15) {
        options.screenJpegQuality = 50
      }else {
        options.screenJpegQuality = 20
      }

      frameProducer.restart()
      framerate = rate
    }

第二个是调节每秒发送的图片张数,也就是帧率,我们可以在Agent端控制发送图片的数量,关键代码如下:

# 首先修改帧率发送部分:
function wsFrameNotifier(frame) {  
  if (latesenttime == 0 || Date.now()-latesenttime > 1000/framerate) {  
    latesenttime = Date.now()  
    return send(frame, {  
      binary: true  
    })  
  }  
}
# 再加入调整帧率的代码:
case 'rate':  
  var rate =  Number(match[6])  
  if (rate > 2 && rate < 100) {  
    framerate = rate  
  }  
  break

那么,帧率和图片压缩比调节到多少才能满足不同网络环境的需要呢?我们先来看一组数据:

图片压缩比 图片尺寸
100% 69.82KB
80% 46.78KB
50% 41.87KB
20% 37.84KB
10% 35.84KB

表中是使用minicap做的图片压缩实验,从数据中我们可以看到当图片质量降低到80%时图片大小降低比较明显,而图片质量并没有明显的下降。继续降低图片质量,图片大小降低有限。我们再来看另外一组数据:

帧率 图片压缩比 实际流量
60 100% 4.02M/S
60 80% 2.74M/S
60 50% 2.41M/S
30 80% 1.43M/S
30 50% 1.22M/S
30 20% 1.10M/S
15 50% 0.63M/S
15 20% 0.55M/S
15 10% 0.52M/S

表中是各种帧率和压缩比组合产生的实际流量数据。

从数据中我们可以看到最高帧率和压缩比的组合下,流量达到了4M/S,而80%压缩比时流量减小到了2.7M/S,降低非常明显。考虑到实际网络情况,我们将60帧、80%压缩作为了高画质选项

而图片质量从80%降低到50%时图片大小下降并不明显,此时降低帧率就成了很好的选择。当帧率降低到30帧时流量降低了一半,1.2M/S的流量能够满足大部分网络状况使用,30帧也能保证操作的流畅度,于是30帧、50%压缩比成为了中画质的选项

低画质主要是为了保证在较差的网络环境能够正常使用,500K/S的流量是红线。我们将15帧、20%压缩比作为低画质选项,此时图片质量和帧率较低,但能够保证基本的使用体验。

除了通过降低图片质量和帧率来减小手机屏幕图像传输的流量外,将图像使用H264等编码压缩成视频传输也是一种有效降低流量的办法,相对于图片,图像的压缩率将会更高,用户的操作体验也会更好。但是图像压缩编码原理比较复杂,相关技术我们还在研究当中。

App Mock

在做App测试过程中经常需要抓包,一般情况下,我们通过修改WiFi的代理然后用抓包工具就可以实现。但是这样做的效率比较低,多个工具切换也非常不便。借助集团的Mock平台,我们开发了一键Mock功能,能够快速完成相应App的Mock操作。带来的好处是我们可以一边操作App,一边查看App发出的请求,大大提高了测试的效率。

App Inspector

App Inspector功能可以让用户在平台上使用真机的同时查看页面控件树及页面元素,并且支持Xpath,更加方便高效的查找页面元素,给UI自动化测试提供了很大便利。

这个功能我们是借助Uiautomator实现的。基本原理是写一个Uiautomator用例,用来获取当前页面的Hierarchy,然后将用例打包成一个JAR放到Agent端。当在Web端触发获取控件树时,Agent将JAR包推送到手机上并运行,此时会在手机端生成一个XML文件。然后再使用cat命令获取XML内容并在前端解析。用例核心代码如下:

public class launch extends UiAutomatorTestCase {

    public void testDumpHierarchy() throws UiObjectNotFoundException {
        File file = new File("/data/local/tmp/local/tmp/uidump.xml");
        UiDevice uiDevice = getUiDevice();
        String filename = "uidump.xml";
        uiDevice.dumpWindowHierarchy(filename);
    } }

当然,你也可以用adb命令来获取Hierarchy:

adb shell uiautomator dump /data/local/tmp/uidump.xml

但这种方式不能获取动态页面,比如视频播放页面。

数据报表

为了更好的了解平台的运营情况,我们做了详细的数据统计,主要从使用次数、使用时间、设备数量、使用分布等方面进行统计。目前我们管理的手机近300台,平均每个月有超过500名研发人员在使用我们的平台,每天的使用次数达到280次,每天总使用时长超过60小时。

其他小功能

除了以上几个比较大的功能点,我们也做了一些贴心的小功能,比如:检测手机网络是否设置代理、检测手机已安装的应用版本及安装时间、快速安装最新版本的测试包、支持App内的Schema跳转等等。这些小功能为研发人员节省了很多时间,提升了他们的工作效率。

未来规划

iOS手机支持

目前,云真机平台只支持Android手机,对iOS手机的支持正在进行中。我们已经初步完成了主要功能的开发,预计很快将与大家见面。

产品优化

我们计划继续扩展产品功能,比如支持Log日志展示和性能数据采集等。目前云真机平台已经在美团点评内部平稳运行超过两年,我们会继续不断迭代版本、打磨产品,提供更好的使用体验。