本文首发于:行者AI

Airtest是一款依据图画辨认和poco控件辨认的UI自动化查验东西,用于游戏和App查验,也广泛使用于设备群控,其特性多线程cpu有什么优点和功用不亚于appium和atx等自动化结构。

说起Airtest就不得不提AirtestIDE,一个健壮的GUI东西,它整合了Airtest和Poco两大结构,内置adb东西、Poco-inspector、设备录屏、脚本批改器、ui截图等,也正是因为它集成许多了健壮的东西,使得自动化查验变得更为便当,极大的提升了自动化查验功线程率,而且得到广泛的运用。

1. 简略入门

1.1 预备

  • 从官网下载并设备AirtestIDE。
  • 预备一台移动设备,保证USB调试功用处于打开状况,也可运用模仿器代替。

1.2 建议AirtestIDE

翻开AirtestIDE,会建议两个程序,一个是打印操作android下载安装日志的操控台程序,如下:

Airtest入门及多设备管理总结

图1. AirtestI多线程的并发问题DE 后台日志

一个是AirtestIDE的UI界面,如下:

Airtest入门及多设备管理总结

java模拟器2. Ajson怎样读irtestIDE UI界面

1.3 联接设备

联接的时分要保证设备json是什么意思在线,一般需求点击改写ADB来检查更新设备及json解析设备状况,然java言语后双击需求联接的设备即可联接,假定联接的设备是模仿器,需留心如下:

  • 保证模仿器与Airtest中的adb版别一同,否则无法联接,指令行中运用adb version即可检查adb版别,Airtest中的adb在Install_pathairtestcoreandroidstaticadbwindows目录下面。

  • 保证勾选Javacap办法②联接,避免联接后呈现黑屏。

Airtest入门及多设备管理总结

图3. AirtestIDE 设备联接

1.4 UI定Android

在Poco辅佐窗挑选A线程池面试题ndroid①而且使能Poco inspector②,然后将鼠标放到多线程使用场景比如控件上面即可显现控件的UI称谓③,也可在左边双击UI称谓将其写到脚本批改窗中④。

Airtest入门及多设备管理总结

图4. Airtjava面试题estIDE UI定位

1.5 脚本批改

多线程是什么意思脚本批改窗编写操作脚本⑤,比如运用java根底知识点百度查找去查找Airtest要害词,输入要害字后点击百度一下控件即可结束查找。

1.6 作业

作业脚本,并在Log多线程的并发问题检查窗检查作业日志android的drawable类⑥。以上操作仅仅简略入门,更多操作可参看官方文档。

2android下载. 多线程中运用Airtest

当项目中需求群控设备时,就会运用多进程或许多多线程面试题线程的办法来调度Airtest,android什么意思并将Airtest和Poco结构集成到项目中,以纯Python代码的办法来运用Airtest,不过仍需Airtest IDE作为辅佐东西帮忙结束UI控件的定位,下面给咱们同享一下运用Airtest操控多台设备的办法以及存在的问题。

2.1 设备json

纯python环境中运用Airtest,需android平板电脑价格在项目环境中设备Airtejson格局sjson文件是干什么的t和Poco两个模块,如下:
pip install -U airtandroid平板电脑价格est pocoui

2.2 多设备联接

每台设备都需求独自绑定一个Poco政策,Poco政策便是一个以apk的办法设备在设备内部的一个名为com.netease.open.pocoservice的服务(以下总称pocoservice),这android体系个服务可用jsonp于打印设备UI树以及模仿点击等,多设备联接的示例代码如下:

from airtest.core.api import *
from poco.drivers.android.uiautomation import AndroidUiautomationPoco
#android下载 过滤日志
air_logger = logging.getLog线程撕裂者ger("airtest")
aijava模拟器r_logger.setLevel(logging.ERROR)
aandroid平板电脑价格uto_setup(__file__)
dev1 = connect_device("Android:///127.0.0.1:21503")
dev2 = connect_device("Androjsonpid:///127.0.0.1:2多线程的完成办法1503")
dev3 =多线程面试题及答案 connect_device("Android:///127.0.0.1:21503")
poco1 = Androidandroid平板电脑价格UiautomationPoco(device=dejava环境变量装备v1)
poco2 = AndroidUiautomationPoco(device=dev2)
poco3 = AndroidUiautomationPoco(device=dev3)

2.3 Poco处理

上面这个写法的保证证了每台设备都独自绑定了一个Poco政策,可是上面这种办法不利于Poco政策的处理,比如检测每个Poco的存活状况。因线程的几种状况而需求一个容器去处理并创立Poco政策,这儿套用源码里面一种办法作为参看,它运用单例办法去处理Poco的创立并将其存为字android手机典,这样既保证了每台设备都有一个独自的Poco,也便当经过设备串号去获取Poco政策,源码如下:

    class A线程池参数ndroidUiautomationHelper(object):
_nuisjson格局怎样打开 = {}
@classmethod
def get_instance(candroid的drawable类ls, device):
"""
Thisjson文件是干什么的 is only a slot to stjava言语ore and get alr多线程并发eady initialized poco instance rather than initializing again. You can
simply pass the ``current dejava根底知识点vice instance`` provided by ``airtest`` to get the AndroidUiautomationPoco instance.
If no such And线程和进程的差异是什么roidUiautomationPoco instance, a new instance will be created and stored.
Args:
djavahdxxevice (:py:obj:`airtest.core.device.Device`): mo多线程和多进程的差异re details refer to `多线程和多进程的差异`airtest doc``
Returns:
poco instance
"""
i多线程原理f cls._nuis.get(device) is None:
cls._nuis[device] = Androidandroid下载安装UiautomationPoco(device)
return cls._nuis[de线程撕裂者vice]

AndroidUiautomationPoco在初始化的时分,内部保护了一个线程KeepRunningInstrujson怎样读mentationThread监控pocosjson格局ervice,监控pocoservi线程的几种状况ce的状况避免异常退出。

    class KeepRunniandroid下载ngInstrumentationThread(threading.Thread):
"""Keep pocoservice running"""
def __init__(self, pocjava模拟器o, port_to_线程池的创立办法有几种ping):
suandroid是什么手机牌子per(Kjava面试题eepRunningInstrumentationThrejson是什么意思ad, self).__init__()
self._stop_event = threading.Event()
self.poc多线程面试题及答案o = poco
self.port_to_ping = port_to_pinjava环境变量装备g
self.daemon = True
def stop(self):java编译器
self._stop_event.set()
def sjava面试题topped(多线程原理self):
randroid什么意思eturn self._stop_event.is_set()
def run(s多线程使用场景比如elf):
while not self.stopped():
if getattr(self.poco, "_instrumjson文件是干什么的enjava根底知识点t_proc", None) is no线程和进程的差异是什么t None:
stdout, stderr = self.poco._instrument_proc.communicate()
print('[pocoservice.apk] stdout: {}'.format(stdout))
print('[pocoservice.apk] st多线程原理derr: {}'.format(stderr))
if not self.stopped():
self.poco._start_instrument(self.port_to_ping)  # 查验重启
time.sleep(1)

这儿存在的问题是,一旦pocoservice出了问题(不安稳),因为KeepRunningInstrumentationThread的存在,pocosjava编译器ervice就会重启,但线程撕裂者是因为pocoservice服务崩溃后,有时是无法重启的,就会循环抛出raise RuntimeError(“unable to launch AndroidUiautomationPoco”)的异常,导致此设备无法正常作业,一般状况下,咱们需求独自处理它,详细如下:

处理Airtest抛json出的异常并保证pocoservice服务重启,一般状况下,需求从头多线程并发设备pocoservice,即从头初始化。可是如何才调检测Poco异常,而且捕获此异常呢?这儿在介绍一种办法,在处理Poco时,运用守时任务的办法去检测Poco的状况,然后将异常Poco移除,android平板电脑价格等候其下次联接多线程

2.4 设备异常处理

一般状况下,设备异常首要表现为AdbError、Devijava根底知识点ceConnectionError,引起这类异常的原因多种多样,因为Airtest操控设备的中心便是经过adb shell指令去操作,只需实施adb shell指令,都有或许呈现这类过失,你能够这样想,Airtest中任何动作都是在实施adb shell指令,为保证项目能长期安稳作业,就要特别留心处理此类异常。

  • 第一个问题

Airtest的adb shell指令函数经过封装subprocess.Popen来结束,而且运用communicate接纳stdout和stderr,这种办法建议一个非堵塞的子进程是没有问题的,可是当运用shell指jsonp令去建议一个堵塞式的子进程时就android下载会卡住,一向等候子进程结束或许json主进程退出才调退出,而有时分咱们不期望被子进程卡住,所以需独自封装一线程池面试题个不堵塞的adb shell函数,保证程序不会被卡住,这种状况下为保证进程建议成功,需自定义函数去检测该进程存在,如下:多线程和多进程的差异

    def rshell_nojsonwait(self, command, proc多线程cpu有什么优点_name):
"""
调用远程设备的shell指android手机令并马上返回, 并杀死其时进程。
:param command: shell指令
:param procandroid什么意思_name: 指令建议java编译器的进程名, 用多线程的完成办法于间断进程
:return: 成功:建议进程的pid, 失利:None
"""
if hasattr(self, "device"):
base_cmd_android下载安装strjson转map = f"{self.device.adb.adb_path} -s {self.device.serialno} shell "
cmd_str = baseandroid/yunos_cmd_str + command
for _ in range(3):
proc = subprocess.Popen(cmd_str)
proc.kill()  # 此进程当即关闭,不会影响远程设备打开的子进程
pid = self.get_rpid(proc_name)
if pid:
return pid
def get_rpid(self, proc_name):
"""
运用多线程cpu有什么优点ps查询远程设备上proandroid手机c_name对应的pid
:多线程param proc_name: 进程名
:return: 成功线程池:进程pid, 失利:None
"""
if hasattr(self, "device"):
cmd = f'{self.device.adb.adb_path} -s {self.device.serialno} shell ps | findstr {proc_name}'
res = list(filter(lambda x: len(x) > 0, os.popen(cmd).read().split(' ')))
return res[1] if res else None

留心:经过subprocess.Popejson是什么意思n翻开的进程记住运用线程的几种状况结束后及时关闭,避免呈现Too many open files的过失。

  • 第二个问题

Airtest中初始化ADB也是会常常报错,这直接导json解析致设备联接失利,可是Aijava编译器rtest并没有直接捕获此类过失,所以咱们需求在上层处理该过失并javaee增加重试机制,如下面这样,也封装成装修器或许多线程是什么意思运用retrying.retry。

def check_device(serialno, retries=3):
for _ injavaee range(retries线程池面试题)
try:
adb = ADB(serialno)
adb.wait_for_device(timeout=timeout)
devices = [item[0] for item in adb.devices(state='device')]
return serialno in devices
except Exception as err:
pass

一般状况下运用try except来捕或许的异常,这儿引android下载安装荐运用funcy,funcjson转mapy是一款可谓瑞士军刀的Python库,其中有一个函数silenandroid下载t便是用来装修或许引起异常的函数,siandroid体系lent源码如下,它结束了一个名为ignore的装修器来处理异常。当然funcy也封装许多python日常作业中常用的东西,感兴趣的话能够看看funcy的源码。

def silent(func):
"""忽略差多线程面试题错的调用""java根底知识点"
return ignore(Exception)(func)
def ignore(errojavaeers, default=None):
errors = _ensure_exceptable(errors)
def decorator(func):
          @wraps(func)
def wrapper(线程池的创立办法有几种*args, **kwargs):
try:
return func(*args, **kwargs)
ejava面试题xcept errors as e:
retujsonp跨域原理rn defaujson转maplt
return wrapper
retujson解析rn decorator
def _ensure_exceptable(errors):
is_exception = isinstance(errors, type) andjson怎样读 issubclass(errors, BaseExceandroid/yunosption)线程的几种状况
return errors if is_exception else多线程和多进程的差异 tuple(errors)
#参看运用办法
import json线程
str1 = '{a: 1, 'b':2线程池参数}'
json_str = silent(json.loads)(str1)
  • 第三个问题

Airtest实施指令androidstudio安装教程时会调用G.DEVICE获取其时设备(运用Poco政策底层会运用G.DEVICE而非本身初始化时传入的device政策),所以在多线程状况java编译器下,本该由这台设备实施线程的几种状况的指令或许被切换其他一台设备实施json文件是干什么的然后导致一系列过失。解决办法便是保护一个行列,确多线程面试题保是主线程在android体系实施Airtest的操作,并在运用Airtest的当地设置G.DEVICE保证G.DEVICE等于Poco的device。

3.结语

Airtest在安稳性、多设备操控尤其是多线程中存在许多坑。最好多看源码加深对Airtest的理解,然后再依据Airtest结构做一些高档的定制化扩展功用。


PS:更多技术干货,快重视【大众号 |java环境变量装备 xingzhjavaeee_ai】,与行者一同评论吧!