Appium自动化测试中的常见模拟操作涵盖了多种用户交互行为,这些操作对于自动化测试框架来说至关重要,因为它们能够模拟真实用户的使用场景,从而验证应用程序的功能和稳定性。


今天讲解高级手势操作&toast操作:

实现步骤:

1、创建TouchAction对象

2、调用手势方法

3、调用perform() 执行操作

1、轻敲操作

示例说明:

action = TouchAction(driver) # 创建建手势对象

action.tap(element=None, x=None, y=None, count=1) # 调用轻敲手势方法,传入的是一个元素对象或者是一个坐标点

count表示的是轻敲的次数, 默认值为1.

action.perform() # 调用perform()执行轻敲操作

2、按下和抬起操作

示例说明:

按下:press(element, x, y)

抬起:release()

TouchAction(driver).press(element=None, 

x=None, y=None).release().perform()

点击(原理):按下和抬起可以结合起来使用,达到点击的效果

3、等待操作

说明:模拟手指等待。wait(ms=0) ms表示的是毫秒数

示例:

TouchAction(driver).press(element=None, 

x=None, y=None).wait(3000).release().perform()

长按(原理):通过等待及按下和抬起实现长按的操作

4、长按操作

示例:long_press(element, x=None, y=None, duration=1000)

说明:

element表示的是元素对象

x, y表示的是坐标点

duration表示的是长按的时长,单位是毫秒

实现:

TouchAction(driver).long_press(element=None,

x=None, y=None, duration=1000).perform()

5、移动操作

原理:模拟手指在手机屏幕上移动的过程,此种方式可以实现手势验证码的解锁(把所有的点都连接起来)

示例:

TouchAction(driver).press(element=None, x=None, y=None).wait(500).move_to(element=None, x=None, y=None).wait(500)
.move_to(element=None, x=None, y=None).release().perform()

说明:

move_to(element=None, x=None, y=None) element表示的是元素对象, x和y表示的是坐标点。二选其一。

移动的操作是需要结合press和release一起使用。

6、代码示例​​​​​​​

import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
 
 
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
 
    # 定义desired_caps 字典,初始化app的配置信息
    desired_caps = {
        "platformName": "android",  # 表示的是android
        "platformVersion": "10",  # 表示的是设备系统的版本号
        "deviceName": "DWV6R19A10002101",  # 表示的是设备的ID名称
        "appPackage": app_package,  # 表示的是app的包名
        "appActivity": app_activity,  # 表示的是app的界面名
        "newCommandTimeout": 100000,
        "noReset": True,  # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
        # "resetKeyboard": True,  # 重置设备的输入键盘 (连接虚拟机时使用)
        # "unicodeKeyboard": True  # 采用unicode编码输入(连接虚拟机时使用)
    }
    # 创建 Appium 驱动实例
    options = UiAutomator2Options().load_capabilities(desired_caps)
    driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
 
    # 启动应用程序
    driver.wait_activity(desired_caps, 5)
    return driver
 
 
# 定义一个获取元素的方法
def get_element_new(driver, element):
    element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
    return element
 
 
if __name__ == "__main__":
    # 本次启动的应用程序包名和活动名(本机设置页面)
    app_package = "com.android.settings"
    app_activity = ".HWSettings"
 
    # 启动应用程序
    driver = start_app(app_package, app_activity)
 
    '''
    一、通过轻敲「WLAN」元素的方式进入WLAN设置页面
    action.tap(element=None, x=None, y=None, count=1).perform()
    '''
    wlan = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="WLAN"]')
    wlan_btn = get_element_new(driver, wlan)
    TouchAction(driver).tap(wlan_btn).perform()
 
    '''
    二、通过「按下和抬起」的方式点击「更多WLAN设置」
    TouchAction(driver).press(element=None, x=None, y=None).release().perform()
    '''
    more_wlan = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="更多 WLAN 设置"]')
    more_wlan_btn = get_element_new(driver, more_wlan)
    TouchAction(driver).press(more_wlan_btn).release().perform()
 
    # 返回上一页面
    time.sleep(1)
    driver.press_keycode(4)
    time.sleep(2)
 
    '''
    三、定位到Wi-Fi列表,通过「等待及按下和抬起」实现长按,展开删除网络/修改网络选项
    TouchAction(driver).press(element=None, x=None, y=None).wait(3000).release().perform()
    '''
    wlan_list = (By.XPATH, '//android.widget.FrameLayout[@resource-id='
                           '"com.android.settings:id/drop_down_refresh_container"]/android.view.View')
    wlan_list_1 = get_element_new(driver, wlan_list)
    TouchAction(driver).press(wlan_list_1).wait(3000).release().perform()
 
    # 返回
    time.sleep(1)
    driver.press_keycode(4)
    time.sleep(3)
 
    '''
    四、定位到Wi-Fi列表,通过长按,展开删除网络/修改网络选项
    TouchAction(driver).long_press(element=None, x=None, y=None, duration=1000).perform()
    '''
    wlan_list = (By.XPATH, '//android.widget.FrameLayout[@resource-id='
                           '"com.android.settings:id/drop_down_refresh_container"]/android.view.View')
    wlan_list_1 = get_element_new(driver, wlan_list)
    TouchAction(driver).long_press(wlan_list_1, duration=3000).perform()
 
    # 返回
    time.sleep(2)
    driver.press_keycode(4)
 
    '''
    五、通过move_to(element, x=x, y=y) 从一个元素移动到另一个元素
    此种方式可以实现手势验证码的解锁(把所有的点都连接起来)
    TouchAction(driver).press(element=None, x=None, y=None).wait(500).move_to(element=None, x=None, y=None).wait(500)
    .move_to(element=None, x=None, y=None).release().perform()
    下图示例只为演示效果
    '''
    # 返回到设置页面
    time.sleep(2)
    driver.press_keycode(4)
 
    # 找到「更多连接」元素信息
    more_connections = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="更多连接"]')
    more_connections_btn = get_element_new(driver, more_connections)
   
    # 由「更多连接」元素移动到「WLAN」元素位置(实际工作中,可以通过此种方式实现点到点的连接,完成手势验证码的解锁)
    TouchAction(driver).press(more_connections_btn).wait(500).move_to(wlan_btn).release().perform()
 
    # 关闭驱动
    time.sleep(3)
    print("代码执行完毕")
    driver.quit()

五、toast操作

Toast是Android中用来显示显示信息的一种机制,Toast的特点是没有焦点,而且显示的时间有限,过一定的时间就会自动消失。

定位方法:

初始化配置中需要增加一个配置项:"automationName": "UiAutomator2"

toast 通用的class属性获取,通过xpath的方式://*[@class="android.widget.Toast"]

图片

方法封装:​​​​​​​

代码示例:​​​​​​​

import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as es


# 定义一个初始化APP的方法
def start_app(app_package, app_activity):

    # 定义desired_caps 字典,初始化app的配置信息
    desired_caps = {
        "platformName": "android",  # 表示的是android
        "platformVersion": "10",  # 表示的是设备系统的版本号
        "deviceName": "DWV6R19A10002101",  # 表示的是设备的ID名称
        "appPackage": app_package,  # 表示的是app的包名
        "appActivity": app_activity,  # 表示的是app的界面名
        "newCommandTimeout": 100000,
        "noReset": True,  # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
        # "resetKeyboard": True,  # 重置设备的输入键盘 (连接虚拟机时使用)
        # "unicodeKeyboard": True  # 采用unicode编码输入(连接虚拟机时使用)
        "automationName": "UiAutomator2"  # 获取toast信息需要使用
    }
    # 创建 Appium 驱动实例
    options = UiAutomator2Options().load_capabilities(desired_caps)
    driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)

    # 启动应用程序
    driver.wait_activity(desired_caps, 5)
    return driver


# 定义一个获取元素的方法
def get_element_new(driver, element):
    element = WebDriverWait(driver, 10).until(es.visibility_of_element_located(element))
    return element

# 定义一个封装滑屏操作的方法
def slide_screen(driver, direction, count=1):
    w = driver.get_window_size()["width"]  # 获取手机屏幕的宽度
    h = driver.get_window_size()["height"] # 获取手机屏幕的高度
    # w=1080  h=1920
    if direction == "up":  # 往上滑
        zb = (w/2, h*0.9, w/2, h*0.1)
    elif direction == "down":  # 往下滑
        zb = (w/2, h*0.1, w/2, h*0.9)
    elif direction == 'left':  # 往左滑
        zb = (w*0.9, h/2, w*0.1, h/2)
    elif direction == 'right':   # 往右滑
        zb = (w*0.1, h/2, w*0.9, h/2)
    else:
        print("无法识别滑动方向,请重新输入!")
    for i in range(count):
        driver.swipe(*zb, duration=1200)
        time.sleep(1)


# 定义一个获取toast的方法
def get_toast(driver, timeout=3, poll_frequency=0.5):
    try:
        toast_loc = ("xpath", "//*[@class='android.widget.Toast']")
        WebDriverWait(driver, timeout, poll_frequency).until(es.presence_of_element_located(toast_loc))
        toast_text = driver.find_element(By.XPATH, "//*[@class='android.widget.Toast']").text
        return toast_text

    except:
        return None


if __name__ == "__main__":
    # 本次启动的应用程序包名和活动名(本机设置页面)
    app_package = "com.android.settings"
    app_activity = ".HWSettings"

    # 启动应用程序
    driver = start_app(app_package, app_activity)
    # 向上滑动页面两次到页面底部
    slide_screen(driver, "up", 2)
    time.sleep(2)

    # 找到「关于本机」按钮并点击
    about_this_machine = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="关于手机"]')
    get_element_new(driver, about_this_machine).click()

    # 获取版本号元素信息并点击(for循环进行多次点击)
    version = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="HarmonyOS 版本"]')
    version_btn = get_element_new(driver, version)
    for i in range(1, 6):
        if i <= 6:
            version_btn.click()
            i += 1

    # 获取toast提示信息并打印
    # toast_text = driver.find_element(By.XPATH, "//*[@class=\"android.widget.Toast\"]").text
    # print(f"toast提示信息是:{toast_text}")
    toast_text = get_toast(driver)
    print(toast_text)

    # 关闭驱动
    time.sleep(3)
    print("代码执行完毕")
    driver.quit()

方法二:如果上述方法无法实现获取toast信息,可以通过截图记录toast信息

代码示例如下:​​​​​​​

import time
from appium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from appium.options.android import UiAutomator2Options
from selenium.webdriver.support import expected_conditions as EC
 
 
# 定义一个初始化APP的方法
def start_app(app_package, app_activity):
 
    # 定义desired_caps 字典,初始化app的配置信息
    desired_caps = {
        "platformName": "android",  # 表示的是android
        "platformVersion": "10",  # 表示的是设备系统的版本号
        "deviceName": "DWV6R19A10002101",  # 表示的是设备的ID名称
        "appPackage": app_package,  # 表示的是app的包名
        "appActivity": app_activity,  # 表示的是app的界面名
        "newCommandTimeout": 100000,
        "noReset": True,  # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
        # "resetKeyboard": True,  # 重置设备的输入键盘 (连接虚拟机时使用)
        # "unicodeKeyboard": True  # 采用unicode编码输入(连接虚拟机时使用)
        "automationName": "Uiautomator2"
    }
    # 创建 Appium 驱动实例
    options = UiAutomator2Options().load_capabilities(desired_caps)
    driver = webdriver.Remote("http://localhost:4723/wd/hub", options=options)
 
    # 启动应用程序
    driver.wait_activity(desired_caps, 5)
    return driver
 
 
# 定义一个获取元素的方法
def get_element_new(driver, element):
    element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located(element))
    return element
 
# 定义一个封装滑屏操作的方法
def slide_screen(driver, direction, count=1):
    w = driver.get_window_size()["width"]  # 获取手机屏幕的宽度
    h = driver.get_window_size()["height"] # 获取手机屏幕的高度
    # w=1080  h=1920
    if direction == "up":  # 往上滑
        zb = (w/2, h*0.9, w/2, h*0.1)
    elif direction == "down":  # 往下滑
        zb = (w/2, h*0.1, w/2, h*0.9)
    elif direction == 'left':  # 往左滑
        zb = (w*0.9, h/2, w*0.1, h/2)
    elif direction == 'right':   # 往右滑
        zb = (w*0.1, h/2, w*0.9, h/2)
    else:
        print("无法识别滑动方向,请重新输入!")
    for i in range(count):
        driver.swipe(*zb, duration=1200)
        time.sleep(1)
 
 
if __name__ == "__main__":
    # 本次启动的应用程序包名和活动名(本机设置页面)
    app_package = "com.android.settings"
    app_activity = ".HWSettings"
 
    # 启动应用程序
    driver = start_app(app_package, app_activity)
    # 向上滑动页面两次到页面底部
    slide_screen(driver, "up", 2)
    time.sleep(2)
 
    # 找到「关于本机」按钮并点击
    about_this_machine = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="关于手机"]')
    get_element_new(driver, about_this_machine).click()
 
    # 获取版本号元素信息并点击(for循环进行多次点击)
    version = (By.XPATH, '//android.widget.TextView[@resource-id="android:id/title" and @text="HarmonyOS 版本"]')
    version_btn = get_element_new(driver, version)
    for i in range(1, 6):
        if i <= 6:
            version_btn.click()
            i += 1
 
    # 获取toast信息(截图)
    # 获取手机截图
    """ 1、路径必须手动创建
    2、文件名称必须是以PNG结尾"""
    current_time_file = "/error" + str(time.time())  # 通过文件名拼接当前时间戳的方式构造唯一文件名
    filename = "/替换成自己正确的路径" + current_time_file + ".png"
    time.sleep(0.5)
    driver.get_screenshot_as_file(filename) # 获取toast信息截图
 
    # 关闭驱动
    time.sleep(3)
    print("代码执行完毕")
    driver.quit()

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐