需求:使用python selenium来自动测试一个网站注册的流程。
假设这个网站的注册流程分为三步,需要提供比较多的信息:
在这个流程里面,需要用户填入信息、在下拉菜单中选择、选择单选的radio button、多选框等等比较复杂的页面元素操作。
在开始做的时候,我会按照一个用户真正的填写习惯,参照页面,一步步的定义每个步骤应该进行怎样的操作,我需要查看每一个页面元素的属性,决定选择一个合理的选项,然后再用代码自动化这样的操作。但是反思一下,其实这样的实现方法并不符合一个计算机自动测试的习惯,也浪费了许多时间在手动的寻找页面元素的相关属性和合理操作值上。
所谓的自动化,就是要机器在最大程度上的去代替人进行某些操作。而只有在程序自己没有办法判断如何操作的时候,我们才为这类操作定义更详细的规定。例如:从计算机的角度,并不需要关心radio button要选择的是male或是female,也不关心下拉菜单中我们要选择的具体的值是什么;它只需要确保radio button和下拉菜单中可以顺利的选择到一个元素。因此,在这个注册流程中,我可以简单的定义找到页面上所有的radio button,然后挨个把它们都点击一遍,这样既能保证每个radio button都被点击事件测试过,也能保证在注册流程中必定有一个选项被选中了。同样的,我可以定义对每个下拉菜单都选择第一个字值。这样的general的方法,可以把我从对每个元素都要找到它的属性然后对其指定详细的操作的辛苦中一次性的解放出来:
def click_radio_btn(driver): radioBtns = driver.find_elements_by_xpath("//input[@type='radio']") for radioBtn in radioBtns: if radioBtn.is_displayed(): radioBtn.click() |
这里我多进行了一次radioBtn.is_displayed()的判断,原因是在我的流程中有的radio button是在选择了某些特定选项之后才会显示在页面上的,因此对于没有显示的元素就不必进行点击操作,否则会抛出异常:
selenium.common.exceptions.ElementNotVisibleException: Message: u'element not visible
而对于需要填入具体信息的input field来说,我们就必须要给出具体每个输入框的输入值来告诉程序如何处理这些元素了。
在这个这个注册流程中,address的下拉菜单中市的选项是基于省份的选值的。这里有一个ajax的异步调用,当用户选择了一个省份之后才会对市下拉单中的值进行加载。于是问题出现了:由于网络的原因,加载市的值的速度是不一定的,有时也许在执行对市的下拉菜单进行选值的时候其中的值其实还没有加载完成。这时,虽然我们选择的是第一个选项,还是会抛出异常:
selenium.common.exceptions.NoSuchElementException: Message: 'Could not locate element with index 1'
这种情况的解决办法是:使用selenium.webdriver.support.ui.WebDriverWait提供的until来使webdriver等待到指定的条件满足或是规定的timeout time到期:
from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC driver = webdriver.Firefox() driver.get("http://www.zhuce.com") city = WebDriverWait(driver,10).until(EC.element_to_be_clickable((By.NAME,"city"))) Select(city).select_by_index(1) |
这样,webdriver将会等待name为“city”的元素enable了之后才算找到该元素,并继续进行接下来的点击操作。如果在10秒内该元素都没有加载成功的话,才抛出异常:
raise TimeoutException(message)
selenium.common.exceptions.TimeoutException: Message: ''
python selenium中提供了多种元素等待的条件:
title_is title_contains presence_of_element_located visibility_of_element_located visibility_of presence_of_all_elements_located text_to_be_present_in_element text_to_be_present_in_element_value frame_to_be_available_and_switch_to_it invisibility_of_element_located element_to_be_clickable #it is Displayed and Enabled. staleness_of element_to_be_selected element_located_to_be_selected element_selection_state_to_be element_located_selection_state_to_be alert_is_present |
最新内容请见作者的GitHub页:http://qaseven.github.io/