Selenium
Selenium
Selenium是一个用于Web平台测试的工具,通过模拟用户操作达到测试目的,Selenium本身是一系列工具,支持各种语言,这里以Python语言示例,主要讲Selenium WebDriver
Selenium系列工具
- Selenium WebDriver
Web应用程序的自动化测试工具
- Selenium IDE
自动化测试的一个浏览器插件。提供简单的脚本录制、编辑与回放功能。
- Selenium Grid
用来给自动化测试用例脚本做分布式处理的工具
安装
安装Selenium库
pip install selenium
安装WebDriver驱动程序
Selenium支持市面上所有主流浏览器,但需要使用浏览器官方的自动化支持驱动WebDriver来驱动浏览器
浏览器 | 系统支持 | 下载地址 |
---|---|---|
Chromium/Chrome | Windows/macOS/Linux | Downloads |
Firefox | Windows/macOS/Linux | Downloads |
---|---|---|
Edge | Windows/macOS | Downloads |
Internet Explorer | Windows | Downloads |
Safari | macOS High Sierra 及更高版本 | 内置,无需安装 |
---|---|---|
安装完后解压文件,将 WebDriver 放在 Python 安装目录下
如果不知道Python文件夹在哪,可以在命令行输入where python ,这个命令会告诉你 Python 安装路径
WebDriver 安装成功后可以用以下 Python 代码试运行,如果可以运行,则成功
from selenium import webdriver
driver = webdriver.Chrome()
如果 WebDriver 不放在 Python 目录下的也可以,但是每次都要选择路径,比较麻烦
from selenium import webdriver
driver = webdriver.Chrome('路径/路径/WebDrive')
安装与浏览器相应版本号,或相近版本号
第三方插件方式
市面上浏览器基本上都会自动更新,但是 WebDriver 不会,如果浏览器突然更新,跟现有 WebDriver 版本对不上,就容易出现自动化测试脚本突然报错,我们可以用webdriver-manager管理器这个第三方库来避免这个问题
webdriver-manage安装
pip install webdriver-manager
Chrome_selenium_3实例
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install())
Firefox_selenium_3实例
from selenium import webdriver
from webdriver_manager.firefox import GeckoDriverManager
driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())
Edge_selenium_3实例
from selenium import webdriver
from webdriver_manager.microsoft import EdgeChromiumDriverManager
driver = webdriver.Edge(EdgeChromiumDriverManager().install())
Opera_selenium_3实例
from selenium import webdriver
from webdriver_manager.opera import OperaDriverManager
driver = webdriver.Opera(executable_path=OperaDriverManager().install())
浏览器
浏览器模式
不需要等待页面加载完即操作
from selenium.webdriver import DesiredCapabilities
from selenium import webdriver
capa = DesiredCapabilities.CHROME
capa["pageLoadStrategy"] = "none"
self.driver = webdriver.Chrome(desired_capabilities=capa)
浏览器导航
from selenium import webdriver
# 打开浏览器
driver = webdriver.Chrome()
# 访问网页
driver.get("https://www.baidu.com/")
# 后退
driver.back()
# 前进
driver.forward()
# 刷新
driver.refresh()
# 查看网页标题
driver.title
# 查看当前网址
driver.current_url
浏览器弹窗
# 点击显示弹窗
driver.find_element(By.ID, "弹窗按钮id").click()
# 等待弹窗显示
wait.until(expected_conditions.alert_is_present())
# 获取弹窗
alert = driver.switch_to.alert
# 确认弹窗
alert.accept()
# 取消弹窗
alert.dismiss()
# 输入弹窗
alert.send_keys("文本")
浏览器cookie
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.example.com")
# 添加cookie
driver.add_cookie(
{
"key": "value",
"key": "value"
}
)
# 获取cookie
driver.get_cookie("foo")
# 获取所有cookie
driver.get_cookies()
# 删除cookie
driver.delete_cookie("key")
# 删除所有 Cookie
driver.delete_all_cookies()
浏览器iFrame
网页中可以放置其它网页的内容,也就是iFrame,因为是其它网页的内容,所以需要先步入到iFrame中,才能操作iFrame内的元素
# 使用元素步入
driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "#modal > iframe"))
# 使用ID步入
driver.switch_to.frame('iFrame ID')
# 使用下标步入
iframe = driver.find_elements_by_tag_name('iframe')[1]
# 退出iFrame
driver.switch_to.default_content()
浏览器选项卡
# 获取选项卡句柄
driver.current_window_handle
# 切换选项卡
driver.switch_to.window(选项卡句柄)
# 创建选项卡
driver.switch_to.new_window('tab')
# 关闭选项卡
driver.close()
# 退出浏览器
driver.quit()
浏览器窗口
# 获取窗口大小
width = driver.get_window_size().get("width")
height = driver.get_window_size().get("height")
# 设置窗口大小
driver.set_window_size(1024, 768)
# 获取窗口位置
x = driver.get_window_position().get('x')
y = driver.get_window_position().get('y')
# 设置窗口位置
driver.set_window_position(0, 0)
#最大化窗口
driver.maximize_window()
#最小化窗口
driver.minimize_window()
#全屏窗口
driver.fullscreen_window()
#窗口截图
driver.save_screenshot('./image.png')
#元素截图
driver.find_element(By.CSS_SELECTOR, 'h1')screenshot('./image.png')
#执行JS脚本
header = driver.find_element(By.CSS_SELECTOR, "h1")
driver.execute_script('return arguments[0].innerText', header)
# 打印页面
from selenium.webdriver.common.print_page_options import PrintOptions
print_options = PrintOptions()
print_options.page_ranges = ['1-2']
driver.get("打印页面.html")
base64code = driver.print_page(print_options)
获取网页源代码
driver = webdriver.Chrome()
driver.get("url")
# 获取页面源代码
html_source = driver.page_source
元素
元素定位
定位方式 | 描述 |
---|---|
CLASS_NAME | 通过class属性定位元素 |
CSS_SELECTOR | 通过CSS样式定位元素 |
ID | 通过元素的id属性定位元素 |
NAME | 通过元素的name属性定位元素 |
LINK_TEXT | 用文本定位超链接元素 |
PARTIAL_LINK_TEXT | 用部分文本定位超链接元素 |
TAG_NAME | 用元素的标签名定位元素(默认返回第一个) |
XPATH | 用Xpath路径定位元素 |
# class name定位
element = driver.find_element(By.CLASS_NAME, 'Class名')
# css selector定位
element = driver.find_element(By.CSS_SELECTOR, 'CSS代码')
# id定位
element = driver.find_element(By.ID, 'ID名')
# name定位
element = driver.find_element(By.NAME, 'name名')
# link text定位
element = driver.find_element(By.LINK_TEXT, '文本')
# partial link text定位
element = driver.find_element(By.PARTIAL_LINK_TEXT, '部分文本')
# tag name定位
element = driver.find_element(By.TAG_NAME, '标签名')
# xpath定位
element = driver.find_element(By.XPATH, 'Xpath路径')
相对定位器
Selenium 4 中引入了相对定位器,顾名思义,定位元素的相对位置,用于辅助元素定位
# 找到元素上方的元素
email_locator = locate_with(By.TAG_NAME, "input").above({By.ID: "password"})
# 找到元素下方的元素
password_locator = locate_with(By.TAG_NAME, "input").below({By.ID: "email"})
# 找到元素左方的元素
cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of({By.ID: "submit"})
# 找到元素右方的元素
submit_locator = locate_with(By.TAG_NAME, "button").to_right_of({By.ID: "cancel"})
# 找到元素最近的元素
email_locator = locate_with(By.TAG_NAME, "input").near({By.ID: "lbl-email"})
# 连接元素与元素
submit_locator = locate_with(By.TAG_NAME, "button").below({By.ID: "email"}).to_right_of({By.ID: "cancel"})
元素交互
元素只能执行 4 个基本操作
- 点击(适用于任何元素)
- 发送键(仅适用于文本字段和内容可编辑元素)
- 清除(仅适用于文本字段和内容可编辑元素)
- 下拉列表
点击(适用于任何元素)
元素点击在元素的中心执行点击。如果元素的中心由于某种原因被遮挡,会返回一个元素点击错误。
driver.find_element(By.ID, "id").click()
输入文本
输入时需要元素是个输入框,如果不可以被编辑,会返回元素状态错误
driver.find_element(By.ID, "id").send_keys("webdriver" + Keys.ENTER)
清除内容
清除时需要元素可编辑可重置,否则会返回元素状态错误
SearchInput = driver.find_element(By.ID, "id").send_keys("selenium")
# 清楚内容
SearchInput.clear()
元素信息
是否显示
用于检测元素是否显示在页面上
is_button_visible = driver.find_element(By.ID, "id").is_displayed()
是否启用
用于检测元素是否是启用状态
is_button_enabled = driver.find_element(By.ID, 'id').is_enabled()
是否被选中
用于检测元素是否是启用状态
is_button_selected = driver.find_element(By.ID, 'id').is_selected()
元素标签名
button_tag_name = driver.find_element(By.ID, 'id').tag_name
大小和位置
用于获取引用元素的尺寸和坐标
res = driver.find_element(By.ID, 'id').rect
获取
CSS 属性值
cssValue = driver.findElement(By.ID, 'id').value_of_css_property('color')
获取文字内容
text = driver.find_element(By.ID, 'id').text
下拉列表
要操作列表元素,需要引入以下语句
from selenium.webdriver.support.select import Select
然后创建 Select 对象
select_element = driver.find_element(By.ID,'下拉列表id')
select_object = Select(select_element)
如果下拉列表的HTML是这样
<select>
<option value=value1>北京</option>
<option value=value2 selected>上海</option>
<option value=value3>深圳</option>
</select>
有三种方法可以选择第一个选项:
# 选择下标
select_object.select_by_index(1)
# 选择value值
select_object.select_by_value('value1')
# 选择文本
select_object.select_by_visible_text('北京')
有些下拉列表可以多选,可以用以下方法判断下拉列表是否可以多选
multiple_selections = select_object.is_multiple
然后可以用以下命令来检查选择了哪些选项:
# 返回已选择的列表
all_selected_options = select_object.all_selected_options
# 返回第一个选择
first_selected_option = select_object.first_selected_option
# 返回<select>标签包含的所有选项
all_available_options = select_object.options
如果要取消选择元素,有四个方法:
# 取消第一个选择
select_object.deselect_by_index(1)
# 根据value值取消
select_object.deselect_by_value('value1')
# 根据文本取消
select_object.deselect_by_visible_text('Bread')
# 取消所有
select_object.deselect_all()
等待
代码全程都可以使用Python的内置等待方法,可以在元素交互完成之后等待
#等待1秒
time().sleep(1)
显式等待
允许代码暂停或冻结线程,直到判断条件通过用,或者超时后报错,显示等待需要引入以下语句
from selenium.webdriver.support.ui import WebDriverWait
以下是显示等待的参数
# timeout=等待时间/秒,poll_frequency=检测频率/秒,ignored_excceptions=忽略的异常
# timeout默认10秒,poll_frequency默认0.5秒,ignored_excceptions默认无
# 除了driver,其它可选填
WebDriverWait(driver, timeout=10,poll_frequency=0.5,ignored_excceptions=())
两种等待方式
# 直到找到指定的元素
WebDriverWait(driver).until(判断条件)
# 直到找不到指定的元素
WebDriverWait(driver).until_not(判断条件)
判断条件
需导入模块
from selenium.webdriver.support import expected_conditions as EC
使用判断条件
# 检查10秒,期间判断是否有弹窗,有弹窗则执行下一步,没有则报错
WebDriverWait(driver).until(EC.alert_is_present())
方法 | 描述 |
---|---|
alert_is_present() | 判断是否有弹窗 |
all_of(*判断方法) | 所有判断方法都为真 |
any_of(*判断方法) | 其中一个判断方法为真 |
element_attribute_to_include(元素,属性) | 检查属性是否包含在元素中 |
element_located_selection_state_to_be(…) | 检查元素状态 |
element_located_to_be_selected(定位器) | 判断是否选中了下拉列表 |
element_selection_state_to_be(元素, …) | 判断元素的选中状态 |
element_to_be_clickable(元素) | 检查元素是否可以被点击 |
element_to_be_selected(元素) | 检查是否被选中 |
frame_to_be_available_and_switch_to_it(定位器) | 判断 iFrame 是否可用 |
invisibility_of_element(元素) | 判断元素不存在与DOM中 |
invisibility_of_element_located(定位器) | 判断元素不存在与DOM中 |
new_window_is_opened(窗口句柄) | 判断新窗口出现 |
none_of(*判断方法) | 判断其中一个为假 |
number_of_windows_to_be(窗口数量) | 判断窗口数量 |
presence_of_all_elements_located(*定位器) | 检查多个元素中,至少有一个在DOM中 |
presence_of_element_located(定位器) | 检查DOM中是否有元素 |
staleness_of(元素) | 等某个元素从DOM中移除 |
text_to_be_present_in_element(定位器,文本) | 检查文本是否在元素中 |
text_to_be_present_in_element_attribute(…) | 检查文本是否在元素属性中 |
text_to_be_present_in_element_value(定位器,...) | 检查文本是否在元素的Value属性中 |
title_contains(文本) | 判断网页标题是否包含文本 |
title_is(文本) | 判断网页标题是否是文本 |
url_changes(网址) | 检查当前网址 |
url_contains(网址) | 期望检查当前网址是否包含部分文本 |
url_matches(正则表达式) | 网页网址是否匹配特定内容 |
url_to_be(网址) | 检查重定向的网址 |
visibility_of(元素) | 检查元素是否可见 |
visibility_of_all_elements_located(定位器) | 检查多个元素全部是否可见 |
visibility_of_any_elements_located(定位器) | 检查多个元素其中之一是否可见 |
visibility_of_element_located(定位器) | 检查元素是否可见 |
隐式等待
隐式等待是全局的,只需要设置一次,功能是当元素找不到时,会等待所配置的时间,全局有效。
from selenium import webdriver
driver = webdriver.Chrome()
# 等待秒数
driver.implicitly_wait(10)
提示
显示等待与隐式等待需要二选一,如果混合使用导致不可预测的错误。例如设置10秒的隐式等待和15秒的显式等待,可能会导致 20 秒后才超时
动作生成器
如果要做一系列的交互操作,可以用到动作生成器
ActionChains(driver)\
# 移动到元素上
.move_to_element(driver.find_element(By.ID, "id"))\
# 等待一秒
.pause(1)\
# 左键按住不动
.click_and_hold()\
# 等待一秒
.pause(1)\
# 输入内容
.send_keys("输入内容")\
# 移动到元素上
.perform()
释放操作,动作生成器执行完后,需要释放,否则指针会停留在最后一步
ActionBuilder(driver).clear_actions()
键盘
键盘只能完成两种操作:按下和抬起按键
ActionChains(driver)\
# 按下按键key_down
.key_down(Keys.SHIFT)\
# 输入abd
.send_keys("abc")\
# 指定元素输入
.send_keys_to_element(text_input, "abc")\
# 抬起按键key_down
.key_up(Keys.SHIFT)\
# 执行
.perform()
复制和粘贴,示例代码
cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL
ActionChains(driver)\
.send_keys("Selenium!")\
.send_keys(Keys.ARROW_LEFT)\
.key_down(Keys.SHIFT)\
.send_keys(Keys.ARROW_UP)\
.key_up(Keys.SHIFT)\
.key_down(cmd_ctrl)\
.send_keys("xvv")\
.key_up(cmd_ctrl)\
.perform()
鼠标
ActionChains(driver)\
# 左键单击并按住
.click_and_hold(driver.find_element(By.ID, "元素id"))\
# 左键单击
.click(driver.find_element(By.ID, "元素id"))\
# 右键单击
.context_click(driver.find_element(By.ID, "元素id"))\
# 双击
.double_click(driver.find_element(By.ID, "元素id"))\
# 移动到元素
.move_to_element(driver.find_element(By.ID, "元素id"))\
# 从 元素1 拖到 元素2
.drag_and_drop(driver.find_element(By.ID, "元素1"), driver.find_element(By.ID, "元素2"))\
# 按XY轴偏移量来拖放
.drag_and_drop_by_offset(driver.find_element(By.ID, "元素id"), X , Y)\
.perform()
滚动
ActionChains(driver)\
# 滚动到元素
.scroll_to_element(driver.find_element(By.ID, "元素id"))\
# 按XY轴偏移量滚动
.scroll_by_amount(X, Y)\
.perform()