1. STest软件测试社区首页
  2. APP测试

UIAutomatorview简单封装与Appium Boostrap结合

本帖已被设为精华帖!,

前几天稍微改装了一下 UIAutoatorview 生成脚本,刚发完帖子发现论坛已经有人发出来了,闭门造车不是个好习惯哈,我做这个东西的初衷呢?就是是这段时间学习APPIUM觉得写脚本调式费劲,就是想能确定元素是否真的可以定位到,可以执行,最终的一切都是为了支持Appium的执行,目前程序完成的比较粗糙,健壮性也不太好,主要是为了给不是特别深入的朋友提供些思路和参考


我这里面的检查执行呢?底层调用时通过Appium的Bootstrap实现,这样才能保持和Appium环境一致,如果用坐标点确定的话,生成的脚本放到Appium里面也不一定是有效的,执行环境变了


具体实现,大家看过Bootstrap的会知道,Bootstrap其实是发布了一个Socket服务端,并且是长连接,所以当Bootstrap运行起来我们可以通过Socket去连接发送请求

/**
* @Descrition:执行初始化连接
* */

public void init() {
try {
String host = "127.0.0.1";
int port = 4724;
InetSocketAddress remote = new InetSocketAddress(host, port);
sc = SocketChannel.open();
sc.connect(remote);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @Descrition:发送请求
* */

public void sendMsg(){
boolean run = true;
while (run) {


String sendMsg = QueueMsg.getSendMsg(); //这里简单弄了个队列信息
if (null!=sendMsg&&!sendMsg.equals("")) {
printMsg(sendMsg, sendMsg);
InputStream inputStream = new ByteArrayInputStream(sendMsg.getBytes());
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String str = br.readLine();
printMsg(sendMsg, "读入一行数据,开始发送...");
w_bBuf = ByteBuffer.wrap(str.getBytes("UTF-8"));
//将缓冲区中数据写入通道
sc.write(w_bBuf);
printMsg(sendMsg, "数据发送成功...");
w_bBuf.clear();
printMsg(sendMsg, "接收服务器端响应消息...");
try {
Thread.currentThread();
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
r_bBuf.clear();
//将字节序列从此通道中读入给定的缓冲区r_bBuf
sc.read(r_bBuf);
r_bBuf.flip();
String resultMsg = Charset.forName("UTF-8").decode(r_bBuf).toString();
QueueMsg.setResultMsg(resultMsg);
}
}
}

我们看UIAutomatorView这个工具去Dump控件文件会发现它是执行的UIAutoamtor,Boostrap也是执行的UIAutoamtor,那么我们启动Boostrap之后,线程是阻塞的,所以在用UIAutomatorView去Dump是无法Dump的,所以我们需要对Boostrap进行改造一下,通过Boostrap去Dump控件文件

首先在Boostrap中的AndroidCommandExecutor.java类要加入一行命令

map.put("dump", new Dump());

然后写一个Dump类

public class Dump extends CommandHandler {
private static final File dumpFolder = new File(Environment.getDataDirectory(), "local/tmp");
private static final String dumpFileName = "myuidump.xml";
@Override
public AndroidCommandResult execute(AndroidCommand command) {
File file = new File(dumpFolder, dumpFileName);
try {
QueryController queryController = UiAutomatorBridge.getInstance().getQueryController();
AccessibilityNodeInfo accessibilityRootNode = queryController.getAccessibilityRootNode();
String msg = "success";
try {
AccessibilityNodeInfoDumper.dumpWindowToFile(accessibilityRootNode, file);
} catch (Exception e) {
msg = e.toString();
}
return getSuccessResult(msg);
} catch (final Exception e) {
Logger.debug("Dump Exception: " + e);
return getErrorResult(e.getMessage());
}
}
}

完成之后重新打Bootstrap放到设备里

UIAutomator里面的UiAutomatorHelper类的getUiHierarchyFile方法要改动一下,通过Bootstrap去Dump控件文件

monitor.subTask("Taking UI XML snapshot...");
//原来的Dunp方法

//try {
// device.executeShellCommand(
// command,
// new CollectingOutputReceiver(commandCompleteLatch),
// XML_CAPTURE_TIMEOUT_SEC * 1000);
// commandCompleteLatch.await(XML_CAPTURE_TIMEOUT_SEC, TimeUnit.SECONDS);
//
// monitor.subTask("Pull UI XML snapshot from device...");
// device.getSyncService().pullFile(UIDUMP_DEVICE_PATH,
// dst.getAbsolutePath(), SyncService.getNullProgressMonitor());
// } catch (Exception e) {
// throw new RuntimeException(e);
// }


//修改后的Dunp方法
try {
QueueMsg.setSendMsg("{\"cmd\":\"action\",\"action\":\"dump\",\"params\":{}} ");
monitor.subTask("Pull UI XML snapshot from device...");
String value = QueueMsg.getResultMsg();
BootstrapCmdDomain bootstrapCmdDomain = JSON.parseObject(value, BootstrapCmdDomain.class);
int status = bootstrapCmdDomain.getStatus();
if (0 == status) {
device.getSyncService().pullFile(MyUIDUMP_DEVICE_PATH,
dst.getAbsolutePath(), SyncService.getNullProgressMonitor());
} else {
throw new Exception(bootstrapCmdDomain.getValue());
}
} catch (Exception e) {
throw new RuntimeException(e);
}

{\”cmd\”:\”action\”,\”action\”:\”dump\”,\”params\”:{}} 这写个命令可以在Appium的日志里获取,大家看我的命令多打了一个空格,因为Bootstrap读取消息的时候少读了一个字节,会报出转JSON异常,所以这里面一定要多加一个空格。

剩下就是封装一些点击事件,输入文本脚本生成的事情了


完成后的结果,我们可以手动把APP启动起来,然后打开UIAtuomator,弄一个输入的事件

UIAutomatorview简单封装与Appium Boostrap结合


选择一个元素,鼠标右键
UIAutomatorview简单封装与Appium Boostrap结合


确定后设备里面的输入被执行了,右侧的文本框打印出了脚本,这里的打印信息,只有事件被正确执行才能生成脚本,生成的脚本规则是自己定义的,所以这里按照自己的需求写自己的算法


UIAutomatorview简单封装与Appium Boostrap结合


点击事件,我们点击下【搜索按钮】

UIAutomatorview简单封装与Appium Boostrap结合

点击【搜索按钮】后的结果

UIAutomatorview简单封装与Appium Boostrap结合


UI界面什么的都比较粗糙,其实就把它做一个辅助工具,为Appium服务,所有功能OK就可以了,当然大家可以自己加一些拖拽、JS执行、长按等事件的操作

原创文章,作者:AITest,如若转载,请注明出处:http://www.stest.com

发表评论

电子邮件地址不会被公开。 必填项已用*标注

QR code