基于Appium,封装自己的常用方法
阅读原文时间:2023年07月15日阅读:3

Appium算是老牌移动端App自动化测试工具了,在使用它的过程中,使用者经常会根据个人习惯,把较常用的方法封装在一起,方便调用。以下是我的封装,希望对你有启发。

from typing import Dict, NoReturn, Tuple, List, Union, Optional
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from appium.webdriver.webelement import WebElement as MobileWebElement
from selenium.webdriver.common.by import By
from loguru import logger
import time

class AppDriver:
def __init__(self, command_executor: str, desired_caps: Optional[Dict]) -> NoReturn:
self.driver = webdriver.Remote(command_executor, desired_caps)

def find\_element(self, element: Tuple\[str, Union\[str, Dict\]\]) -> MobileWebElement:  
    """  
    寻找元素  
    """  
    by = element\[0\]  
    value = element\[1\]  
    try:  
        if self.is\_element\_exist(element):  
            if by == "id":  
                return self.driver.find\_element(By.ID, value)  
            elif by == "name":  
                return self.driver.find\_element(By.NAME, value)  
            elif by == "class":  
                return self.driver.find\_element(By.CLASS\_NAME, value)  
            elif by == "text":  
                return self.driver.find\_element(By.LINK\_TEXT, value)  
            elif by == "partial\_text":  
                return self.driver.find\_element(By.PARTIAL\_LINK\_TEXT, value)  
            elif by == "xpath":  
                return self.driver.find\_element(By.XPATH, value)  
            elif by == "css":  
                return self.driver.find\_element(By.CSS\_SELECTOR, value)  
            elif by == "tag":  
                return self.driver.find\_element(By.TAG\_NAME, value)  
            else:  
                raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.")  
    except Exception as e:  
        logger.error(">>>>>>>> failed to find element: %s is %s. Error: %s" % (by, value, e))

def find\_elements(self, element: Tuple\[str, Union\[str, Dict\]\]) -> Union\[List\[MobileWebElement\], List\]:  
    """  
    寻找一组元素  
    """  
    by = element\[0\]  
    value = element\[1\]  
    try:  
        if self.is\_element\_exist(element):  
            if by == "id":  
                return self.driver.find\_elements(By.ID, value)  
            elif by == "name":  
                return self.driver.find\_elements(By.NAME, value)  
            elif by == "class":  
                return self.driver.find\_elements(By.CLASS\_NAME, value)  
            elif by == "text":  
                return self.driver.find\_elements(By.LINK\_TEXT, value)  
            elif by == "partial\_text":  
                return self.driver.find\_elements(By.PARTIAL\_LINK\_TEXT, value)  
            elif by == "xpath":  
                return self.driver.find\_elements(By.XPATH, value)  
            elif by == "css":  
                return self.driver.find\_elements(By.CSS\_SELECTOR, value)  
            elif by == "tag":  
                return self.driver.find\_elements(By.TAG\_NAME, value)  
            else:  
                raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.")  
    except Exception as e:  
        logger.error(">>>>>>>> failed to find elements: %s is %s. Error: %s" % (by, value, e))

def find\_all\_child\_element\_by\_xpath(self, element: Tuple\[str, Union\[str, Dict\]\]) -> Union\[List\[MobileWebElement\], List\]:  
    """  
    寻找元素的所有子元素  
    """  
    by = element\[0\]  
    value = element\[1\]  
    try:  
        if self.is\_element\_exist(element):  
            if by == "xpath":  
                child\_value = value + '/child::\*'  
                return self.driver.find\_elements(By.XPATH, child\_value)  
            else:  
                raise NameError("Please enter the correct targeting elements 'xpath'.")  
    except Exception as e:  
        logger.error(">>>>>>>> failed to find elements: %s is %s. Error: %s" % (by, value, e))

def save\_screenshot(self, picture\_name: str) -> NoReturn:  
    """  
    获取屏幕截图  
    """  
    fmt = '%Y%m%d%H%M%S'  # 定义时间显示格式  
    date = time.strftime(fmt, time.localtime(time.time()))  # 把传入的元组按照格式,输出字符串  
    picture\_name = "../Result/" + picture\_name + "-" + date + ".jpg"  
    self.driver.get\_screenshot\_as\_file(picture\_name)

def get\_screen\_size(self) -> Tuple\[int, int\]:  
    """  
    获取手机屏幕大小  
    """  
    x = self.driver.get\_window\_size()\['width'\]  
    y = self.driver.get\_window\_size()\['height'\]  
    return x, y

def swipe\_screen(self, direction: str, duration\_ms: int = 800) -> NoReturn:  
    """  
    屏幕向上滑动  
    """  
    location = self.get\_screen\_size()  
    if direction.lower() == "up":  
        x = int(location\[0\] \* 0.5)  
        start\_y = int(location\[1\] \* 0.75)  
        end\_y = int(location\[1\] \* 0.25)  
        self.driver.swipe(x, start\_y, x, end\_y, duration\_ms)  
    elif direction.lower() == "down":  
        x = int(location\[0\] \* 0.5)  
        start\_y = int(location\[1\] \* 0.25)  
        end\_y = int(location\[1\] \* 0.75)  
        self.driver.swipe(x, start\_y, x, end\_y, duration\_ms)  
    elif direction.lower() == "left":  
        start\_x = int(location\[0\] \* 0.75)  
        y = int(location\[1\] \* 0.5)  
        end\_x = int(location\[0\] \* 0.05)  
        self.driver.swipe(start\_x, y, end\_x, y, duration\_ms)  
    elif direction.lower() == "right":  
        start\_x = int(location\[0\] \* 0.05)  
        y = int(location\[1\] \* 0.5)  
        end\_x = int(location\[0\] \* 0.75)  
        self.driver.swipe(start\_x, y, end\_x, y, duration\_ms)  
    else:  
        print("请输入正确的方向")

def tap\_screen(self, positions: List\[Tuple\[int, int\]\], duration: Optional\[int\] = None) -> NoReturn:  
    """  
    用最多五个手指轻拍一个特定的地方,保持一定的时间  
    用法:tap\_screen(\[(100, 20), (100, 60), (100, 100)\], 500)  
    """  
    self.driver.tap(positions, duration)

def click(self, element: Tuple\[str, Union\[str, Dict\]\], found\_index: int = -1) -> NoReturn:  
    """  
    点击按钮  
    """  
    if found\_index == -1:  
        self.find\_element(element).click()  
    else:  
        self.find\_elements(element)\[found\_index\].click()

def send\_keys(self, element: Tuple\[str, Union\[str, Dict\]\], value: str, clear\_first: bool = False, click\_first: bool = False, found\_index: int = -1) -> NoReturn:  
    """  
    键盘输入  
    """  
    if found\_index == -1:  
        if click\_first:  
            self.find\_element(element).click()  
        if clear\_first:  
            self.find\_element(element).clear()  
        self.find\_element(element).send\_keys(value)  
    else:  
        if click\_first:  
            self.find\_elements(element)\[found\_index\].click()  
        if clear\_first:  
            self.find\_elements(element)\[found\_index\].clear()  
        self.find\_elements(element)\[found\_index\].send\_keys(value)

def scroll\_to\_text(self, text) -> NoReturn:  
    """  
    滚动到指定的text  
    """  
    uiautomator\_cmd = "new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text(\\"%s\\").instance(0))" % text  
    self.driver.find\_element\_by\_android\_uiautomator(uiautomator\_cmd)

def get\_attribute(self, element: Tuple\[str, Union\[str, Dict\]\], attribute\_name: str = 'text', found\_index: int = -1) -> Optional\[Union\[str, Dict\]\]:  
    """  
    获取元素属性  
    """  
    if found\_index == -1:  
        return self.find\_element(element).get\_attribute(attribute\_name)  
    else:  
        return self.find\_elements(element)\[found\_index\].get\_attribute(attribute\_name)

def is\_element\_exist(self, element: Tuple\[str, Union\[str, Dict\]\], wait\_seconds: int = 10) -> bool:  
    """  
    判断元素是否存在  
    """  
    by = element\[0\]  
    value = element\[1\]

    try:  
        if by == "id":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.ID, value)))  
        elif by == "name":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.NAME, value)))  
        elif by == "class":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.CLASS\_NAME, value)))  
        elif by == "text":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.LINK\_TEXT, value)))  
        elif by == "partial\_text":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.PARTIAL\_LINK\_TEXT, value)))  
        elif by == "xpath":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.XPATH, value)))  
        elif by == "css":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.CSS\_SELECTOR, value)))  
        elif by == "tag":  
            WebDriverWait(self.driver, wait\_seconds, 1).until(expected\_conditions.presence\_of\_element\_located((By.TAG\_NAME, value)))  
        else:  
            raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.")  
    except:  
        return False  
    return True

def is\_text\_exist(self, text: str, wait\_seconds: int = 10) -> bool:  
    """  
    判断text是否于当前页面存在  
    """  
    for i in range(wait\_seconds):  
        if text in self.driver.page\_source:  
            return True  
        time.sleep(1)  
    return False

def quit(self) -> NoReturn:  
    """  
    退出驱动  
    """  
    self.driver.quit()