封装uiautomator2常用命令用于shell

概述

在前面的文章中介绍了python的标准库argparse,在工作中有时候有一些简单的任务,如对app进行一些重复的操作,因此决定对uiautomator2进行简单的封装,让一些操作成为的mac的命令行

自定义uiautomator2命令行

  • 完整uiautomator_command.py代码如下:
import argparse
import sys
import subprocess
import re
import uiautomator2 as u2
import logging
from merry import Merry

logging.getLogger("uiautomator2").disabled = True  # 关闭uiautomator2的logger打印
logging.getLogger("logzero_default").disabled = True  # 关闭uiautomator2初始化时的logger打印

merry = Merry()
merry.logger.disabled = True  # 关闭merry的logger打印


class U2Device:
    def __init__(self):
        uuid_lst = self.get_device_uuid()
        if len(uuid_lst) == 1:
            self.device = u2.connect(uuid_lst[0])
            print(f'{self.device.info.get("displayWidth")} * {self.device.info.get("displayHeight")}')  # 打印屏幕分辨率便于设置相关操作的坐标
        elif len(uuid_lst) > 1:
            raise RuntimeError("more than one device, just support one")
        else:
            raise RuntimeError("please connect your device first")

    @staticmethod
    def get_device_uuid():
        try:
            subprocess.check_output(['adb', 'version'])
        except:
            print('adb not available')
            sys.exit(1)
        stdout, stderr = subprocess.Popen("adb devices", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                                          text=True).communicate()
        pattern = r'([a-z-A-Z0-9]*)\s*device$'
        uuid_lst = re.findall(pattern, stdout, re.M)
        return uuid_lst


def foo(x):
    '''
    命令行输入参数类型转换
    如'1'->1, '2.1'->2.1, 其他保持为原字符串
    '''
    try:
        if x.isdigit():
            return int(x)
        return float(x)
    except:
        return x


parser = argparse.ArgumentParser()

@merry._try
def click(args):
    params = list(map(foo, args.position))
    if len(params) == 1:
        args.u2device.device(text=params[0]).click()
    elif len(params) == 2:
        args.u2device.device.click(params[0], params[1])
    else:
        raise Exception


@merry._try
def double_click(args):
    params = list(map(foo, args.position))
    args.u2device.device.double_click(params[0], params[1])


@merry._try
def long_click(args):
    params = list(map(foo, args.position))
    args.u2device.device.long_click(params[0], params[1])


@merry._try
def swipe(args):
    params_start_point = list(map(foo, args.swipe_start_point))
    params_end_point = list(map(foo, args.swipe_end_point))
    args.u2device.device.swipe(params_start_point[0], params_start_point[1], params_end_point[0], params_end_point[1])


@merry._try
def press(args):
    if args.key_event in ("home", "back"):
        args.u2device.device.press(args.key_event)
    else:
        raise KeyError


def version(args):
    print('0.0.1')


@merry._except(ValueError)
def catch_value_error(e):
    print(f'input parameters error: {e}')


@merry._except(AttributeError)
def catch_attribute_error(e):
    print(f'input parameters error: {e}')


@merry._except(KeyError)
def catch_key_error(e):
    print(f'input parameters error, only supported home or back')


@merry._except(Exception)
def catch_all(e):
    print('input parameters num error or uiautomator error')


def main():
    u2_device = U2Device()
    subparsers = parser.add_subparsers(help='all supported commands')

    click_parser = subparsers.add_parser('click', help='click point or button with text')
    click_parser.add_argument('position', action='store', nargs='*', help='x y or text str')
    click_parser.add_argument('-u2device', action='store', default=u2_device)
    click_parser.set_defaults(func=click)

    double_click_parser = subparsers.add_parser('double_click', help='double click point or button with text')
    double_click_parser.add_argument('position', action='store', nargs=2, help='x y or text')
    double_click_parser.add_argument('-u2device', action='store', default=u2_device)
    double_click_parser.set_defaults(func=double_click)

    long_click_parser = subparsers.add_parser('long_click', help='long click point or button with text')
    long_click_parser.add_argument('position', action='store', nargs=2, help='x y or text')
    long_click_parser.add_argument('-u2device', action='store', default=u2_device)
    long_click_parser.set_defaults(func=long_click)

    swipe_parser = subparsers.add_parser('swipe', help='swipe point a to point b')
    swipe_parser.add_argument('swipe_start_point', action='store', nargs=2, help='start point x y)')
    swipe_parser.add_argument('swipe_end_point', action='store', nargs=2, help='end point x y')
    swipe_parser.add_argument('-u2device', action='store', default=u2_device)
    swipe_parser.set_defaults(func=swipe)

    press_parser = subparsers.add_parser('press', help='press key_event, just support back and home')
    press_parser.add_argument('key_event', action='store',
                              help='key_event,see more at https://github.com/openatx/uiautomator2')
    press_parser.add_argument('-u2device', action='store', default=u2_device)
    press_parser.set_defaults(func=press)

    version_parser = subparsers.add_parser('version', help='print version and exit')
    version_parser.set_defaults(func=version)

    args = parser.parse_args()
    if 'func' not in args:
        parser.print_help()
        return 1
    return args.func(args)


if __name__ == '__main__':
    sys.exit(main())
else:
    print("this script is intended as a CLI not a package yet")
  • 安装脚本执行需要的第三方库
pip install uiautomator2
pip install merry
  • 定义成mac可执行的命令
    如我将该py脚本存放在如下路径~/Documents/pyscripts/uiautomator_command.py
  1. vim ~/.zshrc并写入如下alias
alias click="python ~/Documents/pyscripts/uiautomator_command.py click"
alias double_click="python ~/Documents/pyscripts/uiautomator_command.py double_click"
alias long_click="python ~/Documents/pyscripts/uiautomator_command.py long_click"
alias swipe="python ~/Documents/pyscripts/uiautomator_command.py swipe"
alias press="python ~/Documents/pyscripts/uiautomator_command.py press"
  1. source ~/.zshrc
  2. 接下来就可以在terminal中执行click、double_click、long_click、swipe、press命令了,enjoy!!

说明

  • 仅支持click、double_click、long_click、swipe、press命令,更多命令请自行扩展
  • 仅支持单设备
  • click支持text(需要能用text定位的元素,否则异常)和坐标
  • press仅支持home键和back键,需要支持其他keyevent,请自行扩展
  • 封装后可结合shell脚本对手机进行操作

扩展阅读