前言
前俩天看到Airtest讨论群里面提出了1个有意思的问题:一位同学在测试自动装包的过程中,发现像oppo、vivo这类品牌的手机在装包过程中都需要输入账号密码,而这会直接让 install()
指令运行失败。
值得思考的是,我们如何保证在安装应用的过程中,同时完成输入账号密码的任务而不中断安装应用的任务呢?
利用多线程解决装包过程输入密码的问题
看到这里,相信很多同学已经想到了可以利用多线程来解决这个问题了。没错,利用python的多线程确实可以帮助我们轻松地实现同时 运行多个任务。
关于新建线程,我们需要用到python标准库里面的 threading
模块:
from threading import Thread # 新建1个新的线程 # 其中function为线程函数,args为传递给线程函数的参数,它必须是tuple类型 t1 = threading.Thread(function, args) # 将线程设置为守护线程 t1.setDaemon(True) # 启动线程活动 t1.start() 复制代码
简单了解完python线程的一些基础用法,我们回到刚才的问题上来,在执行安装应用的任务之前,我们可以先开启1个线程,用于等待输入账号密码弹窗的弹出,以及输入账号密码、点击安装等操作:
完整的示例代码如下:
# -*- encoding=utf8 -*- __author__ = "AirtestProject" from airtest.core.api import * from threading import Thread auto_setup(__file__) from poco.drivers.android.uiautomation import AndroidUiautomationPoco poco = AndroidUiautomationPoco(use_airtest_input=True, screenshot_each_action=False) def input_pw(): sleep(5.0) # 等待弹窗出现 wait(Template(r"tpl1604980843615.png", record_pos=(-0.001, -0.029), resolution=(720, 1440)),timeout=60) sleep(2.0) # 点击输入密码 touch(Template(r"tpl1604978804097.png", record_pos=(0.211, 0.233), resolution=(720, 1440))) sleep(2.0) poco("com.coloros.safecenter:id/et_login_passwd_edit").click() poco("com.coloros.safecenter:id/et_login_passwd_edit").set_text("password") sleep(2.0) poco("android:id/button1").click() sleep(2.0) touch(Template(r"tpl1604979337502.png", record_pos=(-0.003, 0.608), resolution=(720, 1440))) # 新建用于等待弹窗输入账号密码的线程 a_thread = Thread(target=input_pw) a_thread.setDaemon(True) a_thread.start() install(r"D:\demo\tutorial-blackjack-release-signed.apk") 复制代码
PS:感谢Airtest用户“jxou”提供了上述的解决思路。
知识拓展
1.install()与uninstall()
install()
与 uninstall()
都是Airtest的核心API,分别用于 安装应用和卸载应用 ,并且它们都 仅支持安卓平台 :
install(filename)
,其中filename
为被安装应用的路径uninstall(package)
, 其中package
为被卸载应用的包名
示例:
from airtest.core.api import * install(r"D:\demo\tutorial-blackjack-release-signed.apk") uninstall("org.cocos2dx.javascript") 复制代码
2.install_app()与uninstall_app()
在 airtest的安卓模块 下,也提供了安装和卸载应用的方法,分别是 install_app()
和 uninstall_app()
。
相比于 install()
方法,install_app(filename,replace=False,install_options=[])
的参数更加丰富:
filepath
,apk文件在PC上的完整路径replace
, 如果应用已存在,是否替换,默认为Falseinstall_options
,install
命令的额外选项,默认是[],可填入"-l"、"-t"、"-s"、"-d"和"-g"
等参数,用于控制安装apk的行为
其中,install_options
的参数含义如下:
"-l"
,将应用安装到保护目录/mnt/asec"-t"
,允许安装AndroidManifest.xml里application指定android:testOnly="true"
的应用"-s"
,将应用安装到sdcard"-d"
,允许降级覆盖安装"-g"
,授予所有运行时权限
示例:
from airtest.core.android.android import * android = Android() # 非覆盖安装 android.install_app(r"D:\demo\tutorial-blackjack-release-signed.apk",False) # 覆盖安装 android.install_app(r"D:\demo\tutorial-blackjack-release-signed.apk",True) android.uninstall("org.cocos2dx.javascript") 复制代码
另外这个安卓模块下,还提供了一些其它的与应用相关的方法:
list_app(third_only=False)
,返回packages列表,third_only
如果为True
,只返回所有第三方应用列表path_app(package)
,打印出package的完整路径check_app(package)
,检查package在设备中是否存在
实际的测试应用中,比如我们要往设备中安装某个应用,可以先使用 check_app(package)
检查当前设备是否已经安装了该应用,然后再决定是直接安装还是覆盖安装:
from airtest.core.android.android import * android = Android() try: android.check_app("org.cocos2dx.javascript") print("当前设备已存在待安装应用,执行覆盖安装") android.install_app(r"D:\demo\tutorial-blackjack-release-signed.apk",True) except AirtestError: print("当前设备不存在待安装应用,执行非覆盖安装") android.install_app(r"D:\demo\tutorial-blackjack-release-signed.apk",False) 复制代码
3.start_app()、stop_app()与clear_app()
其它常用于应用操作的方法还有 start_app()
、stop_app()
与 clear_app()
:
start_app()
,在设备上启动目标应用,适用于Android和iOS平台stop_app()
,终止目标应用在设备上的运行,适用于Android和iOS平台clear_app()
,清理设备上的目标应用数据,仅适用于Android平台
小结
今天主要跟大家分享了用多线程解决自动装包过程需要输入账号密码的问题,另外还给大家补充了一些airtest在应用操作这方面的方法,奉上新鲜整理好的思维导图,有需要的同学可以先保存起来方便后续查看哦: