uiautomator2简单用法

   基于uiautomator2的UI自动化实践过程中,遇到过不少问题,后来看主要还是缺少对源码的阅读,导致理解不深,部分API不清楚如何调用,故在此记录。

 ---->此处内容非原创,侵删。

手势交互

    点击屏幕(坐标,支持相对坐标)
        d.click(x, y)
        d.click(0.5, 0.5)  #其中(0.235, 0.456) 代表 X(50%) Y(50%)

    双击
        d.double_click(x, y)  # 默认两次点击相隔0.1秒
        d.double_click(x, y, 1) # 两次点击相隔1秒
    
   长按
        d.long_click(x, y)  # 默认按0.5秒
        d.long_click(x, y, 5) # 长按5秒

    滑动(滑动屏幕)
        d.swipe(sx, sy, ex, ey)  # 从坐标(sx,sy)滑动至坐标(ex, ey),支持相对坐标
        d.swipe(sx, sy, ex, ey, 0.5) # 默认滑动时间0.5秒,可修改

    SwipeExt 扩展功能
        d.swipe_ext("right") # 屏幕右滑,4选1 - "left", "right", "up", "down"
        d.swipe_ext("right", scale=0.9) # 默认0.9, 滑动距离为屏幕宽度的90%
        d.swipe_ext("right", box=(0, 0, 100, 100)) # 在 (0,0) -> (100, 100) 这个区域做滑动

    拖动(例:拖动某个APP)
        d.drag(sx, sy, ex, ey)  #支持相对坐标
        d.drag(sx, sy, ex, ey, 0.5) # 默认滑动时间0.5秒,可修改

    多个点连续滑动(典型案例:9宫格解锁)
        从point(x0, y0) 滑动到point(x1, y1)然后滑动到point(x2, y2)...等等
        d.swipe_points([(x0, y0), (x1, y1), (x2, y2)], 0.2))  # 0.2为每次两点之间滑动的时间,坐标可以是绝对坐标,也可以是相对坐标
        d.swipe_points([(0.235, 0.456), (0.503, 0.449), (0.509, 0.601), (0.777, 0.603), (0.771, 0.763), (0.222, 0.75)], 0.2)  # 其中(0.235, 0.456) 代表 X(23.5%) Y(45.6%)

    模拟按下 - 等待 - 移动 - 松开
        d.touch.down(10, 10) # 模拟按下
        time.sleep(0.01) # 控制延迟
        d.touch.move(15, 15) # 模拟移动
        d.touch.up() # 模拟抬起

    截图
        d.screenshot(path) # 传入路径和名称
           
元素选择器
    # 定位text为'Clock'并且className为'android.widget.TextView'的元素
          d(text='Clock', className='android.widget.TextView')   

    后代元素
        #定位className为"android.widget.ListView"的元素下面text为"Bluetooth"的元素
        d(className="android.widget.ListView").child(text="Bluetooth")

    兄弟姐妹,同级元素
        #定位text为"Google"的元素的同级元素中className="android.widget.ImageView"的元素
        d(text="Google").sibling(className="android.widget.ImageView")

    通过多个层级多个属性定位
        #className="android.widget.ListView"且resourceId="android:id/list"的元素下面text为"Bluetooth"且className="android.widget.LinearLayout"的元素
        d(className="android.widget.ListView", resourceId="android:id/list").child_by_text("Bluetooth", className="android.widget.LinearLayout")
        可以由多个层级往下定位,例:
            d(className="###", resourceId="###").child_by_text("Wi-Fi", className="¥¥¥¥").child(className="****").click()

    相对定位
        d(A).left(B), 定位A左边的B
        d(A).right(B), 定位A右边的B
        d(A).up(B), 定位A上边的B
        d(A).down(B), 定位A下边的B

    多个同属性元素索引
        如果元素选择器选择到了多个同属性的元素而无法进行更细致的区分,可以用索引选择指定的元素
        d(text="Add new", instance=0)   #instance=0表示选择第一个,依次类推
        其他操作:
            d(text="Add new").count   #返回当前屏幕某个属性元素的个数
            len(d(text="Add new"))    #返回当前屏幕某个属性元素列表的长度
            d(text="Add new")[0]      #用下标选择指定元素,同d(text="Add new", instance=0)
            迭代:
                for view in d(text="Add new"):
                    view.info

    获取所选ui对象的状态及其信息
        1. 检查元素是否存在
            d(text="Settings").exists # 返回布尔值,True if exists, else False,用户if判断时,不可使用exist()
            d(text="Settings").exists(timeout=3)   #增加等待时间为3秒

        2. 输出指定元素的信息
            d(text="Settings").info
                
        3. 获取、输入、清除输入框文本
            d(text="Settings").get_text()  # 获取文本内容
            d(text="Settings").set_text("My text...")  #输入文本内容
            d(text="Settings").clear_text()  # 清除文本内容

        4. 获取指定元素中心点坐标
            x, y = d(text="Settings").center()
            x, y = d(text="Settings").center(offset=(0, 0)) # offset为指定元素的相对坐标,(0,0)表示元素左上角,(0.5,0.5)表示元素中心,(1,1)表示元素右下角

        5. 指定元素点击操作
                d(text="Settings").click()  #点击指定元素中心位置
                d(text="Settings").click(timeout=10)  #等待元素出现(最多等待10秒)后点击
                d(text="Settings").click(offset=(0.5, 0.5)) # offset为指定元素的相对坐标,(0,0)表示元素左上角,(0.5,0.5)表示元素中心,(1,1)表示元素右下角
                clicked = d(text='Skip').click_exists(timeout=10.0)  #如果10秒内元素存在,则点击,默认等待10秒
                is_gone = d(text="Skip").click_gone(maxretry=10, interval=1.0)  #等待元素消失后点击,返回布尔值,默认轮询次数10次,每次间隔时间1秒
                d(text="Settings").long_click()  #长按指定元素

特定元素的手势操作
    1. 将元素拖向另一个点或另一个元素
        备注:安卓4.3以下不能用
        d(text="Settings").drag_to(x, y, duration=0.5)  # 将指定元素在0.5秒的时间内拖动至指定坐标
        d(text="Settings").drag_to(text="Clock", duration=0.25) # 将指定元素在0.25秒的时间内拖动至指定元素的中心位置

    2. 等待元素出现或消失
        d(text="Settings").wait(timeout=3.0) # 等待元素出现,等待时间最长3秒,返回布尔值,默认等待时间20秒
        d(text="Settings").wait_gone(timeout=1.0)  # 等待元素消失,等待时间最长1秒,返回布尔值,默认等待时间20秒

    3、滚动屏幕          
        scroll()里面的参数steps默认是滑动一个屏幕的距离
        a.向上滚动:d(scrollable=True).scroll(steps=10)
        b.向下滑动:d(scrollable=True).scroll.vert.backward()         
        c.水平向右滚动:d(scrollable=True).scroll.horiz.forward(steps=50)       
        d.水平向左滚动:d(scrollable=True).scroll.horiz.backward(steps=50)      
        e.水平滑动到最左边:d(scrollable=True).scroll.horiz.toBeginning(steps=100,         max_swipes=1000)       
        f.水平滑动到最右边:d(scrollable=True).scroll.horiz.toEnd(steps=100, max_swipes=1000)         
        g.竖直滑动到结尾:d(scrollable=True).scroll.toEnd()      
        h.竖直滑动到开头:d(scrollable=True).scroll.toBeginning(steps=50)        
        i.滑动到指定位置:d(scrollable=True).scroll.to(text="Security")

全局设置
    # 设置每次UI点击后1.5秒的延迟
    d.click_post_delay = 1.5 # default no delay
    
    # 设置默认元素等待超时(秒)
    d.wait_timeout = 30.0 # default 20.0
    
    设置元素查找等待时间(默认20s)
    d.implicitly_wait(10.0)

输入内容
    d.send_keys('str')  # 不好用,存在问题
Toast
    1、显示toast
    d.toast.show("Hello world", 1.0) # show for 1.0s, default 1.0s
    2、获取toast
    # 5.0: 最大等待时间
    # 10.0: toast出现后的缓存时间. 默认 10.0
    # "default message": 返回的toast值. Default None
    d.toast.get_message(5.0, 10.0, "default message")
    # 一般用法
    assert "Short message" in d.toast.get_message(5.0, default="")
    # 清除toast缓存
    d.toast.reset()
xpath
    description -> content-desc(xpath)
    resourceId -> resource-id(xpath)
    # 等待元素存在(等待10秒)
    d.xpath("//android.widget.TextView").wait(10.0) # return bool
    # 找到元素并点击
    d.xpath("//*[@content-desc='分享']").click()
    # 检查是否存在
    if d.xpath("//android.widget.TextView[contains(@text, 'Se')]").exists:
        print("exists")
    # 获取所有输入框的text,属性和中心点坐标
    for elem in d.xpath("//android.widget.TextView").all():
        print("Text:", elem.text)
        # Dictionary eg
        #{'index': '1', 'text': '999+', 'resource-id':   'com.netease.cloudmusic:id/qb', 'package': 'com.netease.cloudmusic', 'content-desc': '', 'checkable': 'false', 'checked': 'false', 'clickable': 'false','enabled': 'true', 'focusable': 'false', 'focused': 'false','scrollable': 'false','long-clickable': 'false', 'password': 'false', 'selected': 'false', 'visible-to-user': 'true', 'bounds': '[661,1444][718,1478]'}'''
        print("Attrib:", elem.attrib)
        # Coordinate eg: (100, 200)
        print("Position:", elem.center())

  部分实例

    def add_picture_to_report(filepath):
        filebytes = ''
        with open(filepath, 'rb') as f:
            filebytes = f.read()
        allure.attach(filebytes, '运行截图', attachment_type=allure.attachment_type.PNG)

    def d_screenshot(self, screenshot_name):
        """ 截图 """
        screenshot_time = time.strftime(TIMEFORMAT, time.localtime())
        filename = '%s_%s_%s_.png' % (screenshot_time, project_conf.PROJECT_SN, screenshot_name)
        logging.info('current picture name is %s' % filename)
        filepath = os.path.join(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'Screenshot'), 'AiHome')
        if not os.path.exists(filepath):
            os.makedirs(filepath)
        picture_file = os.path.join(filepath, filename)
        try:
            self.d.screenshot(picture_file)
            add_picture_to_report(picture_file)
            logging.info('screenshot success')
        except ScreenshotError:
            logging.exception('screenshot failed')
原文地址:https://www.cnblogs.com/longmin/p/12862967.html