Selenium


Selenium

Selenium是一个用于Web平台测试的工具,通过模拟用户操作达到测试目的,Selenium本身是一系列工具,支持各种语言,这里以Python语言示例,主要讲Selenium WebDriver

Selenium系列工具

  • Selenium WebDriver

Web应用程序的自动化测试工具

  • Selenium IDE

自动化测试的一个浏览器插件。提供简单的脚本录制、编辑与回放功能。

  • Selenium Grid

用来给自动化测试用例脚本做分布式处理的工具

安装

安装Selenium库

pip install selenium

安装WebDriver驱动程序

Selenium支持市面上所有主流浏览器,但需要使用浏览器官方的自动化支持驱动WebDriver来驱动浏览器

浏览器系统支持下载地址
Chromium/ChromeWindows/macOS/LinuxDownloadsopen in new window
FirefoxWindows/macOS/LinuxDownloadsopen in new window
EdgeWindows/macOSDownloadsopen in new window
Internet ExplorerWindowsDownloadsopen in new window
SafarimacOS 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()