zoukankan      html  css  js  c++  java
  • Python+Appium自动化测试(13)-toast定位

    一,前言

    在app自动化测试的过程中经常会遇到需要对toast进行定位,最常见的就是定位toast或者获取toast的文案进行断言,如下图,通过定位"登录成功"的toast就可以断言今日头条登录用例是否通过。但toast区别于控件元素,无法获取焦点,不能通过uiautomatorviewer.bat、appium、weditor等工具定位,因此我们就需要通过别的方法来定位。

    今日头条app登录成功页面

    二,环境

    • windows 10
    • Android 10
    • appium 1.18.0 (desktop)
    • selenium 3.141.0
    • jdk 1.8

    三,toast定位准备与定位方法

    1,准备

    注意:网上大量的博客都说定位toast需要使用uiautomator2,且需要安装appium-uiautomator2-driver。但我在以上环境定位toast时是不需要uiautomator2,也无需安装appium-uiautomator2-driver,且能定位成功!!!大家可以尝试,如果报错的话就老实按照下面步骤进行吧。

    1.1,在Capablity里新增参数使用uiautomator2:

    desired_caps['automationName'] = 'uiautomator2',
    

    1.2,再安装appium-uiautomator2-driver,命令如下:

    cnpm install appium-uiautomator2-driver

    安装成功后在C:Usersxxx ode_modules会出现如下文件:

    _appium-uiautomator2-driver@1.12.0@appium-uiautomator2-driver
    _appium-uiautomator2-server@1.10.0@appium-uiautomator2-server
    

    2,定位方法

    toast需使用xpath的方式进行定位

    2.1,根据toast的文本内容定位toast

    driver.find_element_by_xpath('//*[@text="xxxxxx"]')
    

    这种方式一般用于判断或断言是否出现文本为"xxxxxx"的toast,因此我们可以封装如下:

    # -*- coding:utf-8 -*-
    # @author: 给你一页白纸
    
    from selenium.webdriver.support import expected_conditions as ec
    from selenium.webdriver.support.ui import WebDriverWait
    from appium.webdriver.common.mobileby import MobileBy as By
    
    def is_toast_exist(driver, text, timeout=20, poll_frequency=0.1):
        '''
        判断toast是否存在,是则返回True,否则返回False
        :param driver: driver实例对象
        :param text: toast文本
        :param timeout: 定位超时时间
        :param poll_frequency: 查询频率
        :return: True or False
        '''
        try:
            toast_loc = (By.XPATH, ".//*[contains(@text, %s)]" % text)
            WebDriverWait(driver, timeout, poll_frequency).until(
                ec.presence_of_element_located(toast_loc)
            )
            return True
        except:
            return False
    

    2.2,根据toast的属性className定位toast

    toast的className值为:android.widget.Toast

    driver.find_element_by_xpath('//*[@class="android.widget.Toast"]')
    

    这种方式一般用于获取toast的文本内容,封装如下:

    # -*- coding:utf-8 -*-
    # @author: 给你一页白纸
    
    def get_toast_text(driver, timeout=20, poll_frequency=0.1):
        '''
        定位toast元素,获取text属性
        :param driver: driver实例对象
        :param timeout: 元素定位超时时间
        :param poll_frequency: 查询频率
        :return: toast文本内容
        '''
        toast_loc = (By.XPATH, '//*[@class="android.widget.Toast"]')
        try:
            toast = WebDriverWait(driver, timeout, poll_frequency).until(
                ec.presence_of_element_located(toast_loc)
            )
            toast_text = toast.get_attribute('text')
            return toast_text
        except Exception as e:
            return e
    

    注意

    • 等待方式只能用presence_of_element_located(),即只能等待其存在,而不能等待其可见。

    • 如果初始化构造driver时已经使用了隐式等待implicitly_wait(),则timeout参数可以不写。

    四,示例代码

    定位今日头条app账号密码登录成功后的 "登录成功"toast

    注意:我这里是将desired_caps里的Uiautomator2参数注释掉了,且未安装appium-uiautomator2-driver,也同样能定位到,大家可在与我相同的环境下进行尝试。

    # -*- coding:utf-8 -*-
    # @author: 给你一页白纸
    
    from appium import webdriver
    from selenium.webdriver.support import expected_conditions as ec
    from selenium.webdriver.support.ui import WebDriverWait
    from appium.webdriver.common.mobileby import MobileBy as By
    
    def android_driver():
        desired_caps = {
            "platformName": "Android",
            "platformVersion": "10",
            "deviceName": "PCT_AL10",
            "appPackage": "com.ss.android.article.news",
            "appActivity": ".activity.MainActivity",
            # "automationName": "UiAutomator2",
            "unicodeKeyboard": True,
            "resetKeyboard": True,
            "noReset": True,
        }
        # 启动app
        driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
        return driver
    
    def is_toast_exist(driver, text, timeout=20, poll_frequency=0.1):
        '''
        判断toast是否存在,是则返回True,否则返回False
        '''
        try:
            toast_loc = (By.XPATH, ".//*[contains(@text, %s)]" % text)
            WebDriverWait(driver, timeout, poll_frequency).until(
                ec.presence_of_element_located(toast_loc)
            )
            return True
        except:
            return False
    
    def get_toast_text(driver, timeout=20, poll_frequency=0.1):
        '''
        定位toast元素,获取text属性
        '''
        toast_loc = (By.XPATH, '//*[@class="android.widget.Toast"]')
        try:
            toast = WebDriverWait(driver, timeout, poll_frequency).until(
                ec.presence_of_element_located(toast_loc)
            )
            toast_text = toast.get_attribute('text')
            return toast_text
        except Exception as e:
            return e
    
    def login_opera(driver):
        '''登录今日头条操作'''
        try:
            # driver.find_element_by_id("com.ss.android.article.news:id/cji").click()  # 点击【同意】
            driver.find_element_by_id("com.ss.android.article.news:id/cji").click() # 点击【我知道了】
            driver.find_element_by_id("android:id/button1").click() # 点击权限管理-确定按钮
            driver.find_element_by_xpath("//android.widget.TabWidget/android.widget.RelativeLayout[@index=3]").click() # 点击未登录
            driver.find_element_by_id("com.ss.android.article.news:id/a10").click() # 未登录页点击登录按钮
            driver.find_element_by_id("com.ss.android.article.news:id/bgh").click() # 登录页点击“。。。”
            driver.find_element_by_xpath("//android.widget.LinearLayout[@index=4]").click() # 选择密码登录
            driver.find_element_by_id("com.ss.android.article.news:id/bu").send_keys("xxxxxxxx")   # 输入账号
            driver.find_element_by_id("com.ss.android.article.news:id/c5").send_keys("xxxxxxxx")   # 输入密码
            driver.find_element_by_id("com.ss.android.article.news:id/a2o").click() # 点击登录
        except Exception as e:
            print("登录错误,原因为:{}".format(e))
            # 报错时截图
            driver.get_screenshot_as_file(r'E:loglog_scriptimages	est_login_error_01.png')
        else:
            toast_text = get_toast_text(driver)
            print(toast_text)
            toast_el = is_toast_exist(driver, "登录成功")
            print(toast_el)
    
    if __name__ == '__main__':
        driver = android_driver()
        login_opera(driver)
    

    运行结果如下,说明定位该toast成功:

    C:UsersxiaoqqAppDataLocalProgramsPythonPython37python.exe E:/blog/blog_script/login_jrtt.py
    登录成功
    True
    
    Process finished with exit code 0
    
  • 相关阅读:
    字符串的基本操作
    PHP & Delphi 語法
    Delphi项目构成之单元文件PAS
    Delphi项目构成之项目文件DPR
    Delphi项目的构成
    關於那我的編程歷史..
    點擊Button,在Label1顯示HelloWorld!。
    開博客了, 因為搞Delphi 開發的關於Delphi學習
    Java 基础知识(一)
    关于多线程对于全局变量的资源竞争问题
  • 原文地址:https://www.cnblogs.com/lfr0123/p/13706075.html
Copyright © 2011-2022 走看看