【Appium】 课程全笔记(录播+直播课)链接:
Appium基础3(手势操作和uiautomator查找元素)
强制等待、隐式等待、显示等待
三者的特点
- 强制等待是sleep,强烈不推荐,设定的时间太固定,如果是模拟器等待3秒,真机可能只需要等待2秒
- driver.implicitly.wat(timeout),贯穿全部元素的等待,只需要设定一次即可,通常是在创建driver的时候后的代码运行,是dom建立之后的等待
- 显示等待是在客户端的等待:引用连个包和一个例子
- from selenium.webdriver.support.wait import WebDriverWait
- from selenium.webdriver.support import expected_conditions
- WebDriverWait(self.driver,10).until(expected_conditions.element_to_be_clickable(locator))
显示等待的简介
- 显示等待与隐式等待相对,显示等待必须在每一个需要等待的元素前面进行声明
- 是针对某个特定的元素设置等待时间,在设置时间内,默认美格一段时间检测一次当前某个元素是否存在
- 如果在规定的时间内找到元素,则直接执行,即找到元素就执行相关操作
- 如果超过设置时间检测不到就抛出异常,默认检测频率为0.5s,默认抛出的异常时NoSuchElementException
- 用到的两个常用类
- WebDriverWait
- expected_condition
为什么要用显示等待,为什么隐式等待无法替代显示等待
- 显示等待可以等待动态加载的ajax元素,需要配合expected_condition来检查条件
- 一般页面上元素的呈现顺序是
- 首先出现title
- 然后是dom树的出现,presence还不完整,dom树出现就是隐式等待了,但此时的元素可能还没有是可点击的状态,所以只用隐式等待,使用click方法,肯定会报错的
- css出现:可见visbility
- js的出现,js特效执行:可点击clickable
- html文档是自上而下加载的
- js文件加载会阻塞html内容的加载,有些js异步加载的方式来完成js的加载
- 样式表下载完成之后跟之前的样式表一起进行解析,会对之前那的与元素重新渲染
- presence-visibility-clickabe,元素出现-可见-可点击,是元素的三个性质,当DOM树出现时,定位元素可能已经显示出来了,但是可见和可点击的属性可能还没加载出来,这时候元素的一些方法是不可用的,比如element.click(),要等到js渲染出来以后,元素的click属性才可以用
- 对应element.is_displayed()
- 对应element.is_selected()
- 对应element.is_enabled()
js的同步加载和异步加载
- 同步加载:同步模式,又称阻塞模式,会阻止浏览器的后续处理,停止了后续的解析,因此停止了后续的文件加载(如图像)、渲染、代码执行。
-异步加载:异步加载又叫非阻塞,浏览器在下载执行 js 同时,还会继续进行后续页面的处理。
WebDriverWait用法
- WebDriverWait(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None)
- driver:浏览器驱动
- timeout:超时时间,单位秒
- poll_frequency:检查的间隔步长,默认是0.5s
- ignored_exceptions:超时最后的抛出的异常,默认是NoSuchElementException
- 通常我们只会用到driver和timeout
- WebDriverWait().unti(self, method, message=‘’) or until_not()的方法:
- method:在等待期间,每个一段时间(__init__中的poll_frequency)调用这个传入的方法,直到返回值不是False
- message:如果超时,抛出TimeoutException,将message传入异常
- until not是当某个元素小时或什么条件则继续执行,参数也相同
expected_conditions类
- appium直接帮我们封装好了类,只需要传参数即可,比如我们使用的是click(),只需要判断这个元素是否可点击属性才继续点击
- 用法:expected_conditions.element_to_be_clickable(locator),其中locator就是:(By.ID, “com.xueqiu.android:id/tv_search”)
- 常用的几个如下:
- expected_conditions.element_to_be_clickable:元素是否可点击
- expected_conditions.presence_of_element_located:元素是否被加到dom树里面
- expected_conditions.visibility_of_element_located:元素是否可见
lambda获取元素
#可以获取到元素
element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH,'//*[@text="我的"]'))
#这里找到元素后,不用等待,实测证明过了
element.click()
实例
from appium import webdriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from appium.webdriver.common.mobileby import MobileBy as By
class TestFind():
def setup(self):
self.desire_cap= {
"platformName":"android",
"deviceName":"127.0.0.1:7555",
"appPackage":"com.xueqiu.android",
"appActivity":".view.WelcomeActivityAlias",
"noReset":"true",
"unicodeKeyboard":True
}
self.driver=webdriver.Remote("http://127.0.0.1:4723/wd/hub",self.desire_cap)
self.driver.implicitly_wait(5)
def test_search(self):
"""
1.打开雪球app
2.点击我的,进入到个人信息页面
3.点击登录,进入到登录页面
4.输入用户名,输入密码
5.点击登录
6.弹出手机号输入失败的提示,并assert这个提示对不对
:return:
"""
#By.name方法不是对应text的,千万不要用
#self.driver.find_element(By.NAME,"我的")
#用显示等待,element_to_be_clickable(locator),里面的locator记得用元祖
WebDriverWait(self.driver, 15).until(expected_conditions.element_to_be_clickable((By.XPATH,'//*[@text="我的"]')))
#在首页找到我的元素,然后点击
self.driver.find_element(By.XPATH,'//*[@text="我的"]').click()
'''
lambda返回元素
element = WebDriverWait(self.driver, 10).until(lambda x: x.find_element(By.XPATH,'//*[@text="我的"]'))
这里找到元素后,不用等待,实测证明过了
element.click()
'''
#显示等待找到账号密码登录的元素
WebDriverWait(self.driver, 15).until(expected_conditions.element_to_be_clickable((By.XPATH,'//*[@text="帐号密码登录"]')))
#识别账号密码登录的元素,然后点击
self.driver.find_element_by_android_uiautomator('new UiSelector().text("帐号密码登录")').click()
#显示等待找到账号的元素
WebDriverWait(self.driver, 15).until(
expected_conditions.element_to_be_clickable((By.XPATH, '//*[@resource-id="com.xueqiu.android:id/login_account"]')))
#输入账号名为tongtong
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/login_account")').send_keys("tongtong")
#输入密码为tongtong
self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/login_password")').send_keys("tongtong")
#显示等待找到登录的按钮
WebDriverWait(self.driver, 15).until(
expected_conditions.element_to_be_clickable((By.XPATH, '//*[@text="登录"]')))
#点击登录按钮
self.driver.find_element_by_android_uiautomator('new UiSelector().text("登录")').click()
#显示等待找到确定的元素
WebDriverWait(self.driver, 15).until(
expected_conditions.element_to_be_clickable((By.XPATH, '//*[@text="确定"]')))
#找到错误提示框,里面有一个确定的元素
login_incorrect=self.driver.find_element_by_android_uiautomator('new UiSelector().text("确定")')
#当确定的元素可见,表示登录失败,用例pass
assert login_incorrect.is_displayed()