在之前,遇到下拉框的时候我们可以用两次点击来选择我们需要的选项,不过对于下拉框,我们的webdriver中有封装的Select包单独对于下拉框有一套处理的方法,我们可以来学习一下,然后在测试的时候根据不同的情况来选择需要哪儿种方法。
1.select包方法的使用示例以及定位方式
select下拉框的定位
2.select包内的方法详解
1.获取option元素
options:获取包含select下拉框内所有option项element的列表
all_selected_options: 获取当前选中项element的列表
first_selected_option:获取所有下拉选项中的第一个选项的element(或者获取当前选中的这一项)
2.选择option
select_by_value(values):选择option标签中value属性为:values的选项
select_by_index(index_number):选择索引为index_number的选项(索引从0开始)
select_by_visible_text(text):选择option选项内容为:text的选项
3.复选select的情况(select标签中,multiple="multiple"时,即可多选的select选择框)
deselect_all: 取消所有已选择的选项
deselect_by_value(values):取消选择option标签中value属性为:values的选项
deselect_by_index(index_number):取消选择索引为index_number的选项(索引从0开始)
deselect_by_visible_text(text):取消选择option选项内容为:text的选项
3.实例验证(一)百度贴吧高级搜索下拉框
本条实例主要是获取选项元素和通过方法来选择某项option,代码如下
-
from selenium
import webdriver
-
from selenium.webdriver.support.ui
import Select
-
from time
import sleep
-
-
# 打开Chrome浏览器
-
driver = webdriver.Chrome()
-
-
# 进入百度高级搜索页
-
driver.get(
"http://tieba.baidu.com/f/search/adv")
-
-
# 获取select下拉框的元素
-
ele_select = driver.find_element_by_css_selector(
"select[name='sm']")
-
-
# 获取下拉框中所有选项元素(element)
-
options = Select(ele_select).options
-
print(
"所有选项元素的列表:%s" % options)
-
for i
in options:
-
print(
"元素对应的选项:%s"% i.text)
-
-
# 获取下拉框当前显示(选中)的元素(element)
-
options_selected = Select(ele_select).all_selected_options
-
print(
"-----------------------分隔符---------------------------")
-
print(options_selected)
-
for j
in options_selected:
-
print(
"当前选中的选项(默认项):%s" % j.text)
-
-
# 选择value值为2的选项
-
Select(ele_select).select_by_value(
"2")
-
sleep(
1)
-
-
# 输出默认项(当前选中项)
-
now = Select(ele_select).first_selected_option
-
print(now.text)
4.实例验证(二):多选multiple选择框
我们把我们自己写的表单信息给写入到页面上,使用菜鸟教程在线代码运行工具生成html页面,然后再进行多选select框的验证实验。
-
from selenium
import webdriver
-
from selenium.webdriver.support.ui
import Select
-
from time
import sleep
-
-
# 打开浏览器,进入演示页面
-
driver = webdriver.Chrome()
-
driver.get(
"https://www.runoob.com/runcode")
-
-
# 定位输入框文本域
-
ele_textarea = driver.find_element_by_css_selector(
"#codeinp")
-
-
# 清空文本域
-
ele_textarea.clear()
-
-
# 输入多选下拉框的演示源码 (multiple="multiple\")
-
texts =
"<html> " \
-
"<body><form><select multiple=\"multiple\" name=\"cars\"><option value=\"volvo\">Volvo</option>" \
-
"<option value=\"saab\">Saab</option><option value=\"fiat\">Fiat</option>\" \
-
\"<option value=\"audi\">Audi</option></select></form></body></html>"
-
ele_textarea.send_keys(texts)
-
-
# 点击提交代码
-
submit_button = driver.find_element_by_css_selector(
"#btrun")
-
submit_button.click()
-
sleep(
2)
-
-
# 定位frame和select元素
-
all_handles = driver.window_handles
-
driver.switch_to.window(all_handles[
1])
-
ele_select = driver.find_element_by_css_selector(
"body > form > select")
-
# 选择全部的选项(多选)
-
Select(ele_select).select_by_index(
0)
-
sleep(
1)
-
Select(ele_select).select_by_index(
1)
-
sleep(
1)
-
Select(ele_select).select_by_index(
2)
-
sleep(
1)
-
Select(ele_select).select_by_index(
3)
-
sleep(
1)
-
-
# 取消选择第一项选项(页面上可以观察到变化)
-
Select(ele_select).deselect_by_index(
0)
-
-
# 输出当前选择的第一项
-
now = Select(ele_select).first_selected_option
-
print(now.text)
5.源码展示
-
class Select(object):
-
-
def __init__(self, webelement):
-
"""
-
Constructor. A check is made that the given element is, indeed, a SELECT tag. If it is not,
-
then an UnexpectedTagNameException is thrown.
-
-
:Args:
-
- webelement - element SELECT element to wrap
-
-
Example:
-
from selenium.webdriver.support.ui import Select \n
-
Select(driver.find_element_by_tag_name("select")).select_by_index(2)
-
"""
-
if webelement.tag_name.lower() != "select":
-
raise UnexpectedTagNameException(
-
"Select only works on
<select> elements, not on
<%s>" %
-
webelement.tag_name)
-
self._el = webelement
-
multi = self._el.get_attribute("multiple")
-
self.is_multiple = multi and multi != "false"
-
-
@property
-
def options(self):
-
"""Returns a list of all options belonging to this select tag"""
-
return self._el.find_elements(By.TAG_NAME, 'option')
-
-
@property
-
def all_selected_options(self):
-
"""Returns a list of all selected options belonging to this select tag"""
-
ret = []
-
for opt in self.options:
-
if opt.is_selected():
-
ret.append(opt)
-
return ret
-
-
@property
-
def first_selected_option(self):
-
"""The first selected option in this select tag (or the currently selected option in a
-
normal select)"""
-
for opt in self.options:
-
if opt.is_selected():
-
return opt
-
raise NoSuchElementException("No options are selected")
-
-
def select_by_value(self, value):
-
"""Select all options that have a value matching the argument. That is, when given "foo" this
-
would select an option like:
-
-
<option value="foo">Bar
</option>
-
-
:Args:
-
- value - The value to match against
-
-
throws NoSuchElementException If there is no option with specisied value in SELECT
-
"""
-
css = "option[value =%s]" % self._escapeString(value)
-
opts = self._el.find_elements(By.CSS_SELECTOR, css)
-
matched = False
-
for opt in opts:
-
self._setSelected(opt)
-
if not self.is_multiple:
-
return
-
matched = True
-
if not matched:
-
raise NoSuchElementException("Cannot locate option with value: %s" % value)
-
-
def select_by_index(self, index):
-
"""Select the option at the given index. This is done by examing the "index" attribute of an
-
element, and not merely by counting.
-
-
:Args:
-
- index - The option at this index will be selected
-
-
throws NoSuchElementException If there is no option with specisied index in SELECT
-
"""
-
match = str(index)
-
for opt in self.options:
-
if opt.get_attribute("index") == match:
-
self._setSelected(opt)
-
return
-
raise NoSuchElementException("Could not locate element with index %d" % index)
-
-
def select_by_visible_text(self, text):
-
"""Select all options that display text matching the argument. That is, when given "Bar" this
-
would select an option like:
-
-
<option value="foo">Bar
</option>
-
-
:Args:
-
- text - The visible text to match against
-
-
throws NoSuchElementException If there is no option with specisied text in SELECT
-
"""
-
xpath = ".//option[normalize-space(.) = %s]" % self._escapeString(text)
-
opts = self._el.find_elements(By.XPATH, xpath)
-
matched = False
-
for opt in opts:
-
self._setSelected(opt)
-
if not self.is_multiple:
-
return
-
matched = True
-
-
if len(opts) == 0 and " " in text:
-
subStringWithoutSpace = self._get_longest_token(text)
-
if subStringWithoutSpace == "":
-
candidates = self.options
-
else:
-
xpath = ".//option[contains(.,%s)]" % self._escapeString(subStringWithoutSpace)
-
candidates = self._el.find_elements(By.XPATH, xpath)
-
for candidate in candidates:
-
if text == candidate.text:
-
self._setSelected(candidate)
-
if not self.is_multiple:
-
return
-
matched = True
-
-
if not matched:
-
raise NoSuchElementException("Could not locate element with visible text: %s" % text)
-
-
def deselect_all(self):
-
"""Clear all selected entries. This is only valid when the SELECT supports multiple selections.
-
throws NotImplementedError If the SELECT does not support multiple selections
-
"""
-
if not self.is_multiple:
-
raise NotImplementedError("You may only deselect all options of a multi-select")
-
for opt in self.options:
-
self._unsetSelected(opt)
-
-
def deselect_by_value(self, value):
-
"""Deselect all options that have a value matching the argument. That is, when given "foo" this
-
would deselect an option like:
-
-
<option value="foo">Bar
</option>
-
-
:Args:
-
- value - The value to match against
-
-
throws NoSuchElementException If there is no option with specisied value in SELECT
-
"""
-
if not self.is_multiple:
-
raise NotImplementedError("You may only deselect options of a multi-select")
-
matched = False
-
css = "option[value = %s]" % self._escapeString(value)
-
opts = self._el.find_elements(By.CSS_SELECTOR, css)
-
for opt in opts:
-
self._unsetSelected(opt)
-
matched = True
-
if not matched:
-
raise NoSuchElementException("Could not locate element with value: %s" % value)
-
-
def deselect_by_index(self, index):
-
"""Deselect the option at the given index. This is done by examing the "index" attribute of an
-
element, and not merely by counting.
-
-
:Args:
-
- index - The option at this index will be deselected
-
-
throws NoSuchElementException If there is no option with specisied index in SELECT
-
"""
-
if not self.is_multiple:
-
raise NotImplementedError("You may only deselect options of a multi-select")
-
for opt in self.options:
-
if opt.get_attribute("index") == str(index):
-
self._unsetSelected(opt)
-
return
-
raise NoSuchElementException("Could not locate element with index %d" % index)
-
-
def deselect_by_visible_text(self, text):
-
"""Deselect all options that display text matching the argument. That is, when given "Bar" this
-
would deselect an option like:
-
-
<option value="foo">Bar
</option>
-
-
:Args:
-
- text - The visible text to match against
-
"""
-
if not self.is_multiple:
-
raise NotImplementedError("You may only deselect options of a multi-select")
-
matched = False
-
xpath = ".//option[normalize-space(.) = %s]" % self._escapeString(text)
-
opts = self._el.find_elements(By.XPATH, xpath)
-
for opt in opts:
-
self._unsetSelected(opt)
-
matched = True
-
if not matched:
-
raise NoSuchElementException("Could not locate element with visible text: %s" % text)
-
-
def _setSelected(self, option):
-
if not option.is_selected():
-
option.click()
-
-
def _unsetSelected(self, option):
-
if option.is_selected():
-
option.click()
-
-
def _escapeString(self, value):
-
if '"' in value and "'" in value:
-
substrings = value.split("\"")
-
result = ["concat("]
-
for substring in substrings:
-
result.append("\"%s\"" % substring)
-
result.append(", '\"', ")
-
result = result[0:-1]
-
if value.endswith('"'):
-
result.append(", '\"'")
-
return "".join(result) + ")"
-
-
if '"' in value:
-
return "'%s'" % value
-
-
return "\"%s\"" % value
-
-
def _get_longest_token(self, value):
-
items = value.split(" ")
-
longest = ""
-
for item in items:
-
if len(item) > len(longest):
-
longest = item
-
return longest