UIAutomator2自动化测试APP简介

1. UIAutomator2的GitHub链接

https://github.com/openatx/uiautomator2

2. UIAutomator2的安装和运行

  1. 先下载adb并安装
    http://adbdownload.com/
  2. 运行pip3 install -U uiautomator2 安装uiautomator2
  3. 准备一台(不要两台)开启了开发者选项的安卓手机或者雷电模拟器,连接上电脑,确保执行adb devices可以看到连接上的设备(我截图显示的是模拟器,IP:Port的形式显示)。
    在这里插入图片描述
  4. 运行python3 -m uiautomator2 init安装包含httprpc服务的apk到手机+atx-agent, minicap, minitouch (在过去的版本中,这一步是必须执行的,但是从1.3.0之后的版本,当运行python代码u2.connect()时就会自动推送这些文件了)

3. UIAutomator2的使用前提

  1. Android版本 4.4+
  2. Python 3.6+ (社区反馈3.8.0不支持, 但是3.8.2支持)

4. UIAutomator2的元素定位方法

4.1 问题:

在使用UIAutomator2定位手机上的元素时,发现眼睛能看到的元素,用鼠标点击时,并不能定位到对应的元素。

4.2 解决方法:

  1. 将模拟器的分辨率改成和电脑的分辨率一致。
    在这里插入图片描述

  2. 在WEditor工具的hierarchy分层树上查找对应的元素。
    在这里插入图片描述

  3. 如果分层树上找不到对应的元素,需要将鼠标放在页面空白处(没有能点击的元素),然后按下图中的“点击”按钮,再点击“Hierarchy”按钮,就 可以在hierarchy分层树上查找对应的元素。
    在这里插入图片描述在这里插入图片描述

  4. 如果手机是竖屏显示的,但是WEditor中的手机镜像是横屏显示的,需要点击connect断开连接,然后把开关改成“静态”,然后再点击connect重新连接手机,然后把开关改成“实时”,这时WEditor中的手机镜像就会和手机同步改成竖屏显示了。

在这里插入图片描述

在这里插入图片描述

5. UIAutomator2的使用实例

请将username和password修改为自己的qq id和密码后直接执行LeiDianVM.py

5.1 执行效果,需要在720P下观看

python+UIAutomator2完成app自动化操作20210401

5.2 LeiDianVM.py

from time import sleep
import os
import subprocess
from LeiDianApp import LeiDianApp


class LeiDianVM(object):

    def __init__(self):
        # 启动模拟器
        self.start_vm = 'ldconsole.exe launch --name  %d'
        # 删除模拟器
        self.delete_vm = 'ldconsole.exe remove --name %s'
        # 新增模拟器
        self.add_vm = 'ldconsole.exe add --name %d'
        # 关闭所有模拟器
        self.close_vm = 'ldconsole.exe quitall'
        # 启动模拟器
        self.launch_vm = 'ldconsole.exe launch --name %d'
        # 关闭adb server
        self.close_adb_server = 'adb kill-server'
        # 开启adb server
        self.start_adb_server = 'adb start-server'
        # 修改分辨率,分辨率必须和笔记本电脑的分辨率一样,否则会出现看到按钮的位置,但是鼠标点上去发现定位不到按钮的位置(resourceId/text/xpath等)
        self.alter_ratio = 'ldconsole.exe modify --name %d --resolution 1920,1080,280 --cpu 4 --memory 2048 ' \
                           '--manufacturer HUAWEI --model HMA-AL00 --pnumber 13248888888 --imei 865166020734532 '
        # 安装app
        self.install_app = 'ldconsole.exe installapp --index %d --filename %s'
        # app目录路径
        self.app_dir_path = 'E:\\adbd.apk'
        # ldconsole.exe路径
        self.ld_path = 'E:\\ChangZhi\\dnplayer2'
        # 查看模拟器所有信息
        self.all_vm_info = 'ldconsole.exe list2'

    # 切换目录
    def change_dir(self, vm_name):
        try:
            current_dir = os.getcwd()
            print('当前目录为 %s' % current_dir)
            # 切换到雷电路径
            os.chdir(self.ld_path)
            # 查看修改后的工作目录
            after_dir = os.getcwd()
            print('当前工作目录已修改为 %s' % after_dir)
        except Exception as e:
            print(e)
        else:
            self.view_vm(vm_name)

    # 查看模拟器
    def view_vm(self, vm_name):
        data = subprocess.Popen('ldconsole.exe list2', stdout=subprocess.PIPE, universal_newlines=True)
        number_list = []
        #  通过循环获取已经存在的vm_name
        for line in data.stdout:
            info = line.strip().split(',')
            vm_number = info[1]
            number_list.append(vm_number)
            print(number_list)
        #  判断准备创建的vm_name是否在查询的列表里,如果存在就执行删除vm的的函数,如果不存在就启动新建vm的函数
        if str(vm_name) in number_list:
            # 查询vm_name出现了多少次
            count_vm_name = number_list.count(str(vm_name))
            print('该模拟器已经存在 %d 次' % count_vm_name)
            print('正在关闭模拟器')
            subprocess.call(self.close_vm)
            print('关闭模拟器完成')
            # for i in range(1, count_vm_name + 1):
            #     print('开始删除%s' % vm_name)
            #     self.del_vm(vm_name)
            # print('删除 %s 完成' % vm_name)
            for j in number_list:
                print('j= %s' % j)
                if j == '雷电模拟器':
                    pass
                else:
                    self.del_vm(j)
                    print('删除%s完成' % j)

            print('restarting adb_server')
            subprocess.call(self.close_adb_server)
            subprocess.call(self.start_adb_server)
            sleep(2)
            print('finish restart adb_server')
            result = 'deleted_vm'
            print('view_vm= %s !!!' % result)
            LeiDianVM().view_vm(1)
        else:
            print('start creating %s' % vm_name)
            self.make_vm(vm_name=vm_name)
            result = 'made_vm'
            print('view_vm= %s !!!' % result)
            print('finish LeiDianVM,start LeiDianApp')
            LeiDianApp().vm_status('QQ')

    # 删除模拟器
    def del_vm(self, vm_name):
        subprocess.call(self.delete_vm % vm_name)

    # 创建模拟器
    def make_vm(self, vm_name):
        subprocess.call(self.add_vm % vm_name)
        print('创建模拟器{}成功!'.format(vm_name))
        subprocess.call(self.alter_ratio % vm_name)
        print('修改模拟器{}分辨率成功!'.format(vm_name))
        subprocess.call(self.start_vm % vm_name)
        print('启动模拟器%s' % vm_name)
        print('开始安装%s!' % self.app_dir_path)
        code = subprocess.call(self.install_app % (vm_name, self.app_dir_path))
        print(code)
        if code == 0:
            sleep(60)
            print('install %s successfully!' % self.app_dir_path)
        print('start install uiautomator2!')
        data2 = subprocess.Popen('python -m uiautomator2 init', stdout=subprocess.PIPE, universal_newlines=True)
        number_list2 = []
        for line in data2.stdout:
            info2 = line.strip().split(' ')
            status = info2[0]
            number_list2.append(status)
        print(number_list2)
        if 'Successfully' in number_list2:
            print('install uiautomator2 successfully')
        else:
            print('install uiautomator2 unsuccessfully')

    # 启动模拟器
    def launch_vm(self, vm_name):
        subprocess.call(self.launch_vm % vm_name)
        print('finish launch_vm')


if __name__ == '__main__':
    LeiDianVM().change_dir(1)

5.3 LeiDianApp.py


import uiautomator2 as u2
import uiautomator2.ext.htmlreport as htmlreport
from LeiDianAppOpt import LeiDianAppOpt


class LeiDianApp(object):

    def __init__(self):
        try:
            self.d = u2.connect_usb()
        except Exception as e:
            print(e)
        # 每个ui点击后休眠1s
        self.d.click_post_delay = 1

    # 连接测试
    def vm_status(self, app_name):
        if self.d.info['naturalOrientation']:
            print('设备连接正常!')
            print('finish vm_status')
            self.search_app(app_name)
        else:
            print('设备连接出现问题!请检查后重试!')

    # 搜索app
    def search_app(self, app_name):
        self.d.press('home')
        self.d(resourceId="com.android.launcher3:id/search_text_view").click()
        self.d(focused=True).set_text(app_name)
        self.d(resourceId="com.android.launcher3:id/searchImageView").click()
        try:
            self.d(resourceId="com.android.flysilkworm:id/gameName", text=app_name).click()
            print('finish search_app')
            self.install_app()
        except Exception as e:
            print(e)

    # 安装app
    def install_app(self):
        try:
            self.d(resourceId="com.android.flysilkworm:id/download_btn_layout").wait(exists=True, timeout=20)
            self.d(resourceId="com.android.flysilkworm:id/download_btn_layout").click()
            self.d(resourceId="com.android.flysilkworm:id/open_btn").wait(exists=True, timeout=30)
            self.d(resourceId="com.android.flysilkworm:id/open_btn").click()
            self.d(resourceId="com.tencent.mobileqq:id/dialogRightBtn").wait(exists=True, timeout=20)
            self.d(resourceId="com.tencent.mobileqq:id/dialogRightBtn").click()
            print('finish install_app')
            self.login_app()
        except Exception as e:
            print(e)

    # 登录app
    def login_app(self):
        self.d(resourceId="com.tencent.mobileqq:id/btn_login").click()
        self.d(resourceId="com.tencent.mobileqq:id/input").click()
        self.d.send_keys("username", clear=True)
        self.d(resourceId='com.tencent.mobileqq:id/password').set_text('password')
        try:
            self.d(resourceId="com.tencent.mobileqq:id/login").click()
            self.d(resourceId="com.tencent.mobileqq:id/dialogLeftBtn").wait(exists=True, timeout=120)
            self.d(resourceId="com.tencent.mobileqq:id/dialogLeftBtn").click()
            print('正在登录,请稍后')
            print('finish LeiDianApp,start LeiDianAppOpt')
            LeiDianAppOpt().app_opt()
        except Exception as e:
            print(e)


if __name__ == '__main__':
    print('this is inside LeiDianApp __name__')

    

5.4 LeiDianAppOpt.py

import uiautomator2 as u2


class LeiDianAppOpt(object):
    def __init__(self):
        try:
            self.d = u2.connect_usb()
        except Exception as e:
            print(e)

    def app_opt(self):
        self.d.xpath('//*[@resource-id="com.tencent.mobileqq:id/recent_chat_list"]/android.widget.LinearLayout['
                     '6]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.view.View['
                     '2]').click()
        self.d(resourceId="com.tencent.mobileqq:id/fun_btn")
        self.d(resourceId="com.tencent.mobileqq:id/input").wait(exists=True, timeout=60)
        self.d(resourceId="com.tencent.mobileqq:id/input").set_text('test')
        self.d(resourceId="com.tencent.mobileqq:id/fun_btn").click_exists(15)
        self.d(resourceId="com.tencent.mobileqq:id/chat_item_content_layout", text="test").long_click(1)
        if self.d(resourceId="com.tencent.mobileqq:id/name", text="撤回").exists:
            self.d(resourceId="com.tencent.mobileqq:id/name", text="撤回").click()
            self.d(resourceId="com.tencent.mobileqq:id/dialogRightBtn").click()
        else:
            self.d(resourceId="com.tencent.mobileqq:id/name", text="删除").click()
            self.d(resourceId="com.tencent.mobileqq:id/action_sheet_button").click()
        print('finish app_opt')


if __name__ == '__main__':
    print('this is inside LeiDianAppOpt __name__')

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值