前言:
随着产品发布的周期越来越快, 行业对测试的要求也越来越高; 往往需要在很短的时间内完成
多端测试(Android iOS 小程序、H5)、
多环境测试(联调环境、测试环境、预发布环境)、
多机型覆盖(后逃统计到的top20 or top50?)
多版本共存(历史版本兼容?)
历史用例的回归(回归测试时的覆盖面?)
这些问题都在推动这整个行业去寻求技术的突破, 自动化测试就是能够保证产品质量的一个重要手段, 其与企业
产品线的CI CD 集成 完成回归测试 兼容性及自动化探索测试等;今天主要整理下UI自动化测试技术中的主流技术
手段 Appium.
使用分层测试策略,控制UI自动化测试规模(在决定做UI自动化前 一定要确定其主要解决的问题)
- 少数核心用例交给自动化测试
- 大部分的基础回归测试交给自动遍历
- 新功能测试交给人工测试
一、Appium应用原理:
Appium是一个独立的模块,使用的时候需要我们启动它; 当开启appium服务器的同时就开启了监听端口;我们运行脚本的时候,调用任何的appiumAPI,都会向Appium Server端post一条HTTP请求,(我们可以使用任何方式去发送交互的post http请求, 各语言脚本,或者是自定义curl等,只要请求符合webdirver协议 );请求内容就是根据webdriver wire protocol协议规定的一条JSON格式的数据;Appium Server端接收到请求后,解析出JSON数据并发送到手机端;(appium会给手机端发送一个apk, apk在手机上会监听一个forword端口) 手机端上已经由BootStrap.jar(iOS为BootStrip.js)开启的socket服务器监听相应的端口,BootStrap.jar在appium每个session第一次访问手机端的时候会自动安装;手机端接收到对应的请求后,通过BootStrap.jar翻译成UIAutomator能执行的命令,然后通过UIAutomator处理并操作APP完成测试。下面通过分析脚本与appium通讯日志 以及 appium与移动设备通讯日志来分析其运行原理.
二、使用Appium 启动一个app实例来展示appium的工作流程
- 分析Appium的log 分析其工作流程 其中存储来appium工作流中的关键数据 可以使用appium -p 5723 -g /tmp/appium.log 将appium产生的log导出到本地分析;
- 监听webdriver 通过tcpdump抓包分析 协议通讯流程
- 分析uiautomator的log
$(which emulator) -list-avds 查找可用的模拟器
$(which emulator) @XXX 启动xxx模拟器
启动Appium服务; start一个Session 然后导出logs
Running '/Users/wangjianqing/Applications/adt-bundle-mac-x86_64-20131030/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys window'
主要分析Running 中的
adb -P 5037 -s emulator-5554 shell dumpsys window'
-P adb开的端口 -s 对应的设备 后面对应的执行脚本
为了便于分析, 将android 中的adb 替换成如下脚本 将adb mock掉 原adb 改成adb.bak mv adb adb.bak
```
log=/tmp/adb.log
echo "# $$ "$(date "+%Y/%m/%d %H:%M:%S") >> $log
echo "# ppid: $(ps -o command $(ps -o ppid $$ | tail -1) | tail -1)" >> $log
echo "adb $@" >> $log
if echo "$@" | grep -E "logcat |exec-out |uiautomator runtest" &>/dev/null; then
echo "exec" >> $log
exec /Users/wangjianqing/Applications/adt-bundle-mac-x86_64-20131030/sdk/platform-tools/adb.bak "$@"
elif echo "$@" | grep "dumpsys package io.appium.settings" &>/dev/null; then
echo "mock" >> $log
cat /Users/wangjianqing/temp/appium/package.mock | tee -a $log
elif echo "$@" | grep "io\.appium\.settings" &>/dev/null;then
echo "mock" >> $log
echo "11111" | tee -a $log
else
result=$(/Users/wangjianqing/Applications/adt-bundle-mac-x86_64-20131030/sdk/platform-tools/adb.bak "$@")
echo "origin" >> $log
echo "$result" | tee -a $log
fi
echo "" >> $log
```
将adb替换完成后, 默认会使用脚本中的adb执行逻辑; 执行完的log会保存到 /tmp/adb.log中; 如执行adb devices 之后,打开log日志如下:
# 3779 2019/08/12 22:54:42
# ppid: -bash
adb devices
origin
List of devices attached
emulator-5554 device
此时再次使用appium'时生成的log就会是使用新adb产生的简化结果日志;
2、
使用curl命令来给appium发送请求,让它执行启动app的操作:
curl -H "Content-Type: application/json; charset=utf-8" \
-H "Cache-Control: no-cache" \
--data '{"desiredCapabilities":{"appActivity":".view.WelcomeActivityAlias","appPackage":"com.xueqiu.android","autoGrantPermissions":"true","deviceName":"hogwarts","platformName":"android","newCommandTimeout":0,"connectHardwareKeyboard":true}}' \
-XPOST http://127.0.0.1:5723/wd/hub/session
如果要封装Appium 的话,首先要知道它做了什么,才能做到使用你自己的语言或方式去操作appium,可以直接按照webdriver协议规范封装发送请求 ,编写appium前端.
使用tcpdump监听webdriver协议操作过程中的端口,包括操作脚本与appium通讯的端口和appium和手机交互过程中的通讯端口
adb forword
appium在和手机交互 会向手机推送一个apk ,这个apk启动后会监听一个端口,会把手机上的命令通过 forword命令映射到你的PC上去;你的PC机更多的是和
forword端口来和手机通讯;
sudo tcpdump -i any port 5723 or port 4724 -vv -w /tmp/tcpdump.1 #5723是appium端口 4724是forword端口 将发送到这两个端口的请求都录下来
然后使用wireshark打开tcpdump 选择某个tcp右键follow Http可以查看具体的请求
POST /wd/hub/session HTTP/1.1
Connection: keep-alive
User-Agent: admc/wd/1.11.1
Accept: application/json
Content-Type: application/json; charset=UTF-8
Content-Length: 234
host: 127.0.0.1:5723
{"desiredCapabilities":{"appActivity":".view.WelcomeActivityAlias","appPackage":"com.xueqiu.android","autoGrantPermissions":"true","deviceName":"hogwarts","platformName":"android","newCommandTimeout":0,"connectHardwareKeyboard":true}}HTTP/1.1 200 OK
X-Powered-By: Express
Vary: X-HTTP-Method-Override
Content-Type: application/json; charset=utf-8
Content-Length: 856
ETag: W/"358-h2tUi1B25lJ0BAIZ1c7Eh+Nw5yY"
Date: Fri, 05 Jul 2019 13:19:54 GMT
Connection: keep-alive
{"status":0,"value":{"platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"appActivity":".view.WelcomeActivityAlias","appPackage":"com.xueqiu.android","autoGrantPermissions":true,"deviceName":"hogwarts","platformName":"android","newCommandTimeout":0,"connectHardwareKeyboard":true},"appActivity":".view.WelcomeActivityAlias","appPackage":"com.xueqiu.android","autoGrantPermissions":true,"deviceName":"emulator-5554","platformName":"android","newCommandTimeout":0,"connectHardwareKeyboard":true,"deviceUDID":"emulator-5554","platformVersion":"8.0.0","deviceScreenSize":"1080x1920","deviceModel":