Python+Appium自动化测试之元素等待方法与重新封装元素定位方法

在appium自动化测试脚本运行的过程中,因为网络不稳定、测试机或模拟器卡顿等原因,有时候会出现页面元素加载超时元素定位失败的情况,但实际这又不是bug,只是元素加载较慢,这个时候我们就会使用元素等待的方法来避免这种情况,增加代码的健壮性。

一,元素等待方法

1,强制等待

复制代码
import time
 
# 强制等待5s
time.sleep(5)

2,隐式等待

implicitly_wait()是由webdriver提供的隐式等待方法,它不是针对某一个元素,而是针对当前session(即当前driver对象的生命周期)的全部元素,所以只需要在构造driver对象时设置一次即可。隐式等待在定位元素时,需等待该页面全部元素加载完成,才会执行下一步操作(即下一条语句),如果超过设定时间未加载完成则抛出异常。

复制代码
from appium import webdriver
 
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,
    }
    # 启动app
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    # 隐式等待8s
    driver.implicitly_wait(8)
    return driver

3,显式等待

3.1,webDriverWait()是由webdriver提供的显示等待方法。与隐式等待不一样的是,显示等待是针对单个元素定位进行等待,每隔一段时间检查需要定位的元素是否加载完成,超过参数规定的时间仍未定位到该元素,则定位该元素失败,抛出异常。

复制代码
from selenium.webdriver.support.ui import WebDriverWait
 
WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
# 参数说明:
# driver,上面代码返回的driver对象
# timeout,最长等待时间,使用时要考虑隐式等待的时间(假如有设置隐式等待的话)
# poll_frequency,检查元素的时间间隔,默认是0.5s即每隔0.5秒查找一次
# ignored_exceptions,超时后抛出的异常信息,默认NoSuchElementExeception

3.2,WedDriverWait()需要与unit()或until_not()方法结合使用。

复制代码
until(method, message='')
# 源码说明:Calls the method provided with the driver as an argument until the return value is not False.
# 调用driver提供的方法作为参数,直到返回值不是False。
 
until_not(method, message='')
# 源码说明:Calls the method provided with the driver as an argument until the return value is False.
# 调用driver提供的方法作为参数,直到返回值为False

自定义等待时间,使用find_element_by_*()方法定位元素,如下:

复制代码
# 设置等待,最长等待时间为5s,每0.5秒检查一次
wait = WebDriverWait(driver, 5, 0.5)
# 使用匿名函数定位元素
wait.until(lambda diver:driver.find_element_by_id("android:id/button1"))

3.3,WebDriverWait()与expected_conditions结合使用。

expected_conditions是webdriver.support提供的一个类,这个类里面提供了比较多的预期条件判断的方法,但在我们定位元素过程中常用以下三种方法

presence_of_element_located

判断某个元素是否被加载到 dom 树里,但该元素不一定可见

visibility_of_element_located

判断元素是否可见(可见代表元素非隐藏,并且元素宽和高都不等于 0)

element_to_be_clickable

判断某个元素中是否可见并且可点击

复制代码
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
 
wait = WebDriverWait(driver, 5, 0.5)
element = waite.until(EC.presence_of_element_located((By.ID, "android:id/button1"), message="")
# message=""可以省略,注意此时By.ID有两层()
# element = waite.until(EC.presence_of_element_located((By.ID, "android:id/button1"))

二,重新封装元素定位方法

在脚本编写的过程中,为了增加脚本的健壮性,排除非bug因素导致的脚本运行失败,我们可以在定位元素时加入显示等待,封装成新的元素定位方法。

复制代码
# /basePage.py
 
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
 
class BasePage:
    def __init__(self, driver):
        self.driver = driver
 
    def get_visible_element(self, locator, timeout=20):
        '''
        获取可视元素
        param loctor: By方法定位元素,如(By.XPATH, "//*[@text='照片']")
        return:返回可见元素
        '''
        try:
            return WebDriverWait(self.driver, timeout).until(
                ec.visibility_of_element_located(locator)
            )
        except Exception as e:
            # 截图、日志
            Screenshots(self.driver, "获取可视元素失败").screen_shot()
            log.error("获取可视元素失败:{}".format(e))
 
    def get_presence_element(self, locator, timeout=20):
        '''获取存在元素'''
        try:
            return WebDriverWait(self.driver, timeout).until(
                ec.presence_of_element_located(locator)
            )
        except Exception as e:
            Screenshots(self.driver, "获取存在元素失败").screen_shot()
            log.error("获取存在元素失败:{}".format(e))
 
    def get_clickable_element(self, locator, timeout=20):
        '''获取可点击元素'''
        try:
            return WebDriverWait(self.driver, timeout).until(
                ec.element_to_be_clickable(locator)
            )
        except Exception as e:
            Screenshots(self.driver, "获取可点击元素失败").screen_shot()
            log.error("可点击元素获取失败:{}".format(e))

这样就可以调用新的方法来进行元素定位

复制代码
# /homePage.py
 
from basePage import BasePage
 
class HomePage(BasePage):
    i_know_btn = (By.ID, 'com.ss.android.article.news:id/ciy')
    jurisdiction_btn = (By.ID, 'android:id/button1')
    no_login_btn = (By.XPATH, '//android.widget.TabWidget/android.widget.RelativeLayout[@index=3]')
 
    def enter_to_login_page(self):
        '''首页进入未登录页面'''
        get_visible_element(self.i_know_btn).click()
        get_presence_element(self.jurisdiction_btn).click()
        get_clickable_element(self.no_login_btn).click()
总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

相关推荐
returnthem4 天前
安装Appium
appium
seabirdssss9 天前
Appium 在小米平板上的安装受限与闪退排查
android·appium·电脑
小陈的进阶之路13 天前
Selenium 滑动 vs Appium 滑动
python·selenium·测试工具·appium
小陈的进阶之路13 天前
Appium 自动化测试笔记
笔记·appium
linglan42815 天前
APPium环境配置
appium·自动化
lifewange21 天前
Appium是什么
appium·压力测试
柚子+1 个月前
Appium+python+雷电模拟器自动化测试入门
数据库·python·appium
@Aurora.1 个月前
【GUI自动化测试】--基于QQ音乐项目的GUI自动化测试
appium
楚轩努力变强3 个月前
iOS 自动化环境配置指南 (Appium + WebDriverAgent)
javascript·学习·macos·ios·appium·自动化