AirtestProject 如何解决 “自动装包 ” 过程中 oppo、vivo 等手机需要输入密码的问题
此文章来源于项目官方公众号:“AirtestProject”
版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途
前言
前俩天看到 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
, 如果应用已存在,是否替换,默认为 False -
install_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 在应用操作这方面的方法,奉上新鲜整理好的思维导图,有需要的同学可以先保存起来方便后续查看哦:
Airtest 官网:airtest.netease.com/
Airtest 教程官网:airtest.doc.io.netease.com/
搭建企业私有云服务:airlab.163.com/b2b