uiautomator2+python+Android 自动化

为了减少人员的资源分配,减少可重复性检测的时间

提示:以下是本篇文章正文内容

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的自动化同步到此,敬请期待哦!

猜你喜欢

转载自blog.csdn.net/weixin_43603846/article/details/126248667
今日推荐