ATX 安卓设备集群管理 atx-server

codeskyblue · 2018年01月07日 · 最后由 999 回复于 2018年12月14日 · 12363 次阅读
本帖已被设为精华帖!

背景介绍

众所周知,安卓单台设备的UI自动化测试已经比较完善了,有数不清的自动化框架或者工具。但是介绍多设备管理的内容并不多,当手里的手机多了之后,要做自动化测试平台,这块的东西又不得不碰。我是一位比较喜欢实践的人,和同事在一起开发过简单的多设备管理系统,也用过开源的,后来又自己开发过。前前后后大概经历了4个不同的版本。

  • 第一个版本是是将adb的服务封装成HTTP接口,可以调用adb forward,install,并且利用screencap和input keyevent这些基本命令实现了一个简单的远程控制界面(速度很慢,但是基本能用)。为了解决截图慢的问题,我还买过两个摄像头。
  • 第二版版本是直接改造的openstf,本来第一个版本还在开发中,突然有同事对我说:“哎,你有没有见过这个项目呀openstf,好像跟你们最近开发的项目挺像的”,还发了一个链接过来。我当时就看了不超过10分钟,我就决定把第一个版本给废掉了。然后花了两个星期的时间把openstf的每一行代码都读了一遍(实际时间更长,因为读了很多遍)。后来在openstf上也加了不少功能,翻翻openstf的pr历史,也可以看到很多我的提交。这个项目教会了我很多,让我重新认识了nodejs,让我了解了rethinkdb
  • 第三个版本出来的很意外,原来是试试看的项目,就是用Go语言重写openstf,写了一个多星期,发现改造起来也不是很难嘛,而且还让openstf的架构变简单了很多(openstf的搭建比较头疼),之后内部组织重组,各种变动,从最开始最多5个人开发,到现在又是我一个人开发,实在应了那句话“计划赶不上变化”。人多的时候架子铺的太大,坑挖的有点多,代码维护起来也很累,过了一段时间实在不想管这个项目了。
  • 第四个版本:虽然我不想管第三个版本了,但是多设备管理的需求还是没消失,还是要硬着头皮维护下去。某个清空万里的好日子,突然灵机一动,把atx-agent给写了出来。这才意思到,就算没有数据线,就算没有adb,也是可以做设备自动化的嘛。关于atx-agent的介绍在杭州第三期沙龙分享过一次。基于atx-agent带来的无线连接技术,设备管理平台的硬件管理一下子就方便了好多好多,再也不用弄那些树莓派了,拉网线,还要烧代码provider代码的sd卡了。现在只要给保证手机是有电的就OK。软件层面实现一个atx-server管理一下众多的atx-agent就足够了。然后把openstf中的minicap和minitouch整合进atx-agent里面,远程控制功能就也有了。UI自动化则是使用了基于atx-agent的python uiautomator2,虽没有appium这么庞大和NB,但是麻雀虽小五脏俱全,只要你会python,各种UI自动化都能搞定。

基本架构图

             +--------------+
| |
| atx-server |
| |
+--+-------+--++
| | |
| | +--------------------------+
+---+ +-------+ |
| | |
| | |
+-----------v----+ +------v---------+ +---v------------+
| Android | | Android | | Android |
| | | | | |
| +---------+ | +---------+ | +---------+
| |atx-agent| | |atx-agent| | |atx-agent|
| | | | | | | | |
+------+---------+ +------+---------+ +------+---------+

atx-agent运行在手机的内部,为手机增加了远程控制,自动化的功能。atx-server最重要的功能,是将atx-agent汇总到一个网页上展示,并提供一个API可以获取所有设备的列表。

点击设备最右侧的那个眼睛图标,就可以进入远程控制界面。功能比较简单,但是基本功能够用了。

目前只试过80台设备,更多的设备应该也不成问题,不知道上限是多少,手机多的可以帮我测试下。

关于UI自动化, uiautomator2这个项目只需要知道设备的ip就可以运行自动化了,包括安装运行,推送文件,各种功能都有。在这个项目之上外加一个Jenkins之类的运行脚本的服务,稍加处理就是一个自动化测试平台了。美滋滋

辛辛苦苦终于写完了,希望看文章的人多思考思考,笔者非常期待思维的碰撞,欢迎留言。

项目地址: https://github.com/openatx/atx-server

附上cynic的实践文章:atx 安卓集群管理 安装运行及自动化的实践

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 107 条回复 时间 点赞

手动点赞

赞呀!后面抽空试用下~

相当赞

陈恒捷 将本帖设为了精华贴 01月08日 07:32

NB,在上家公司OPENSTF我都还没看完代码就匆匆的离职了。能读完STF的所有代码收获肯定不少吧。

0x88 回复

是呀,刷新了我的代码观

厉害了我的哥

厉害了...回头马上试用一下。

回头学习下,给大佬点赞👏

厉害了,我的哥!

我最近也在想让AppCrawler绕过appium直接支持你的atx-server。目前的需求还是以设备管理为主,把adb做成service就可以了。这样架构就可以简单了。基于这个基础,甚至都可以搞个众测设备的公有云服务了

如果需要接入用户的设备的话还需要弄个隧道代理

codeskyblue 回复

是的,我想个社区的移动设备共享平台,各家公司共享富余的设备

需要把交易系统弄好才行,还有网络的优化。现在这个系统就只支持局域网的

哈哈,我又有时间折腾了

codeskyblue 回复

好想跟着大佬一块折腾

llliuyx 回复

可以提pr 我给你review

codeskyblue 回复

先熟悉一下你的代码,现在工作的工作都没有用到呢 就一年前研究过xiaocong 的uiautomator

```Fetching https://golang.org/x/net/context?go-get=1
https fetch failed: Get https://golang.org/x/net/context?go-get=1: dial tcp 216.239.37.1:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.

我翻墙和不翻墙都下载不下来,不知道咋回事

agent 是个app吗?怎么启动?

adonisjph 回复

翻墙就可以,你这个是翻墙没成功。@dongdong, agent是一个二进制程序

codeskyblue 回复

我都能上google啊,这还不算翻墙成功?

adonisjph 回复

命令行翻墙需要配置一下 HTTP_PROXY

codeskyblue 回复

已经搞定,但是有个问题,我现在有多个设备,然后选择一台设备进行锁屏或者解锁操作时,其他设备也会有反应

adonisjph 回复

左侧的选择框代表的是设备是否可用来测试的状态


我选择了第三个,进行解锁操作,然后第二个设备解锁了,第三个没解锁

手动点赞👍

手动点赞👏 👍

codeskyblue 回复

我是说这个agent 第一次 启动怎么做?usb 命令行?

已使用,超赞👍 请大神收下我的膝盖

心向东 回复

adb shell

执行go get -v github.com/openatx/atx-server的过程中一直有下面的提示:
go\src\github.com\openatx\atx-server\database.go:12:2: no Go files in C:\Users\用户名\go\src\gopkg.in\gorethink\gorethink.v4

单独去go get只能取到gorethink.v3;go get v4的话会提示:
can't load package: package gopkg.in/gorethink/gorethink.v4: no Go files in C:\Users\用户名\go\src\gopkg.in\gorethink\gorethink.v4

@codeskyblue 请问为啥我的远程控制界面是一直都是灰的

wuming 回复

可以打开开发者选项看看有什么日志不,不过总会有部分手机不支持的

codeskyblue 回复

手机是红米4,版本是MIUI9.2,安卓版本是6.0.1,用的浏览器是ubuntu 16.04的firefox。开了好像没什么日志,logcat的这个不知道有没有用
1 EsService2 W loaded /system/lib/egl/libEGL_adreno200.so
1 EsService2 W loaded /system/lib/egl/libEGL_adreno200.so
2000 EsService I readResults: read results: 32, lastRequestId: 330
2000 I Kgd.KeyguardUpdateMonitor: mTimeTickBroadcastReceiver current state is mBootCompleted=true mDeviceProvisioned=true mPhoneState=0 Keyguard.isShowing = false Keyguard.isOccluded = false mScreenOn=true
2000 libEGL D loaded /system/lib/egl/libEGL_adreno200.so

已经使用,感谢大佬的分享,不过在使用的过程中,发现web端的手机屏幕截图刷新很慢哦

李海默 回复

 很快就更新了

感谢楼主分享,我发现一个问题,
1、使用N5 6.0系统手机,一开始连接正常。监控页面也可以看到手机。当我关机再重启以后就无法再正常连接手机了。除非重新输入python -m uiautomator2 init。得手动重新启动atx-server吗?
2、可以直接使用adb connect ip吗?就像stf那样直接远程连接?我发现连接显示成功,但设备都是offline呢

xiaqing 回复
  1. 不需要重启atx-server,但是需要重新init
  2. 如果需要adb connect的话,可以在手机连接在PC上的时候输入 adb tcpip 5555, 然后你就可以adb connect $IP
codeskyblue 回复

感谢楼主回复。之前考虑的是如果做成公司级别的设备管理系统,手机都在大家手中。如果重启以后还需要init的话就有点不便了,估计就再也连不上了。最好可以开机自启就能重新连接。
如果可以默认的进行adb connect ip,那么安装应用也会方便很多,现在只能支持url链接。

xiaqing 回复

在别人手上的手机除非你能给他奖励,一般都是不会共享出来的

@codeskyblue 手机黑屏的话不能唤醒,stf目前支持唤醒的,希望能把这个功能做进去。不然远程的话还要通知别人把屏幕打开。。

wuming 回复

atx-agent不能唤醒是因为用的wlan,黑屏之后,wlan断开了,无法跟手机继续通信了。(PS: 突然想到可以断开之后,直接再自动解锁屏幕,强制恢复wlan。明天试试)

codeskyblue 回复

666,期待更新,感谢分享

期待iOS的集群管理~~~~

现在执行了python -m uiautomator2 init 手机添加不上去,加了电脑IP+端口也不行,之前好好的,请问是什么问题呢

codeskyblue [该话题已被删除] 中提及了此贴 03月22日 16:21

好厉害,最近在学go,一定拜读您的代码。

atx-agent端当IP发生变化时没法主动通知atx-server端。会造成设备离线无法管理。可否在atx-agent端做一个心跳。定时向server端报告信息.IP变化时server端也换设备IP。

qiutao 回复

实际上是有的,我再看看代码吧,看看是不是有什么bug了

codeskyblue [该话题已被删除] 中提及了此贴 04月03日 19:26
codeskyblue 回复

这个问题改好了吗

wuming 回复

还没

atx-agent运行在手机的内部,为手机增加了远程控制,自动化的功能。atx-server最重要的功能,是将atx-agent汇总到一个网页上展示,并提供一个API可以获取所有设备的列表。----现在版本atx-agent自动化这块,就是网页端鼠标操作一台单独设备,然后该手机端会跟着执行吗?atx-server没法让所有连接到的手机一起运行同一份脚本吗?看git上atx-agent的说明,同时对所有连接的手机执行命令,是要在终端里面进行操作?但似乎没有atx里那些找图的功能可以用呀?

八个鸭鹿 回复

这个东西本来就不是为了面面俱到的

超赞,什么时候把logcat这块写好?很需要

飞狐 回复

来github提issue,省的我忘记掉了

codeskyblue 回复

android-uiautomator-server 的代码写的很漂亮,点赞,我看了好几遍了

飞狐 回复

你说的那个java项目是fork的,大部分代码是https://github.com/xiaocong写的, 我的java不怎么好

codeskyblue 回复

用到不少设计模式,代码结构也很清晰

不懂go,但是感觉很强大~

安装成功后在本地的localhost页面,更多栏位没有出现眼睛的图标,是什么原因造成的呢

@codeskyblue ,请问一下再华为P9 plus上 下载安装微信,遇到错误,在nexus 6p下试验成功,会是什么原因?

d.app_install("http://dldir1.qq.com/weixin/android/weixin666android1300.apk"
)
13:21:54 id: 10
13:21:54 download initialing
13:21:55 download initialing
13:21:56 download 100%
13:21:56 http download error
Traceback (most recent call last):
File "", line 1, in
File "D:\Android\python36\lib\site-packages\uiautomator2_init.py", line 47
7, in app_install
return self._wait_install_finished(id, installing_callback)
File "D:\Android\python36\lib\site-packages\uiautomator2__init
_.py", line 52
4, in _wait_install_finished
raise RuntimeError("error", jdata.get('error'))
RuntimeError: ('error', 'Get http://dldir1.qq.com/weixin/android/weixin666androi
d1300.apk: read udp 10.63.21.82:46756->221.12.1.227:53: i/o timeout')

zhang 回复

改版了,表格的最左边有个Use

chenshanju 回复

貌似是dns解析错误,手机看看有没有代理或者换个wifi试试

71楼 已删除

你好,我的手机连接上PC运行是正常的,一旦拔出,就变成offline了。请问,这个东西需要同时usb连接到电脑上,还需要同在一个局域网内吗?

区别就是我这个专注自动化,顺便管理。

zangtian2 回复

一个局域网内就好。可以提个issue 如果不正常

codeskyblue 回复

我想不用了。就只有一个机型不可以,其他都ok了。是升级到最新android 8的 三星S8

这种情况如何处理捏,红米note2
我把check_apk_installed这个函数注释了,可能就是检查太快了,没安装完就检查了

Leo 回复

现在不会有这种情况的,一种是你u2版本低,一种是真没安装上

目前在内网测试了一下,在服务器页面操作手机速度还可以,但在其他同事的页面上操作设备延迟就很高。光看手机运行是可以的,但是一操作就很卡了。stf并没有类似问题,总体来说真心不错。

xiaqing 回复

估计还是网络问题。我前两天给机房换了一个TP-LINK的企业级路由器。从此就不卡了

执行go get -v github.com/openatx/atx-server
报错,错误如下:
C:\Users\Administrator>go get -v github.com/openatx/atx-server
github.com/openatx/atx-server

github.com/openatx/atx-server

go\src\github.com\openatx\atx-server\httpserver.go:397:5: hbs.OnReconnect undefi
ned (type *heartbeat.Server has no field or method OnReconnect)

闪耀之冷 回复

go get -u 更新下依赖库

codeskyblue 回复

具体是那个依赖库

闪耀之冷 回复

是这个gohttpserver吗?

codeskyblue 回复

C:\Users\Administrator>python -m uiautomator2 init 10.0.1.1:8000
2018-05-08 14:26:59,427 - main.py:254 - INFO - atx-server addr 10.0.1.1:8000

2018-05-08 14:26:59,506 - main.py:269 - INFO - Detect pluged devices: ['980f
5397']
2018-05-08 14:26:59,507 - main.py:286 - INFO - Device(980f5397) initialing .
..
[Kminicap.so |################################| 13.2K / 13.2K
[?25h2018-05-08 14:27:09,736 - main.py:113 - INFO - install minicap
[Kminicap |################################| 357.9K / 357.9K
[?25h2018-05-08 14:27:22,467 - main.py:120 - INFO - install minitouch
[Kminitouch |################################| 29.5K / 29.5K
[?25h2018-05-08 14:27:27,442 - main.py:143 - INFO - app-uiautomator.apk(1.0
.13) installing ...
Traceback (most recent call last):
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 601, in u
rlopen
chunked=chunked)
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 387, in _
make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 383, in _
make_request
httplib_response = conn.getresponse()
File "C:\Python36\lib\http\client.py", line 1331, in getresponse
response.begin()
File "C:\Python36\lib\http\client.py", line 297, in begin
version, status, reason = self._read_status()
File "C:\Python36\lib\http\client.py", line 266, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
http.client.RemoteDisconnected: Remote end closed connection without response

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Python36\lib\site-packages\requests\adapters.py", line 440, in send
timeout=timeout
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 639, in u
rlopen
_stacktrace=sys.exc_info()[2])
File "C:\Python36\lib\site-packages\urllib3\util\retry.py", line 357, in incre
ment
raise six.reraise(type(error), error, _stacktrace)
File "C:\Python36\lib\site-packages\urllib3\packages\six.py", line 685, in rer
aise
raise value.with_traceback(tb)
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 601, in u
rlopen
chunked=chunked)
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 387, in _
make_request
six.raise_from(e, None)
File "", line 2, in raise_from
File "C:\Python36\lib\site-packages\urllib3\connectionpool.py", line 383, in _
make_request
httplib_response = conn.getresponse()
File "C:\Python36\lib\http\client.py", line 1331, in getresponse
response.begin()
File "C:\Python36\lib\http\client.py", line 297, in begin
version, status, reason = self._read_status()
File "C:\Python36\lib\http\client.py", line 266, in _read_status
raise RemoteDisconnected("Remote end closed connection without"
urllib3.exceptions.ProtocolError: ('Connection aborted.', RemoteDisconnected('Re
mote end closed connection without response',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Python36\lib\runpy.py", line 193, in run_module_as_main
"
main", mod_spec)
File "C:\Python36\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Python36\lib\site-packages\uiautomator2__main
.py", line 352, in odule>
main()
File "C:\Python36\lib\site-packages\uiautomator2__main
.py", line 348, in ma
in
fire.Fire(MyFire)
File "C:\Python36\lib\site-packages\fire\core.py", line 127, in Fire
component_trace = _Fire(component, args, context, name)
File "C:\Python36\lib\site-packages\fire\core.py", line 366, in _Fire
component, remaining_args)
File "C:\Python36\lib\site-packages\fire\core.py", line 542, in _CallCallable
result = fn(*varargs, **kwargs)
File "C:\Python36\lib\site-packages\uiautomator2__main
.py", line 273, in in
it
ignore_apk_check)
File "C:\Python36\lib\site-packages\uiautomator2__main
.py", line 291, in _i
nit_with_serial
ins.install_uiautomator_apk(apk_version, reinstall)
File "C:\Python36\lib\site-packages\uiautomator2__main
.py", line 144, in in
stall_uiautomator_apk
path = cache_download(app_url)
File "C:\Python36\lib\site-packages\uiautomator2__main
_.py", line 73, in cac
he_download
r = requests.get(url, stream=True)
File "C:\Python36\lib\site-packages\requests\api.py", line 72, in get
return request('get', url, params=params, **kwargs)
File "C:\Python36\lib\site-packages\requests\api.py", line 58, in request
return session.request(method=method, url=url, **kwargs)
File "C:\Python36\lib\site-packages\requests\sessions.py", line 508, in reques
t
resp = self.send(prep, **send_kwargs)
File "C:\Python36\lib\site-packages\requests\sessions.py", line 618, in send
r = adapter.send(request, **kwargs)
File "C:\Python36\lib\site-packages\requests\adapters.py", line 490, in send
raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', RemoteDisconnected(
'Remote end closed connection without response',))

是直接在git 下载下来 就可以直接运行了吗?还说需要配置?

use 和离线这个状态是根据什么来判断的?

小胖。 回复

设备会每隔5s向服务器发送一次心跳包,如果服务器没有接收到,就说明设备离线了

codeskyblue 回复

目前管理服务器部署在A服务器上,多部手机装atx服务是在B电脑装的,如何快速把手机接入到A服务器的管理平台(除了卸载服务用A服务器装以外),因为发现使用IP+端口查看info信息uuid是一致的,是否只用在A服务器某文件写入相应信息就可以连接上A服务器管理平台呢?

小胖。 回复

最新版是可以直接用域名指定server的,我现在就是直接换域名的

准备实践下,想请教下楼主,atx-agent如何解决国内各种定制手机的apk安装的限制? 比如oppo、vivo的帐号弹框,vivo还有个烦人的模拟点击,小米的安全权限等等。

重启能否自动拉起atx-agent呢?
因为安卓手机有bug,存在uid leak的情况,简单来说就是apk循环安装卸载,重复10000次,手机就没办法再安装apk了,需要卸载全部第三方apk后重启手机,这个bug报给google,但明确表示won't fix。

加油,暂时继续使用openstf

求助,现在管理设备服务器在imac上,通过其他电脑访问设备管理页面,不能操作设备,看报错,应该是无法连接手机设备。

remote.js?t=1526889597:570 WebSocket connection to 'ws://192.168.2.26:7912/minicap' failed: Error in connection establishment: net::ERR_CONNECTION_TIMED_OUT

有什么解决办法吗?

atx-agent是个apk么? 还是一个so? 运行在andoroid上会不会被杀(比如oppo vivo有些top50的手机后台定期会清理内存,加入白名单都不行)?

zhangbp 回复

是一个binary,还是有可能被杀的,只不过被杀的概率不大。

这个项目里的Advanced usage不是很懂,大佬可以简单说明一下吗?

Joe 回复

dingtalk那个,现在不怎么用了,当它不存在吧

win7 安装atx 报错如下:

F:\Go\src>go get -v github.com/openatx/atx-server
github.com/openatx/atx-server (download)

cd .; git clone https://github.com/openatx/atx-server F:\golang\go\src\github.

com\openatx\atx-server
Cloning into 'F:\golang\go\src\github.com\openatx\atx-server'...
fatal: unable to access 'https://github.com/openatx/atx-server/:' error:1407742E
:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
package github.com/openatx/atx-server: exit status 128

Asiazhang 回复

翻个墙试试

体验了一下,貌似手机切换网络或断网,自动重连后,设备可以正常显示,但无法在web页面对手机进行远程控制操作

请问能否在uiautomator.apk里面添加把 axt-agent注册到atx-server的功能,这样不用每次连电脑注册。

所有设备连接在一个wifi下,80台手机的话是否有带宽不足的问题,能否数据线+有限网络实现,求教

大佬,其实这样就完全可以知道局域网内哪些ip的手机安装了ATX或者ui2客户端,然后测试局域网内的多台有ATX的设备哇,可以提供一个方法获取这些有用的ip,或者默认直接就测试这些ip哇,感觉可行,比较省事,省去了测不了多台手机的尴尬


页面是这样,功能用不了,求指点

Smile 回复

我也是同样问题


我查了下是这样说的:golang不允许循环导包,如果检测到import cycle,会在编译时报错,通常import cycle是因为设计错误或包的规划问题。
可是我不知道怎么解决,有遇到的嘛

梵心一点 回复

确认下是不是 GOPATH, GOROOT没有配置对

codeskyblue 回复

可以了,就是设备不显示,台式电脑的ip跟手机的IP不在一个网络,这是个问题

109楼 已删除

请问以后有可能支持iOS吗?

剪烛 回复

有可能的,现在不敢保证

112楼 已删除
simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 14:44
114楼 已删除
115楼 已删除
xiaqing 回复

重启后可以通过连接USB线然后执行下面命令来重启服务
adb shell /data/local/tmp/atx-agent server --server 192.168.101.209:8000 -d

999 回复

恩,但是就得靠测试同学的主观执行了。一旦不去执行,还是失去了手机的连接,对吧?不过你的方法很好,谢谢啦

xiaqing 回复

是的 需要手动执行, 或者找个root的android设备写个能执行adb shell命令的apk,直接在apk里执行shell脚本

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册