使用 Appium 进行多设备的集群分布式 UI 自动化测试

时间:2021-04-29 16:39:06

在TesterHome挺久了,一般是看帖比较少发,
最近有看到一些同学做多设备的Appium测试有碰到一些问题。
刚好自己前段也涉及到类似的方案,在这里分享些自己这段碰到的一些问题阻碍,和解决的一些思路吧,刚涉及UI自动化不久,很多东西还很生疏,欢迎大家提点。

1.需求和条件制约
最早需求的提出,场景的要求是要同时实现几十台设备的UI自动化测试且是有客户端的交互行为,部分设备运行的APP需要等待其他设备的APP进行操作。
APP是Hybrid类型的,内嵌了webview,且该webview是自定义过的,robutim是无法识别到控件,尝试过录制器也无法用,而尝试了appium则是可以使用的因为是chromedriver控制的。
设备数量大概是在60左右,要求持续运行较久的时间,那么设备需要持续USB供电,就不能直接连PC跑脚本(PS:PC也没那么多口接这么多设备)
那么需求就清晰了:用appium在同个用例里进行60台设备的UI自动化控制。

2.方案实施
1. 首先因为无法USB连接,这里全部都使用无线ADB连接,之前有同学写过使用无线adb工具进行连接的文章,其实只要有root权限,一个命令就可以搞定了。
在cmd运行adb tcpip 5555,可以启动5555端口的监听,如果需要切换回usb则运行adb usb

使用 Appium 进行多设备的集群分布式 UI 自动化测试
之后通过adb connect IP 进行设备的无线调试连接,adb disconnect IP来断开连接
使用 Appium 进行多设备的集群分布式 UI 自动化测试

2.然后开始多设备时的Appium Server控制,因为Appium Server与设备要一一对应,所以需要启动较多的server,所以肯定不选择windows版本的server控制,因为启动需要手动去点击,出现问题也无法重新启动。
那么就使用命令行模式的(PS:部分同学因为被墙的原因无法npm进行安装,这里有个小技巧,可以帮助你们装完windows版的appium server后依然可以使用命令行的:传送门)

设计AppiumServer类来进行Server的批量启动控制如下。

public class AppiumServer {
LogUtil log = new LogUtil();

public AppiumServer(){
KillTask("node.exe");
log.info("init appium server...");
}

public void KillTask(String taskname){
String Command = "taskkill /F /im " + taskname;
log.info("kill " + taskname + " task ...");
runCommand(Command);
}

public void runServer(int port,String udid) {
log.info("run " + udid + " Appium Server in port " + port + "...");
int bpport = port +1;
int chromeport = port + 4792;
//多设备server端需要手动指定每台设备的udid,安卓无线连接下就是设备的ip:port..
String Command = "appium.cmd -p " + port + " -bp " + bpport + " --session-override --chromedriver-port "+ chromeport +" -U "
+ udid + " >c://" + port + ".txt";
log.info(Command);
runCommand(Command);
}

private void runCommand(String command){
try {
Runtime.getRuntime().exec(command);
} catch (IOException e) {
e.printStackTrace();
}
}

启动server

    AppiumServer AS = new AppiumServer();
AS.runServer(4723, "192.168.1.17:5555");

3.对于同时启动大量的AppiumServer运行webview的测试,在实际运行时,出现问题了,当启动的设备超过十几台时候,adb的进程数会达到几十个,数量达到一定程度后,adb会停止响应并结束进程断开所有设备,而且webview进行测试的时候会需要启动chromedriver进程,与设备也是一一对应,启动超过十几个进程并行执行,也会出现很多不稳定的不识别或者停止响应的情况。
针对这个问题,其实原因还是windows下的adb太脆弱了,结合Appium的Server支持远程执行的情况,搭建多台Linux环境的PC来做Appium Server端的运行执行(最后实际测试linux下同时可以承载30+台设备妥妥的),Server的启动控制使用STAF进行控制。(PS:STAF环境搭建之后再整理份,不过百度下应该挺多)
搭建好STAF环境后,导入JSTAF.jar并增加staf的运行控制方法如下

import com.ibm.staf.STAFException;
import com.ibm.staf.STAFHandle;

......
private void runRemoteCommand(String command){
try {
handle = new STAFHandle("MySTAF");
} catch (STAFException e) {
System.out.println("Error registering with STAF, RC: " + e.rc);
}
String service = "PROCESS";
String request = "start command shell \"" + command + "\"";
try {
handle.submit2(ServerIP, service, request);
handle.unRegister();
} catch (STAFException e) {
System.out.println("run process error");
}
}

修改LinuxServer的启动方法如下:

private String LinuxAppiumPath = "/usr/local/lib/node_modules/appium/bin";
public AppiumServer(String ServerType, String ip){
this.setServerType(ServerType);
this.setServerIP(ip);
this.isRemote = true;
KillTask("node");
log.info("init remote appium server at "+ ip +"...");
}
......
public void runLinuxServer(int port,String udid) {
log.info("run " + udid + " Appium Server in port " + port + "...");
int bpport = port +1;
int chromeport = port + 4792;
String Command = "/usr/bin/node " + LinuxAppiumPath +"/appium.js -a " + ServerIP +" -p " + port + " -bp " + bpport + " --session-override --chromedriver-port "+ chromeport +" -U " + udid + " >/home/wang/log/" + port + ".log";
log.info(Command);
runRemoteCommand(Command);
}

(当然AppiumServer类还需要进行一些对应的逻辑调整,比如区分开远程和本地的Server执行的方法,区分Server的Type,区分IP等。这里就不细说了)
3.流程图
大致画了个简单原理的流程图如下:

使用 Appium 进行多设备的集群分布式 UI 自动化测试

4.运行结果
具体的用例构建和脚本是用testNG加testReport来处理的,这里也不细写了,运行的部分日志结果如下:

使用 Appium 进行多设备的集群分布式 UI 自动化测试