自动化工具poco源码简单分析

Airtest简介

Airtest是网易游戏开源的一款UI自动化测试项目,目前处于公开测试阶段,该项目分为AirtestIDE、Airtest、Poco、Testlab四个部分,基于python脚本的方式,用于web、windows程序、app自动化测试。
AirtestIDE:跨平台的UI自动化测试编辑器,内置了Airtest和Poco的相关插件功能,能够使用它快速简单地编写脚本;

Airtest:是一个跨平台、基于图像识别的UI自动化测试框架,适用于游戏和App测试,目前支持Windows、Android、IOS平台,原理:利用截图的方式,在已展示出的手机界面中寻找所匹配的图片;

Poco:一款基于UI控件识别的自动化测试框架,目前支持Unity3D/cocos2dx-*/Android原生app/iOS原生app/微信小程序,也可以在其他引擎中自行接入poco-sdk来使用

链接:https://airtest.netease.com/

poco 作用

基于UI控件搜索的自动化测试框架,定位目标控件,然后调用函数方法对目标控件进行操作,安装在android手机上的app
github链接

元素获取: 使用getRootInActiveWindow() ,获取 AccessibilityNodeInfo

无障碍服务api

这个类代表了窗口内容的一个节点,以及可以从源头请求的动作。 从AccessibilityService的角度来看,一个窗口的内容被呈现为可访问节点信息的树状结构,可以一对一映射到视图层次结构

api :
node.isVisibleToUser() 用户是否可见
node.getBoundsInScreen(bound1) 获取节点位置
node.getText() 获取显示文案

案例

@Test
public void getNode() throws Exception {Log.i("TestActivity","Text ");UiDevice  device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());Set<AccessibilityNodeInfo> roots = new HashSet();device.waitForIdle();UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();AccessibilityNodeInfo activeRoot = uiAutomation.getRootInActiveWindow();if (activeRoot != null) {roots.add(activeRoot);}Iterator i$ = uiAutomation.getWindows().iterator();while (i$.hasNext()) {AccessibilityWindowInfo window = (AccessibilityWindowInfo) i$.next();AccessibilityNodeInfo root = window.getRoot();if (root == null) {Log.w("getWindowRoots", String.format("Skipping null root node for window: %s", window.toString()));} else {roots.add(root);Rect outBounds = new Rect();CharSequence text = root.getText();root.getBoundsInScreen(outBounds);Log.i("TestActivity","root "+ new  Gson().toJson(root));if(text != null){Log.i("TestActivity","text:"+text.toString()+ "       outBounds: "+outBounds.toString());}}}
}

因为 UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 在activity中不能调用,需要在 测试类中写
调用可以用

adb  shell am instrument -w -e debug false -e class com.netease.open.pocoservice.InstrumentedTestAsLauncher#getNode
com.netease.open.pocoservice/androidx.test.runner.AndroidJUnitRunner

元素点击: 主要通过UiAutomation 类中的 injectInputEvent(InputEvent event, boolean sync)方法

例如长按事件:

public void longClick(double x, double y, double duration) {// duration: 单位秒down(x, y);SystemClock.sleep((long) (duration * 1000));up(x, y);}private void down(double x, double y, int w, int h, int contactId, boolean sync) {long now = SystemClock.uptimeMillis();double fx = x * w;double fy = y * h;MotionEvent.PointerProperties[] mpps = makeMPPs(new int[] {contactId});MotionEvent.PointerCoords[] mpcs = makeMPCs(new float[][]{{(float) fx, (float) fy}});MotionEvent evt = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, 1, mpps, mpcs, 0, 0, 1.0f, 1.0f, 1, 0, InputDevice.SOURCE_TOUCHSCREEN, 0);injectEvent(evt);}    

PointerProperties 对象中有 2个比较重要的字段

id
tooltype

PointerCoords 对象中有4个比较重要的对象
X 点击的x坐标
Y 点击的y坐标

pressure 按压的力度 力度值在 0 -1 之间,正常情况下 我么的触屏是0-0.1之前,当然具体手机具体参考

size 按压的面积 面积之同样在0 - 1 之间,
案例:

@Test
public void input() throws Exception {Log.i("TestActivity","Input ");UiDevice  device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());device.waitForIdle();Context context = InstrumentationRegistry.getTargetContext();UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();Input2 input2 = new Input2(context,uiAutomation);input2.swipe(0.5,0.5,0.6,0.6,5);Log.i("TestActivity","Input 2");}

调用可以用:

adb  shell am instrument -w -e debug false -e class com.netease.open.pocoservice.InstrumentedTestAsLauncher#input
com.netease.open.pocoservice/androidx.test.runner.AndroidJUnitRunner

通信实现:
NanoHTTPD :
NanoHttpd是个很强大的开源库,仅仅用一个Java类,就实现了一个轻量级的 Web Server,可以非常方便地集成到Android应用中去,让你的App支持 HTTP GET, POST, PUT, HEAD 和 DELETE 请求。

例子:

  @Overridepublic Response serve(IHTTPSession session) {StringBuilder builder = new StringBuilder();builder.append("<!DOCTYPE html><html><body>");builder.append("404 -- Sorry, Can't Found "+ session.getUri() + " !");builder.append("</body></html>\n");byte[] bytes;try {bytes = builder.toString().getBytes("UTF-8");} catch (UnsupportedEncodingException e) {bytes = new byte[0];}return newFixedLengthResponse(Response.Status.OK, NanoHTTPD.MIME_HTML, new ByteArrayInputStream(bytes), bytes.length);}

使用映射命令 adb forward --no-rebind tcp:6100 tcp:8010

访问:http://0.0.0.0:6100/

click 点击过程中的通信

2022-03-14 20:42:44.188 6223-6904/com.netease.open.pocoservice I/RpcServer: req=====  {"id":"9728b9d8-7288-4f16-8d79-e4de1195c961","uri":"poco-uiautomation-framework","method":[["getattr","selector"],["getattr","select"],["call",[["",["and",[["attr=",["name","com.Qunar:id\/atom_alexhome_youth_mod_flight"]]]]],["",false]]]],"session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d"}
2022-03-14 20:42:44.322 6223-6904/com.netease.open.pocoservice I/RpcServer: resp=====  {"id":"9728b9d8-7288-4f16-8d79-e4de1195c961","session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d","result":"<Rpc remote object proxy of [Lcom.netease.open.libpoco.sdk.AbstractNode;@c4a042d>","uri":"[Lcom.netease.open.libpoco.sdk.AbstractNode;@c4a042d(b8aff6cd-c224-4426-bf22-d68b417ccd5e)"}
2022-03-14 20:42:44.354 6223-6905/com.netease.open.pocoservice I/RpcServer: req=====  {"id":"2f4f8b9c-e5d1-4076-8afe-ef3edec95f64","uri":"[Lcom.netease.open.libpoco.sdk.AbstractNode;@c4a042d(b8aff6cd-c224-4426-bf22-d68b417ccd5e)","method":[["len",[]]],"session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d"}
2022-03-14 20:42:44.355 6223-6905/com.netease.open.pocoservice I/RpcServer: resp=====  {"id":"2f4f8b9c-e5d1-4076-8afe-ef3edec95f64","session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d","result":1}
2022-03-14 20:42:44.378 6223-6906/com.netease.open.pocoservice I/RpcServer: req=====  {"id":"fcb39e93-b3f5-4318-81fb-efd9026e101a","uri":"poco-uiautomation-framework","method":[["getattr","attributor"],["getattr","getAttr"],["call",[["uri","[Lcom.netease.open.libpoco.sdk.AbstractNode;@c4a042d(b8aff6cd-c224-4426-bf22-d68b417ccd5e)"],["","pos"]]]],"session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d"}
2022-03-14 20:42:44.381 6223-6906/com.netease.open.pocoservice I/RpcServer: resp=====  {"id":"fcb39e93-b3f5-4318-81fb-efd9026e101a","session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d","result":[0.1787037037037037,0.3325]}
2022-03-14 20:42:48.006 6223-7019/com.netease.open.pocoservice I/RpcServer: req=====  {"id":"","uri":"[Lcom.netease.open.libpoco.sdk.AbstractNode;@c4a042d(b8aff6cd-c224-4426-bf22-d68b417ccd5e)","method":[["del",[]]],"session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d"}
2022-03-14 20:42:48.006 6223-7019/com.netease.open.pocoservice I/RpcServer: resp=====  {"id":"","session_id":"d2e19bd5-0ee9-447d-b761-a96758b1689d","result":"<Rpc remote object proxy of [Lcom.netease.open.libpoco.sdk.AbstractNode;@c4a042d>"}

类图 :

参考资料:
模拟MotionEvent事件
Android 多点触控通信
NanoHttpd嵌入式服务器

poco源码简单分析相关推荐

  1. Hessian 源码简单分析

    Hessian 源码简单分析 Hessian 是一个rpc框架, 我们需要先写一个服务端, 然后在客户端远程的调用它即可. 服务端: 服务端通常和spring 做集成. 首先写一个接口: public ...

  2. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  3. FFmpeg的HEVC解码器源码简单分析:解码器主干部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  4. JSP 编译和运行过程与JSP源码简单分析

    JSP 编译和运行过程与JSP转移源码简单分析 Web容器处理JSP文件请求的执行过程主要包括以下4个部分: 1. 客户端发出Request请求 2. JSP Container 将JSP转译成Ser ...

  5. 线程的3种实现方式并深入源码简单分析实现原理

    前言 本文介绍下线程的3种实现方式并深入源码简单的阐述下原理 三种实现方式 Thread Runnable Callable&Future 深入源码简单刨析 Thread Thread类实现了 ...

  6. reentrantlock失效了?_ReentrantLock 源码简单分析

    JAVA中锁的实现最常见的方式有两种,一种是 synchronized关键字,一种是Lock.实际的开发过程中,要对这两种方式进行取舍. synchronized是基于JVM层面实现的, Lock却是 ...

  7. ChaLearn Gesture Challenge_3:Approximated gradients源码简单分析

    前言 上一篇博文ChaLearn Gesture Challenge_2:examples体验 中简单介绍了CGC官网提供的丰富的sample,本节来简单分下其中的一个sample源码,该sample ...

  8. Linux·内核源码简单分析

    目录 系统总体流程: 各个目录的阅读总结: (一) boot (二)内核初始化init (三)kernel: (四)mm内存管理 (五)文件系统模块fs: 系统总体流程: 系统从boot开始动作,把内 ...

  9. Enemy源码简单分析

    这是这个项目的网页链接,以下是关于enemy源代码的粗略分析. https://github.com/freakanonymous/enemy 弗兰克,是一个全职的恶意代码工程师,会不定期更新enem ...

最新文章

  1. javascript检测浏览器精简版
  2. 网站的高性能架构--web前端优化
  3. 2020-11-28 Latex相关小工具
  4. 如何用excel筛选相似内容_Excel中如何将两组数据的相同内容进行快速筛选配对...
  5. tomcat8 安装|解决启动慢|进入管理|host-manager 403错误
  6. php根据设备判断访问,PHP判断设备访问来源
  7. (已更新)视频app小程序模板源码
  8. 【深度学习之美笔记】人工“碳”索意犹尽,智能“硅”来未可知(入门系列之二)
  9. 软件质量-知识点整理
  10. java架构知识-分布式(学习笔记)
  11. python实现热力图_基于 Folium 的 Python 热力图实现
  12. java编程:假定公鸡5元钱1只,母鸡3元钱1只,小鸡1元钱3只。现在有100元钱要求买100只鸡,请编程列出所有可能的购鸡方案。
  13. SSRS 锁定标题栏
  14. c语言输出字母是问号,为什么数组输出会多一个问号
  15. 企业推广常用的网络推广方法有哪些?
  16. java安卓自动关机_android自动关机代码
  17. JAVA网络编程 -UDP篇(简单实现网络聊天)
  18. 计算机主机内部主要由哪些硬件构成,计算机硬件由哪几部分组成?各部分的作用是什么?...
  19. 视频硬字幕提取方法(可完全离线),开发个小工具辅助一下
  20. 自然辩证法之李约瑟难题

热门文章

  1. iOS开发常用代码片段:总有你用得上的功能
  2. 思科路由器各种show命令的输出详解
  3. 外文翻译 | 你以为你会用Math.random() ? 不,你不会……
  4. 安卓下的c语言ide,C语言编译器IDEapp-C语言编译器IDE安卓版下载v2.4.0-飞飞世界
  5. mybatis方法参数是list的批量插入
  6. 树莓派4B之ubuntu系统配置UART
  7. NTFS文件系统详解(三)NTFS元文件解析
  8. 【友盟+】国庆假期旅游类APP使用报告(中)
  9. 为什么建议选英文技术书籍
  10. Router-Link详解