python+uiautomator2二次封裝
#!python3.7
# -*- coding: utf-8 -*-
__author__ = 'haiertamendie'
__data__ = "2019-11-15 19-56"
import base64
"""
界面元素基礎操作
"""
import uiautomator2 as u2
from Config.Config import Config
from Api.Public.PyApiLog import PyApiLog
import datetime
import os
import time
from unittest import TestCase
class Action:
def __init__(self):
pass
def connect_wifi(self, ip):
"""
通過WiFi連接配接裝置:ip根據情況自己修改
:param ip:
:return:
"""
return u2.connect_wifi(ip)
def connect_usb(self):
"""
通過USB連接配接裝置
:return:
"""
return u2.connect_usb()
def healthcheck(self):
"""
檢查并維持裝置端守護程序處于運作狀态
:return:
"""
self.device.healthcheck()
def app_start(self, package_name,
activity=None,
extras={},
wait=True,
stop=True,
unlock=False,
launch_timeout=30,
use_monkey=False):
"""
啟動APP
:param package_name:
:param activity:
:param extras:
:param wait:
:param stop:
:param unlock:
:param launch_timeout:
:param use_monkey:
:return:
"""
self.device.app_start(package_name, activity=activity, extras=extras, wait=wait, stop=stop, unlock=unlock,
launch_timeout=launch_timeout, use_monkey=use_monkey)
def app_stop(self, package_name):
"""
關閉app
:param package_name: 應用包名
:return:
"""
self.device.app_stop(package_name)
def app_clear(self, package_name):
"""
清除app緩存
:param package_name: 應用包名
:return:
"""
self.device.app_clear(package_name)
def get_app_info(self, package_name):
"""
擷取應用資訊
:param package_name: 應用包名
:return:
"""
return self.device.app_info(package_name)
def app_stop_all(self, excludes=[]):
"""
關閉excludes中的所有應用
:param excludes: 應用包名集合
:return:
"""
self.device.app_stop_all(excludes)
def get_app_list_running(self):
"""
擷取已啟動的應用
:return:
"""
return self.device.app_list_running()
def wait_activity(self, activity, timeout=10):
"""
等待activity加載出來
:param activity:
:param timeout:
:return:
"""
self.wait_activity(activity=activity, timeout=timeout)
def app_wait(self, package_name, timeout=20.0,
front=False):
"""
等待應用啟動
:param package_name: 應用包名
:param timeout: 逾時時間
:param front:
:return:
"""
return self.device.app_wait(package_name, timeout=timeout, front=front)
def app_insatll(self, url, installing_callback=None, server=None):
"""
安裝應用
:param url: 裝置名字或者位址
:param installing_callback:
:param server:
:return:
"""
self.device.app_install(url, installing_callback=installing_callback, server=server)
def app_uninstall(self, package_name):
"""
解除安裝應用
:param package_name: 應用包名
:return:
"""
self.device.app_uninstall(package_name)
def app_uninstall_all(self, excludes=[], verbose=False):
"""
解除安裝多個應用
:param excludes: 應用包名集合
:param verbose:
:return:
"""
self.device.app_uninstall_all(excludes=excludes, verbose=verbose)
def get_element_xpath(self, xpath):
"""
根絕xpath路徑擷取元素
:param xpath: xpath路徑
:return:
"""
return self.device.xpath(xpath)
def get_elements(self, childCount=None, **kwargs):
"""擷取元素
@:param childCount 子元素數量
"""
ele = self.device(**kwargs)
if childCount:
eles = []
for i in ele:
if i.info.get("childCount") == childCount:
eles.append(i)
return eles
else:
return ele
def get_count(self, **kwargs):
"""
擷取元素個數
:param kwargs: 元素定位
:return:
"""
return self.device(**kwargs).count
def get_child_element(self, element, childCount=None, **kwargs):
"""
擷取子對象
:param element: 元素對象
:param childCount:
:param kwargs:
:return:
"""
ele = element.child(**kwargs)
if childCount == None or len(ele) == 1:
return ele
else:
eles = []
for i in ele:
if i.info.get("childCount") == childCount:
eles.append(i)
return eles
def get_left_element(self, element, **kwargs):
"""
擷取element左側元素
:param element: 元素對象
:param kwargs:
:return:
"""
return element.left(**kwargs)
def get_right_element(self, element, **kwargs):
"""擷取element右側元素"""
return element.right(**kwargs)
def get_up_element(self, element, **kwargs):
"""
擷取element上方元素
:param element: 元素對象
:param kwargs:
:return:
"""
return element.up(**kwargs)
def get_down_element(self, element, **kwargs):
"""
擷取element下方元素"
:param element: 元素對象
:param kwargs:
:return:
"""""
return element.down(**kwargs)
def get_sibling_elements(self, index=0, **kwargs):
"""
擷取兄弟元素
:param index: 第幾個兄弟,預設為全部
:param kwargs: 元素定位(唯一)
:return:
"""
self.wait(**kwargs)
if index == 0:
return self.device(**kwargs).sibling()
return self.device(**kwargs).sibling()[index]
def get_sibling_elements_by_element(self, element, **kwargs):
"""
擷取兄弟元素
:param element: 元素
:param kwargs: 兄弟元素定位(唯一)
:return:
"""
return element.sibling(**kwargs)
def click(self, **kwargs):
"""
點選元素
:param index: 索引值
:param kwargs: 元素定位()
:return:
"""
self.device(**kwargs).click()
def click_xpath(self, xpath, timeout=5):
"""
根據xpath路徑點選元素
:param xpath:
:param timeout:
:return:
"""
self.device.xpath(xpath).click(timeout=timeout)
def click_element(self, element):
"""
點選元素
:param element: 元素對象
:return:
"""
element.click()
def click_child_element(self, element, **kwargs):
"""
點選element的子元素
:param element: 元素對象
:param kwargs: 子元素定位資訊
:return:
"""
ele = self.get_child_element(element, **kwargs)[0]
self.click_element(ele)
def click_by_point(self, x, y):
"""
點選坐标點
:param x: 橫坐标
:param y: 縱坐标
:return:
"""
self.device.click(x, y)
def double_click(self, x, y, duration=0.1):
"""輕按兩下
@:param duration 間隔
"""
self.device.double_click(x, y, duration=duration)
def long_click(self, duration=10, timeout=10, **kwargs):
"""
長按指定的對象
:param duration: 持續時間
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
self.device(**kwargs).long_click(duration=duration, timeout=timeout)
def long_click_by_element(self, element, duration=10, timeout=10):
"""
長按
:param element: 元素對象
:param duration: 持續時間
:param timeout: 逾時時間
:return:
"""
element.long_click(duration=duration, timeout=timeout)
def long_click_by_point(self, x, y):
"""
長按坐标點
:param x: 橫坐标
:param y: 縱坐标
:return:
"""
self.device.long_click(x, y)
def get_element_info(self, **kwargs):
"""
擷取元素資訊
:param kwargs: 元素定位
:return:
"""
return self.device(**kwargs).info
def get_info_by_element(self, element):
"""
擷取元素資訊
:param element: 元素對象
:return:
"""
return element.info
def input_text(self, content, **kwargs):
"""
輸入文本
:param content: 文本内容
:param kwargs: 元素定位資訊
:return:
"""
self.wait(**kwargs)
self.device(**kwargs).set_text(content)
self.press("enter")
def input_text_xpath(self, content, xpath):
"""
輸入文本
:param content: 文本内容
:param xpath: 元素xpath定位資訊
:return:
"""
self.wait_xpath(xpath)
element = self.get_element_xpath(xpath)
self.click_element(element)
element.set_text(content)
def input_text_by_element(self, element, content):
"""輸入"""
self.click_element(element)
element.set_text(content)
self.press("enter")
def clear_text(self, **kwargs):
"""
清除輸入框資料
:param kwargs: 輸入文本框定位
:return:
"""
self.device(**kwargs).clear_text()
def clear_text_by_element(self, element):
"""清除資料"""
element.clear_text()
def click0(self, **kwargs):
"""點選UI對象中心位置"""
self.device(**kwargs).click0()
def click0_by_element(self, element):
"""點選UI對象中心位置"""
element.click0()
def click_bottomright(self, **kwargs):
"""點選UI對象右下角"""
self.device(**kwargs).click.bottomright()
def click_bottomright_by_element(self, element):
"""點選UI對象右下角"""
element.click.bottomright()
def click_topleft(self, **kwargs):
"""點選UI對象左上角"""
self.device(**kwargs).click.topleft()
def click_topleft_by_element(self, element):
"""點選UI對象左上角"""
element.click.topleft()
def long_click_bottomright(self, **kwargs):
"""長按UI對象右下角"""
self.device(**kwargs).long_click.bottomright()
def long_click_bottomright_by_element(self, element):
"""長按UI對象右下角"""
element.long_click.bottomright()
def long_click_topleft(self, **kwargs):
"""長按UI對象左上角"""
self.device(**kwargs).long_click.topleft()
def long_click_topleft_by_element(self, element):
"""長按UI對象左上角"""
element.long_click.topleft()
def drag_to_point(self, element, x, y, duration=1):
"""拖動指定對象到x,y位置,0.5s完成"""
element.drag.to(x, y, duration=duration)
def drag_to_element(self, element, **kwargs):
"""拖拽某一UI對象到另外一個UI對象(中心)"""
element.drag.to(**kwargs, steps=100)
def refresh(self):
"""重新整理頁面"""
wedith = self.get_window_size()[0]
height = self.get_window_size()[1]
self.swipe(wedith / 2, height * 1 / 4, wedith / 2, height * 5 / 6)
def swipe_right(self, **kwargs):
"""從UI對象的中心滑動到UI對象的右邊緣"""
self.device(**kwargs).swipe.right()
def swipe_right_by_element(self, element):
"""從UI對象的中心滑動到UI對象的右邊緣"""
element.swipe.right()
def swipe_up(self, **kwargs):
"""從UI對象的中心滑動到UI對象的上邊緣"""
self.device(**kwargs).swipe.up()
def swipe_up_screen(self, scre=1, steps=100):
"""
向上滑動螢幕,預設為一屏
:param scre: 滑動比例
:return:
"""
device_info = self.get_device_info()
height = device_info.get("displayHeight")
width = device_info.get("displayWidth")
self.device.swipe(width / 2, height * 8 * scre / 9, width / 2, height / 9, steps=steps)
def swipe_down_screen(self, scre=1, steps=100):
"""
向下滑動螢幕,預設為一屏
:param scre: 滑動比例
:return:
"""
device_info = self.get_device_info()
height = device_info.get("displayHeight")
width = device_info.get("displayWidth")
self.device.swipe(width / 2, height / 9, width / 2, height * 8 * scre / 9, steps=steps)
def swipe_up_by_element(self, element):
"""從UI對象的中心滑動到UI對象的上邊緣"""
element.swipe.up()
def swipe_left(self, **kwargs):
"""從UI對象的中心滑動到UI對象的左邊緣"""
self.device(**kwargs).swipe.left()
def swipe_left_by_element(self, element):
"""從UI對象的中心滑動到UI對象的左邊緣"""
element.swipe.left()
def swipe_down(self, **kwargs):
"""從UI對象的中心滑動到UI對象的下邊緣"""
self.device(**kwargs).swipe.down()
def swipe_down_by_element(self, element):
"""從UI對象的中心滑動到UI對象的下邊緣"""
element.swipe.down()
def pinch_In(self, **kwargs):
"""從邊緣到中心"""
self.device(**kwargs).pinch.In(percent=100, steps=10)
def pinch_In_by_element(self, element):
"""從邊緣到中心"""
element.pinch.In(percent=100, steps=10)
def pinch_Out(self, percent=33, steps=100):
"""從螢幕外側向中心滑動,percent為左右起始位置占兩邊的比例"""
self.device().pinch_out(percent=percent, steps=steps)
def pinch_Out_element(self, element, percent=33, steps=100):
"""從中心到邊緣"""
element.pinch_out(percent=percent, steps=steps)
def set_implicitly_wait(self, timeout=30):
"""設定全局最長等待時間"""
return self.device.implicitly_wait(timeout)
def click_wait(self, timeout=10, **kwargs):
"""
當timeout s内對象出現就點選
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
self.device(**kwargs).click_exists(timeout)
def click_wait_xpath(self, xpath, timeout=10):
"""
當timeout s内對象出現就點選
:param xpath: xpath定位
:param timeout: 逾時時間
:return:
"""
self.wait_xpath(xpath, timeout=timeout)
self.click_xpath(xpath)
def click_gone(self, maxretry=10, interval=1.0, **kwargs):
"""
點選并輪詢對象直到消失
:param maxretry: 最多點選次數
:param interval: 輪詢時間間隔
:param kwargs: 元素定位
:return:
"""
self.device(**kwargs).click_gone(maxretry=maxretry, interval=interval)
def wait_exists_by_element(self, element, timeout=10):
"""
等待UI對象出現
:param element: 元素對象
:param timeout: 逾時時間
:return:
"""
return element.exists(timeout=timeout)
def wait(self, timeout=10, **kwargs):
"""
等待
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
return self.device(**kwargs).wait(timeout)
def wait_should_be_contains(self, timeout=10, **kwargs):
"""
等待包含元素,逾時抛出錯誤
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
self.device(**kwargs).must_wait(exists=True, timeout=timeout)
def wait_xpath(self, xpath, timeout=10):
"""
等待
:param xpath: xpath路徑
:param timeout: 逾時時間
:return:
"""
return self.device.xpath(xpath).wait(timeout=timeout)
def wait_gone(self, timeout=10, **kwargs):
"""
等待UI對象消失
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
return self.device(**kwargs).wait_gone(timeout=timeout)
def wait_gone_xpath(self, xpath, timeout=10):
"""
等待UI對象消失
:param xpath: xpath定位
:param timeout: 逾時時間
:return:
"""
return self.device.xpath(xpath).wait_gone(timeout=timeout)
def wait_gone_by_element(self, element, timeout=3000):
"""
等待UI對象消失
:param element: 元素對象
:param timeout: 逾時時間
:return:
"""
return element.wait_gone(timeout=timeout)
def scroll_up(self, steps=10):
"""
向上滑動
:param steps: 步長
:return:
"""
self.device(scrollable=True).scroll(steps=steps)
def scroll_up_to_content_element(self, max_scroll_num=15, **kwargs):
"""
向上滑動直到某個元素出現
:param max_scroll_num: 最大滑動次數
:param kwargs: 元素定位
:return:
"""
self.sleep()
num = 0
while num < max_scroll_num:
if self.exists(timeout=0.5, **kwargs):
return True
else:
try:
self.swipe_up_screen(0.5, steps=20)
except:
return False
num = num + 1
self.sleep(0.2)
if num == max_scroll_num:
return False
else:
return True
def vert_backward(self):
"""
向下滑動
:return:
"""
self.device(scrollable=True).scroll.vert.backward()
def vert_backward_to_content_element(self, **kwargs):
"""
向下滑動直到某個元素出現
:param kwargs: 元素定位
:return:
"""
while True:
if self.exists(**kwargs):
break
else:
self.device(scrollable=True).scroll.vert.backward(steps=100)
def scroll_to_beginning(self, steps=10, max_swipes=1000):
"""
向左滑動到開始位置
:param steps: 步長
:param max_swipes:
:return:
"""
self.device(scrollable=True).scroll.horiz.toBeginning(steps=steps, max_swipes=max_swipes)
def horiz_forward(self, steps=10):
"""
向右滑動"
:param steps: 步長
:return:
"""""
self.device(scrollable=True).scroll.horiz.forward(steps=steps)
def scroll_to_end(self, steps=10):
"""
向結束方向滑動
:param steps: 步長
:return:
"""
self.device(scrollable=True).scroll.toEnd(steps=steps)
def scroll_to(self, **kwargs):
"""
向前滾動到指定UI位置
:param kwargs: 元素定位
:return:
"""
self.device(scrollable=True).scroll.to(**kwargs)
def get_device_info(self):
"""
擷取裝置資訊
:return:
"""
return self.device.info
def get_window_size(self):
"""
擷取視窗大小
:return:
"""
return self.device.window_size()
def get_device_height(self):
"""
擷取裝置的高度
:return:
"""
return self.device.info.get("displayHeight")
def get_device_width(self):
"""
擷取裝置的寬度
:return:
"""
return self.device.info.get("displayWidth")
def screen_on(self):
"""
打開螢幕
:return:
"""
self.device.screen.on()
def screen_off(self):
"""
關閉螢幕
:return:
"""
self.device.screen.off()
def wakeup(self):
"""
喚醒裝置
:return:
"""
self.device.wakeup()
def device_sleep(self):
"""
關閉裝置
:return:
"""
self.device.sleep()
def sleep(self, seconds=2):
"""
強制等待時間
:param seconds:
:return:
"""
time.sleep(seconds)
def press_home(self):
"""
按home鍵
:return:
"""
self.device.press("home")
def press_back(self):
"""
按傳回鍵
:return:
"""
self.device.press("back")
def press(self, key):
"""
按下鍵碼
:param key: 鍵碼值
:return:
"""
self.device.press(key)
def press_enter(self):
"""
按下Enter鍵
:return:
"""
self.device.press.enter()
def swipe(self, sx, sy, ex, ey, steps=10):
"""
從sx,sy坐标滑動至ex,ey坐标
:param sx: 起點橫坐标
:param sy: 起點縱坐标
:param ex: 終點橫坐标
:param ey: 終點縱坐标
:param steps:
:return:
"""
self.device.swipe(sx, sy, ex, ey, steps=steps)
def gesture(self, a, b, c, d, a1, b1, c1, d1, steps=100):
"""
雙指從(a,b),(c,d)滑動(a1,b1),(c1,d1),步長100
:param a:
:param b:
:param c:
:param d:
:param a1:
:param b1:
:param c1:
:param d1:
:param steps:
:return:
"""
self.device.gesture((a, b), (c, d), (a1, b1), (c1, d1), steps=steps)
def drag(self, sx, sy, ex, ey, steps=10):
"""
從sx,sy坐标拖動至ex,ey坐标
:param sx: 起點橫坐标
:param sy: 起點縱坐标
:param ex: 終點橫坐标
:param ey: 終點縱坐标
:param steps: 步長
:return:
"""
self.device.drag(sx, sy, ex, ey, steps=steps)
def screenshot(self, name=""):
"""
截屏
:param name: 圖檔名字
:return:
"""
if name != "":
path = os.path.join(self.path_screenshot, name + ".png")
else:
path = os.path.join(self.path_screenshot, datetime.datetime.now().strftime('%Y-%m-%d_%H_%M') + ".png")
self.device.screenshot(path)
def get_screenshot_as_base64(self):
"""
截屏并轉換成base64
:return:
"""
content = self.device.screenshot(format="raw")
base64_data = base64.b64encode(content)
# base64.b64decode(base64data)
return str(base64_data, "utf-8")
def dump(self, path):
"""
将目前螢幕結構儲存在本機,xml檔案
:param path: 儲存路徑
:return:
"""
self.device.dump_hierarchy(path)
def notification(self):
"""
打開通知消息
:return:
"""
self.device.notification()
def open_quick_settings(self):
"""
打開快捷設定欄
:return:
"""
self.device.open.quick_settings()
def register_watcher_click(self, name, **kwargs):
"""
建立并運作監聽器
:param name:
:param kwargs:
:return:
"""
watcher = self.device.watcher(name).when(**kwargs).click(**kwargs)
self.watchers_run()
return watcher
def remove_watcher(self, name):
"""
移除監聽器
:param name: 監聽器名字
:return:
"""
self.device.watcher(name).remove()
def watchers(self):
"""
擷取所有監聽器
:return:
"""
return self.device.watcher()
def watchers_triggered(self, name):
"""
擷取所有已觸發監聽器
:param name:
:return:
"""
return self.device.watcher(name).triggered
def watchers_reset(self):
"""
重置所有已觸發的螢幕
:return:
"""
self.device.watchers.reset()
def watchers_run(self):
"""
運作所有已注冊的監聽器
:return:
"""
self.device.watchers.run()
def exists(self, timeout=10, **kwargs):
"""
判斷元素是否存在
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
return self.device(**kwargs).exists(timeout=timeout)
def exists_xpath(self, xpath):
"""
判斷元素是否存在
:param xpath: xpath路徑
:return:
"""
return self.device.xpath(xpath).exists
def wait_not_exists(self, timeout=15, **kwargs):
"""
等待元素消失
:param timeout: 逾時時間
:param kwargs: 元素定位
:return:
"""
num = 1
while num <= timeout * 2:
if self.exists(**kwargs):
self.sleep(0.5)
num = num + 1
else:
return True
return False
def exists_by_element(self, element, timeout=10):
"""
判斷元素是否存在
:param element: 元素對象
:param timeout: 逾時時間
:return:
"""
return element.exists(timeout=timeout)
def disable_popups(self, disable=True):
"""彈出視窗
@:param disable True:自動跳過彈出視窗,False:禁用自動跳過彈出視窗
"""
self.device.disable_popups(disable)
def get_toast(self, wait_timeout=15,
cache_timeout=8,
default=None):
"""
擷取toast提示
:param wait_timeout: 逾時時間
:param cache_timeout: 從現在開始多少時間以内
:param default: 逾時提示
:return:
"""
toast = self.device.toast.get_message(wait_timeout=wait_timeout,
cache_timeout=cache_timeout,
default=default)
if toast:
self.reset_toast()
return toast
def reset_toast(self):
"""
清除裝置toast提示
:return:
"""
self.device.toast.reset()
更多系列文章:https://blog.csdn.net/qq_33676825