为了减少人员的资源分配,减少可重复性检测的时间
提示:以下是本篇文章正文内容
1.引入库
import os
import time
import random
import datetime
import uiautomator2 as ut
2、检测连接手机(列表是用来做多线程执行…还未实现)
devices = []
# 检测是否连接手机
try:
for dName_ in os.popen("adb devices"):
if "\t" in dName_:
if dName_.find("emulator") < 0:
devices.append(dName_.split("\t")[0])
devices.sort(cmp=None, key=None, reverse=False)
except:
pass
3、报警提示(该位置使用的是飞书群机器人报警,也可以使用其他方式,例如:钉钉、邮件、短信)
if devices == []:
msg = 'Android手机 导致无法找到devices 进行启动Android自动化脚本。'
send_FeiShu("无法连接", msg)
exit()
4、录制case执行视频(直接用当前时间做视频名称,判断有没有video文件夹)
# today = (datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S') # 原
today = ((datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S')) # 改
VideoName = f"case_{
today}"
if not os.path.exists("video"):
os.makedirs('video')
VideoPath = 'video'
device.screenrecord(VideoPath + "/" + VideoName + ".mp4")
5、查找应用(获取当前页面所有的文案,判断程序有没有在,没有就在下一屏找,直到找到并打开)
while True:
device.press("home")
device.press("home")
text_list = [ele.text for ele in device.xpath('//android.widget.TextView').all()]
if "XXX" not in text_list:
device.swipe_ext('left', scale=0.9)
else:
device(text="XXX").click()
time.sleep(5)
try:
device(resourceId="com.xxxxx.xxxxx:id/iv_dialog_active_close").click()
except:
print("不存在弹窗")
break
6、text文档(编写执行case,格式如下)
例如:1、xx>xxx.xxxxx.xxxxx - xx>xxx.xxxxx.xxxxx
当中:“1、”、“>”、" - " 为解析使用
1、首页>com.xxxxx.xxxxx:id/button_bar_home_img - 直播电商>xxx.xxxxx.xxxxx:id/button_bar_streaming_img - 达人>xxx.xxxxx.xxxxx:id/button_bar_ranking_img - 社区>xxx.xxxxx.xxxxx:id/button_bar_commodity_img - 我的>xxx.xxxxx.xxxxx:id/button_bar_user_img
2、实时直播>xpath('//*[@resource-id="com.xxxxx.xxxxx:id/rlHomeFunction"]/android.view.ViewGroup[1]/android.widget.ImageView[1]') - 退出页面登录>com.xxxxx.xxxxx/ivPhoneLoginBack
3、我的>com.xxxxx.xxxxx:id/button_bar_user_img - 登录 - 首页>com.xxxxx.xxxxx:id/button_bar_home_img
4、直播引流>com.xxxxx.xxxxx:id/tv_live_business_live_drainage - 上滑(下滑)
7、解析case(读取case文档,进行解析)
# 读取文档,获取case
with open('ExecuteCodeAndroid.text', 'r', encoding='UTF-8') as code_find:
# 解析case
code_list = [code_i.split('、')[1].replace('\n', '').split(' - ') for code_i in code_find.readlines()]
for i in range(len(code_list)):
for code_list_i in code_list[i]:
8、校验弹窗(获取当前页面所有文案,校验有没有关键词,有就进行指定点击)
# 获取当前页面文案,判断是否有弹窗
Tips = [elem.text for elem in device.xpath('//android.widget.TextView').all()]
if "个人信息保护指引" in Tips:
device(resourceId="com.xxxxx.xxxxx:id/tv_dialog_agreement_confirm").click()
device.swipe_ext("left", 0.6)
device.swipe_ext("left", 0.6)
device(resourceId="com.xxxxx.xxxxx:id/btn_item_welcome").click()
elif "好像哪里出错了" in Tips:
device.xpath('//*[@text="返回"]').click()
elif "信息走失啦" in Tips:
device.xpath('//*[@text="刷新"]').click()
elif "暂无数据" in Tips:
device.xpath('//*[@text="稍后再试"]').click()
elif "访问过于频繁" in Tips:
device.xpath('//*[@text="稍后再试"]').click()
elif "您当前账号登录" in Tips:
device.xpath('//*[@text="取消"]').click()
9、执行(详细执行功能点击操作)
# # 解析后长度大于等于 2 的时候
# if len(code_list_i.split('>')) >= 2:
# if 'xpath' in code_list_i.split('>')[1]:
# device.xpath(f"""{code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]}""").click()
# else:
# if ", text=" in code_list_i.split('>')[1]:
# resourceId_ = code_list_i.split('>')[1].split(', text=')[0]
# text_ = code_list_i.split('>')[1].split(', text=')[1].replace('"', '')
# device(resourceId=f"{resourceId_}", text=f"{text_}").click()
# else:
# if "text" in code_list_i.split(">")[1]:
# text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0]
# device(text=f"{text_name}").click()
# else:
# device(resourceId=f"{code_list_i.split('>')[1]}").click()
# # 小于 2
# elif code_list_i.split('>')[0] == "登录":
# AndroidLogin()
# elif code_list_i.split('>')[0] == "退出登录":
# AndroidLogout()
# elif code_list_i.split(">")[0] == "输入":
# device(resourceId="com.xxxxx.xxxxx:id/etSearchEdit").set_text(InputGbk2312())
# device.send_action('search')
# elif code_list_i.split('>')[0] == "上滑":
# Slide_up()
# elif code_list_i.split('>')[0] == "下拉":
# Slide_down()
# 改后
# 解析后长度大于等于 2 的时候
if len(code_list_i.split('>')) >= 2:
if 'xpath' in code_list_i.split('>')[1]:
print("xpath", code_list_i.split('>')[1])
xpath_code = code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]
print(f"device.xpath('{
xpath_code}').click()")
device.xpath(f'{
xpath_code}').click()
else:
# if ", text=" in code_list_i.split('>')[1]:
# print(", text", code_list_i.split('>')[1])
# resourceId_ = code_list_i.split('>')[1].split(', text="')[0]
# text_ = code_list_i.split('>')[1].split(', text="')[1].replace('"', '')
# print(resourceId_, text_)
# print(f'device(resourceId="{resourceId_}", text="{text_}").click()')
# device(resourceId=f"{resourceId_}", text=f"{text_}").click()
# # 该执行方式有误,网上说没有打开USB点击模式? 没有找到在哪里
# # 再就是还有 UI 结构层次混乱,从而导致元素选择器获取不到指定元素
# else:
if "text" in code_list_i.split(">")[1]:
text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0]
print("text", code_list_i.split(">")[1])
device(text=f"{
text_name}").click()
else:
print("resourceId", code_list_i.split(">")[1])
device(resourceId=f"{
code_list_i.split('>')[1]}").click()
# 小于 2
elif code_list_i.split('>')[0] == "登录":
AndroidLogin()
elif code_list_i.split('>')[0] == "退出登录":
AndroidLogout()
elif code_list_i.split(">")[0] == "输入":
device(resourceId="com.aiyingli.douchacha:id/etSearchEdit").set_text(InputGbk2312())
device.send_action('search')
elif code_list_i.split('>')[0] == "上滑":
print("上滑页面")
Slide_up()
elif code_list_i.split('>')[0] == "下拉":
print("下拉页面")
Slide_down()
10、全部代码
#
为了减少人员的资源分配,减少可重复性检测的时间
---
提示:以下是本篇文章正文内容
## 1.引入库
```python
import os
import time
import random
import datetime
import uiautomator2 as ut
2、检测连接手机(列表是用来做多线程执行…还未实现)
devices = []
# 检测是否连接手机
try:
for dName_ in os.popen("adb devices"):
if "\t" in dName_:
if dName_.find("emulator") < 0:
devices.append(dName_.split("\t")[0])
devices.sort(cmp=None, key=None, reverse=False)
except:
pass
3、报警提示(该位置使用的是飞书群机器人报警,也可以使用其他方式,例如:钉钉、邮件、短信)
if devices == []:
msg = 'Android手机 导致无法找到devices 进行启动Android自动化脚本。'
send_FeiShu("无法连接", msg)
exit()
4、录制case执行视频(直接用当前时间做视频名称,判断有没有video文件夹)
# today = (datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S') # 原
today = ((datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S')) # 改
VideoName = f"case_{
today}"
if not os.path.exists("video"):
os.makedirs('video')
VideoPath = 'video'
device.screenrecord(VideoPath + "/" + VideoName + ".mp4")
5、查找应用(获取当前页面所有的文案,判断程序有没有在,没有就在下一屏找,直到找到并打开)
while True:
device.press("home")
device.press("home")
text_list = [ele.text for ele in device.xpath('//android.widget.TextView').all()]
if "XXX" not in text_list:
device.swipe_ext('left', scale=0.9)
else:
device(text="XXX").click()
time.sleep(5)
try:
device(resourceId="com.xxxxx.xxxxx:id/iv_dialog_active_close").click()
except:
print("不存在弹窗")
break
6、text文档(编写执行case,格式如下)
例如:1、xx>xxx.xxxxx.xxxxx - xx>xxx.xxxxx.xxxxx
当中:“1、”、“>”、" - " 为解析使用
1、首页>com.xxxxx.xxxxx:id/button_bar_home_img - 直播电商>xxx.xxxxx.xxxxx:id/button_bar_streaming_img - 达人>xxx.xxxxx.xxxxx:id/button_bar_ranking_img - 社区>xxx.xxxxx.xxxxx:id/button_bar_commodity_img - 我的>xxx.xxxxx.xxxxx:id/button_bar_user_img
2、实时直播>xpath('//*[@resource-id="com.xxxxx.xxxxx:id/rlHomeFunction"]/android.view.ViewGroup[1]/android.widget.ImageView[1]') - 退出页面登录>com.xxxxx.xxxxx/ivPhoneLoginBack
3、我的>com.xxxxx.xxxxx:id/button_bar_user_img - 登录 - 首页>com.xxxxx.xxxxx:id/button_bar_home_img
4、直播引流>com.xxxxx.xxxxx:id/tv_live_business_live_drainage - 上滑(下滑)
7、解析case(读取case文档,进行解析)
# 读取文档,获取case
with open('ExecuteCodeAndroid.text', 'r', encoding='UTF-8') as code_find:
# 解析case
code_list = [code_i.split('、')[1].replace('\n', '').split(' - ') for code_i in code_find.readlines()]
for i in range(len(code_list)):
for code_list_i in code_list[i]:
8、校验弹窗(获取当前页面所有文案,校验有没有关键词,有就进行指定点击)
# 获取当前页面文案,判断是否有弹窗
Tips = [elem.text for elem in device.xpath('//android.widget.TextView').all()]
if "个人信息保护指引" in Tips:
device(resourceId="com.xxxxx.xxxxx:id/tv_dialog_agreement_confirm").click()
device.swipe_ext("left", 0.6)
device.swipe_ext("left", 0.6)
device(resourceId="com.xxxxx.xxxxx:id/btn_item_welcome").click()
elif "好像哪里出错了" in Tips:
device.xpath('//*[@text="返回"]').click()
elif "信息走失啦" in Tips:
device.xpath('//*[@text="刷新"]').click()
elif "暂无数据" in Tips:
device.xpath('//*[@text="稍后再试"]').click()
elif "访问过于频繁" in Tips:
device.xpath('//*[@text="稍后再试"]').click()
elif "您当前账号登录" in Tips:
device.xpath('//*[@text="取消"]').click()
9、执行(详细执行功能点击操作)
# # 解析后长度大于等于 2 的时候
# if len(code_list_i.split('>')) >= 2:
# if 'xpath' in code_list_i.split('>')[1]:
# device.xpath(f"""{code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]}""").click()
# else:
# if ", text=" in code_list_i.split('>')[1]:
# resourceId_ = code_list_i.split('>')[1].split(', text=')[0]
# text_ = code_list_i.split('>')[1].split(', text=')[1].replace('"', '')
# device(resourceId=f"{resourceId_}", text=f"{text_}").click()
# else:
# if "text" in code_list_i.split(">")[1]:
# text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0]
# device(text=f"{text_name}").click()
# else:
# device(resourceId=f"{code_list_i.split('>')[1]}").click()
# # 小于 2
# elif code_list_i.split('>')[0] == "登录":
# AndroidLogin()
# elif code_list_i.split('>')[0] == "退出登录":
# AndroidLogout()
# elif code_list_i.split(">")[0] == "输入":
# device(resourceId="com.xxxxx.xxxxx:id/etSearchEdit").set_text(InputGbk2312())
# device.send_action('search')
# elif code_list_i.split('>')[0] == "上滑":
# Slide_up()
# elif code_list_i.split('>')[0] == "下拉":
# Slide_down()
# 改后
# 解析后长度大于等于 2 的时候
if len(code_list_i.split('>')) >= 2:
if 'xpath' in code_list_i.split('>')[1]:
print("xpath", code_list_i.split('>')[1])
xpath_code = code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]
print(f"device.xpath('{
xpath_code}').click()")
device.xpath(f'{
xpath_code}').click()
else:
# if ", text=" in code_list_i.split('>')[1]:
# print(", text", code_list_i.split('>')[1])
# resourceId_ = code_list_i.split('>')[1].split(', text="')[0]
# text_ = code_list_i.split('>')[1].split(', text="')[1].replace('"', '')
# print(resourceId_, text_)
# print(f'device(resourceId="{resourceId_}", text="{text_}").click()')
# device(resourceId=f"{resourceId_}", text=f"{text_}").click()
# # 该执行方式有误,网上说没有打开USB点击模式? 没有找到在哪里
# # 再就是还有 UI 结构层次混乱,从而导致元素选择器获取不到指定元素
# else:
if "text" in code_list_i.split(">")[1]:
text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0]
print("text", code_list_i.split(">")[1])
device(text=f"{
text_name}").click()
else:
print("resourceId", code_list_i.split(">")[1])
device(resourceId=f"{
code_list_i.split('>')[1]}").click()
# 小于 2
elif code_list_i.split('>')[0] == "登录":
AndroidLogin()
elif code_list_i.split('>')[0] == "退出登录":
AndroidLogout()
elif code_list_i.split(">")[0] == "输入":
device(resourceId="com.xxxxx.xxxxx:id/etSearchEdit").set_text(InputGbk2312())
device.send_action('search')
elif code_list_i.split('>')[0] == "上滑":
print("上滑页面")
Slide_up()
elif code_list_i.split('>')[0] == "下拉":
print("下拉页面")
Slide_down()
10、全部代码
import os
import time
import random
import datetime
import uiautomator2 as ut
from call_the_police import send_FeiShu
while True:
devices = []
# 检测是否连接手机
print("检测是否连接手机")
try:
for dName_ in os.popen("adb devices"):
if "\t" in dName_:
if dName_.find("emulator") < 0:
devices.append(dName_.split("\t")[0])
devices.sort(cmp=None, key=None, reverse=False)
except:
pass
if devices == []:
msg = 'Android手机 导致无法找到devices 进行启动Android自动化脚本。'
send_FeiShu("无法连接", msg)
exit()
else:
print("<————————执行用例————————>")
try:
device = ut.connect_usb(devices[0])
except:
os.popen("adb kill-server")
os.popen("adb start-server")
device = ut.connect_usb(devices[0])
# 录制视频
if not os.path.exists("Android/video"):
os.makedirs('Android/video')
today = ((datetime.datetime.now() - datetime.timedelta(days=0)).strftime('%Y_%m_%d_%H_%M_%S'))
VideoName = f"case_{
today}"
VideoPath = 'Android/video'
print("<————————开始录制————————>")
device.screenrecord(VideoPath + "/" + VideoName + ".mp4")
# 手机中查找 相关应用
print("<————————查找抖查查————————>")
while True:
device.press("home")
device.press("home")
text_list = [ele.text for ele in device.xpath('//android.widget.TextView').all()]
if "抖查查" not in text_list:
device.swipe_ext('left', scale=0.9)
else:
device(text="抖查查").click()
time.sleep(5)
try:
device(resourceId="com.xxxxx.xxxxx:id/iv_dialog_active_close").click()
except:
print("不存在弹窗活动弹窗!!!")
break
# 登录
def AndroidLogin():
try:
device.xpath(
'//*[@resource-id="com.xxxxx.xxxxx:id/ll_user_top"]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]').click()
except:
print('非"我的"页面进行登录')
device(text="密码登录").click()
device(resourceId="com.xxxxx.xxxxx:id/cb").click()
device(text="请输入手机号").set_text("18730301074")
device(text="请输入密码").set_text("ceshi123")
device(text="登录").click()
# 退出登录
def AndroidLogout():
device(resourceId="com.xxxxx.xxxxx:id/tv_user_setting").click()
device(resourceId="com.xxxxx.xxxxx:id/btnLogout").click()
device(resourceId="com.xxxxx.xxxxx:id/tv_logout_confirm").click()
# 随机输入 1 个字
def InputGbk2312():
head = random.randint(0xb0, 0xf7)
body = random.randint(0xa1, 0xfe)
val = f'{
head:x}{
body:x}'
str = bytes.fromhex(val).decode('gb2312')
return str
# 上滑
def Slide_up():
device.swipe_ext("up", 0.6)
# 下拉
def Slide_down():
device.swipe_ext("down", 0.6)
# 读取文档,获取case
with open('Android/ExecuteCodeAndroid.text', 'r', encoding='UTF-8') as code_find:
# 解析case
code_list = [code_i.split('、')[1].replace('\n', '').split(' - ') for code_i in code_find.readlines()]
for i in range(len(code_list)):
for code_list_i in code_list[i]:
time.sleep(1)
# 获取当前页面文案,判断是否有弹窗
print('判断是否有弹窗')
Tips = [elem.text for elem in device.xpath('//android.widget.TextView').all()]
if "个人信息保护指引" in Tips:
device(resourceId="com.xxxxx.xxxxx:id/tv_dialog_agreement_confirm").click()
device.swipe_ext("left", 0.6)
device.swipe_ext("left", 0.6)
device(resourceId="com.xxxxx.xxxxx:id/btn_item_welcome").click()
elif "如遇问题请添加抖查查客服" in Tips:
device.xpath(
'//*[@resource-id="com.xxxxx.xxxxx:id/centerPopupContainer"]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]').click()
elif "信息走失啦" in Tips:
device.xpath('//*[@text="刷新"]').click()
elif "暂无数据" in Tips:
device.xpath('//*[@text="稍后再试"]').click()
elif "访问过于频繁" in Tips:
device.xpath('//*[@text="稍后再试"]').click()
elif "您当前账号登录" in Tips:
device.xpath('//*[@text="取消"]').click()
# 解析后长度大于等于 2 的时候
if len(code_list_i.split('>')) >= 2:
if 'xpath' in code_list_i.split('>')[1]:
print("xpath", code_list_i.split('>')[1])
xpath_code = code_list_i.split('>')[1].split("xpath('")[1].split("')")[0]
print(f"device.xpath('{
xpath_code}').click()")
device.xpath(f'{
xpath_code}').click()
else:
# if ", text=" in code_list_i.split('>')[1]:
# print(", text", code_list_i.split('>')[1])
# resourceId_ = code_list_i.split('>')[1].split(', text="')[0]
# text_ = code_list_i.split('>')[1].split(', text="')[1].replace('"', '')
# print(resourceId_, text_)
# print(f'device(resourceId="{resourceId_}", text="{text_}").click()')
# device(resourceId=f"{resourceId_}", text=f"{text_}").click()
# # 该执行方式有误,网上说没有打开USB点击模式? 没有找到在哪里
# # 再就是还有 UI 结构层次混乱,从而导致元素选择器获取不到指定元素
# else:
if "text" in code_list_i.split(">")[1]:
text_name = code_list_i.split(">")[1].split('(text="')[1].split('")')[0]
print("text", code_list_i.split(">")[1])
device(text=f"{
text_name}").click()
else:
print("resourceId", code_list_i.split(">")[1])
device(resourceId=f"{
code_list_i.split('>')[1]}").click()
# 小于 2
elif code_list_i.split('>')[0] == "登录":
AndroidLogin()
elif code_list_i.split('>')[0] == "退出登录":
AndroidLogout()
elif code_list_i.split(">")[0] == "输入":
device(resourceId="com.xxxxx.xxxxx:id/etSearchEdit").set_text(InputGbk2312())
device.send_action('search')
elif code_list_i.split('>')[0] == "上滑":
print("上滑页面")
Slide_up()
elif code_list_i.split('>')[0] == "下拉":
print("下拉页面")
Slide_down()
# list_data = [elem.text for elem in device.xpath('//android.widget.TextView').all()]
# if "暂无相关数据" in list_data:
# msg = f"case: {i + 1}"
# send_FeiShu("无数据", msg) # 增加钉钉或飞书报警
# 结束录制
print("<————————录制结束————————>")
device.screenrecord.stop()
break
总结
例如:以上就是今天要讲的内容,本文仅仅只是对于uiautomator2+Android+python的使用,而uiautomator2依旧有很多待发现的内容,等待我们发现。
近期会将ios的自动化同步到此,敬请期待哦!
# 总结
例如:以上就是今天要讲的内容,本文仅仅只是对于uiautomator2+Android+python的使用,而uiautomator2依旧有很多待发现的内容,等待我们发现。
近期会将ios的自动化同步到此,敬请期待哦!