APP自动化测试(8)-元素等待
我们在前面遇到过定位元素时元素还未载入成功,然后定位失败的情况,当这种情况时,我们需要等待元素出现。可以用4种方法
1、强制等待
所谓强制等待就是直接sleep,代码如下
import time
time.sleep(10)
强制等待存在几个问题
- 无论后面步骤元素是否可以定位,都必须等待设置的时间,非常影响自动化测试的效率
- 时间长短不好把握,设长了影响测试的效率,设短了可能元素还未载入成功,导致执行失败
所以一般不建议使用强制等待
2、隐式等待implicitly_wait()
隐式等待的方法是全局设置,存货与webdriver对象的生命周期,设置代码如下
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps)
driver.implicitly_wait(10)
隐式等待是在定位元素时,等到页面所有元素都加载成功后才执行下一步,如果超时时间未定位到元素则抛异常。
隐式等待也存在一些问题
- 当定位的元素已经出来时,页面元素未加载成功,还是会一直等待,影响测试效率
- 抛的异常无法自己设置(如下为关键异常信息),不容易看出是什么元素出问题
selenium.common.exceptions.NoSuchElementException: Message: An element could not be located on the page using the given search parameters.
3、用wait_activity()等待页面出现
当操作为一个元素下一个元素迟迟不出现的情况肯定是切好页面了,所以也可以用wait_activity()来等待预期出现的activity出现后再做下一步元素定位操作。
示意代码如下
#点击记一笔按钮
#time.sleep(5)
add_trans_btn = driver.find_element(AppiumBy.ID,"com.mymoney:id/add_trans_btn")
print("add_trans_btn 的文本是,",add_trans_btn.text)
add_trans_btn.click()
#上述操作后跳转到新的activity,com.mymoney.biz.addtrans.activity.AddTransActivityV12
#等待页面出现
driver.wait_activity(“com.mymoney.biz.addtrans.activity.AddTransActivityV12”)
此方法也有一些问题
- 需要知道操作后下一个activity的名字,操作起来耗费时间
- 有时候activity虽然出现了,可是我们要定位的元素还是没载入成功,最后还是会失败
4、显示等待WebDriverWait()
WebDriverWait()可以应用到确切的元素,而且可以设置抛出异常的类型和抛出异常的消息,方便进行定位
WebDriverWait需要配合until或until_not使用,until用于等待元素出现,until_not用于等待元素消失。
WebDriverWait需要通过“from selenium.webdriver.support.wait import WebDriverWait”引用。
参数说明:
- driver:浏览器驱动,需要传入该参数
- timeout:最长超时时间,默认以秒为单位,必须传入该参数
- poll_frequency:检测的间隔步长,默认为0.5s,可以不传
- ignored_exceptions:超时后的抛出的异常信息,默认抛出NoSuchElementExeception异常,可以不传
until参数说明:
:param method: callable(WebDriver),可以用自定义方法,也可以使用expected_conditions类
:param message: optional message for :exc:`TimeoutException`,默认是空字符串,此处可以设置在失败是我们希望看到的错误信息,便于定位问题
| 方法 | 说明 |
| title_is | 判断当前页面的 title 是否完全等于(==)预期字符串,返回布尔值 |
| title_contains | 判断当前页面的 title 是否包含预期字符串,返回布尔值 |
| presence_of_element_located | 判断某个元素是否被加到了 dom 树里,并不代表该元素一定可见 |
| visibility_of_element_located | 判断元素是否可见(可见代表元素非隐藏,并且元素宽和高都不等于 0) |
| visibility_of | 同上一方法,只是上一方法参数为locator,这个方法参数是 定位后的元素 |
| presence_of_all_elements_located | 判断是否至少有 1 个元素存在于 dom 树中。举例:如果页面上有 n 个元素的 class 都是’wp’,那么只要有 1 个元素存在,这个方法就返回 True |
| text_to_be_present_in_element | 判断某个元素中的 text 是否 包含 了预期的字符串 |
| text_to_be_present_in_element_value | 判断某个元素中的 value 属性是否包含 了预期的字符串 |
| frame_to_be_available_and_switch_to_it | 判断该 frame 是否可以 switch进去,如果可以的话,返回 True 并且 switch 进去,否则返回 False |
| invisibility_of_element_located | 判断某个元素中是否不存在于dom树或不可见 |
| element_to_be_clickable | 判断某个元素中是否可见并且可点击 |
| staleness_of | 等某个元素从 dom 树中移除,注意,这个方法也是返回 True或 False |
| element_to_be_selected | 判断某个元素是否被选中了,一般用在下拉列表 |
| element_selection_state_to_be | 判断某个元素的选中状态是否符合预期 |
| element_located_selection_state_to_be | 跟上面的方法作用一样,只是上面的方法传入定位到的 element,而这个方法传入 locator |
| alert_is_present | 判断页面上是否存在 alert |
代码示意
'''
等待元素出现
利用WebDriverWait 和until
until的参数为自定义方法和expected_conditions方法
'''
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
import time
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions import interaction
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_input import PointerInput
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
caps = {}
caps["platformName"] = "Android"
caps["appium:platfformVersion"] = "11"
caps["appium:deviceName"] = "OFYDHUCIPN8PHEBI"
caps["appium:appPackage"] = "com.mymoney"
caps["appium:appActivity"] = "com.mymoney.biz.main.v12.MainActivityV12"
caps["appium:noReset"] = True
caps["appium:noSign"] = True
caps["appium:unicodeKeyboard"] = True
caps["appium:resetKeyboard"] = True
caps["appium:ensureWebviewsHavePages"] = True
caps["appium:nativeWebScreenshot"] = True
caps["appium:newCommandTimeout"] = 3600
caps["appium:connectHardwareKeyboard"] = True
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", caps)
#定义WebDriverWait对象,设置等待的时间
wait_driver = WebDriverWait(driver,20)
#点击记一笔按钮
add_trans_btn = driver.find_element(AppiumBy.ID,"com.mymoney:id/add_trans_btn")
print("add_trans_btn 的文本是,",add_trans_btn.text)
add_trans_btn.click()
#用自定义方法判断元素是否出现
wait_driver.until(lambda lam1: driver.find_element(AppiumBy.ID,"com.mymoney:id/cost_btn"),"com.mymoney:id/cost_btn 没定位到")
#借助expected_conditions的方法定位元素是否出现
wait_driver.until(ec.presence_of_element_located((AppiumBy.ID,"com.mymoney:id/cost_btn")),"com.mymoney:id/cost_btn 元素找不到")
#presence_of_element_located参数要注意,它只能传一个参数,所以我们参数是传的一个元祖,需要两个小括号
cost_btn = driver.find_element(AppiumBy.ID,"com.mymoney:id/cost_btn")
#向文本框中输入数字
print("输入框中的文本是",cost_btn.text)
总结:
等待元素方法使用建议是根据APP的相应情况使用显示等到,实际应用中可以将是否等到元素出现封装,以便在测试用例中方便使用。
更多推荐
所有评论(0)