WebUI测试 - 浏览器操作

浏览器操作

一、 selenium 与 webdriver

  • Selenium 是一个用于 Web 测试的工具,测试运行在浏览器中,就像真正的用户在手工操作一样。
    • 支持所有主流浏览器,包括 IE, Mozilla Firefox, Safari,Google Chrome, Opera 等。
  • WebDriver 就是对浏览器提供的原生 API 进行封装,使其成为一套更加面向对象的Selenium WebDriver API。
    • 使用这套 API 可以操控浏览器的开启、关闭,打开网页,操作界面元素,控制 Cookie,还可以操作浏览器截屏、安装插件、设置代理、配置证书等

使用 Selenium 实现自动化测试,主要需要 3 个东西:

  1. 测试脚本,可以是 python, java 编写的脚本程序(也可以叫做 client 端)
  2. 浏览器驱动, 这个驱动是根据不同的浏览器开发的,浏览器不同,对应的驱动也不同,甚至同一浏览器不同的版本也需要不同的驱动
  3. 浏览器,目前 selenium 支持市面上大多数浏览器,如:火狐,谷歌, IE 等脚本操作驱动,驱动操作浏览器;浏览器返回给驱动,驱动返回给脚本

1. 安装 selenium

1
pip install selenium

导入

1
from selenium import webdriver

2. 安装 浏览器驱动(chrome)

1. 查看 浏览器版本

image-20210816170441936

2. 驱动下载

驱动下载地址http://chromedriver.storage.googleapis.com/index.html

image-20210816170923649

3. 将驱动放在 python 跟目录

image-20210816171131571

二、设置元素等待

WebDriver 提供了两种类型的等待:强制等待显式等待隐式等待

  • 隐式等待: 设置一个超时时间,在这个时间内不断寻找这个元素,超时找不到就会抛出异常
  • 显示等待: 设置一个超时时间和一个元素查找条件,在这个时间内不断寻找这个元素,超时找不到就会抛出异常
  • 强制等待 : 设置一个事件,程序会在这个位置强制停留一段时间

1. 隐式等待 (页面全部加载)

1
driver.implicitly_wait(10)

优点:

  • 使用简单, 一次添加终生有效
  • 一般在创建 driver 之后设置一个隐式等待(创建 driver 之后设置,目的是让driver 的整个生命周期都有隐式等待的逻辑)
  • 设置后的元素查找全都会进入隐式等待的逻辑

缺点:

  • 无法对指定的元素进行等待
  • 需要等页面全部加载完成, 相对浪费时间, 降低脚本执行速度
1
2
3
4
5
6
7
8
9
10
11
from selenium import webdriver

driver = webdriver.Chrome()
# 隐式等待:设置一个超时时间,在这个时间内,不断的寻找元素,超时找不到就抛出异常
driver.implicitly_wait(10)


driver.get("http://127.0.0.1:8088/login")
driver.find_element_by_name("username").send_keys("libai")
driver.find_element_by_name("password").send_keys("opmsopms123")
driver.find_element_by_class_name("btn-login").click()

2. 显示等待 (页面部分加载)

1
webDriverWait(driver, 等待时间,检查间隔时间).until(EC.元素定位方法)

优点:

  • 不需要等待页面全部加载完成, 相对节省时间
  • 可以指定需要等待的元素, 对一些加载缓慢的元素, 可以为其增加等待时间

缺点:

  • 使用相对复杂, 代码量多

  • 每次等待都需要再写一遍代码

方法导入

1
2
3
from selenium.webdriver.support import expected_conditions as ec  # 提供等待条件
from selenium.webdriver.support.ui import WebDriverWait # 显示等待类
from selenium.webdriver.common.by import By

实例:

1
2
3
4
5
6
7
# 每隔 1 秒检查一次,最多等待 10 秒
ele = WebDriverWait(driver, 10, 1).until(
ec.visibility_of_element_located(
(
By.CSS_SELECTOR, "body > section > div.left-side.sticky-left-side > div.left-side-inner > ul > li:nth-child(2)")
)
)

对 显示等待函数 分装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

def webElementWait(driver, timeout, lo_time, by_locate, locate):
"""
:param driver: 浏览器驱动对象
:param timeout: 最大等待时间
:param lo_time: 轮询时间
:param by_locate: 元素定位方法
:param locate: 元素定位表达式
:return:
"""
# 每隔 0.5 秒检查一次,最多等待 10 秒
ele = WebDriverWait(driver, timeout, lo_time).until(
# 这里传入我们的期望条件
EC.visibility_of_element_located(
(by_locate, locate)
)
)
return ele

可将显示等待与隐式等待结合使用

  • 申明一个隐式等待, 全局通用
  • 对一些加载特别缓慢的元素,设置显示等待, 适当为其增加等待时间
  • 当显示等待与隐式等待一同出现的时候, 取时间更多的一个

三、 webdriver 常用方法

1. 元素操作

  • clear() : 清除文本
  • send_keys(value) : 模拟按键输入(被操作元素需要是文本输入框)
  • click() : 单击元素

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
from selenium import webdriver

driver = webdriver.Chrome()

driver.get("https://www.baidu.com")

driver.find_element_by_id("kw").send_keys("selenium") # 输入内容
driver.find_element_by_id("kw").clear() # 清除内容
driver.find_element_by_id("kw").send_keys("python") # 输入内容
driver.find_element_by_id("su").click() # 点击内容

driver.quit()

2. 元素 返回

  • size :返回元素的尺寸
  • text :获取元素的文本
  • get_attribute(name) :获取属性值

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")

# 获得输入框的尺寸
size = driver.find_element_by_id('kw').size
print(size)

# 返回百度页面底部备案信息
text = driver.find_element_by_id("cp").text
print(text)

# 返回元素的属性值, 可以是 id、 name、 type 或其他任意属性
attribute = driver.find_element_by_id("kw").get_attribute('type')
print(attribute)

driver.quit()

3. 获取页面信息

  • title :获取当前页面的标题
  • current_url : 获取当前页面的 url
  • text : 获取标签对时间的文本信息

注意:

  • 标签元素如果不展示在页面上,获取结果为空
  • 标签对中间没有值,获取结果为空
  • 如 input 标签之类的标签,获取结果为空
  • get_attribute 方法,获取元素某个属性的值
    • ele.get_attribute(‘href’)
    • ele 这个元素的 href 属性的值

四、 控制浏览器操作

1. 控制浏览器大小

最大化 : maximize_window()
最小化 : minimize_window()
设置大小号 : set_window_size()

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from selenium import webdirver

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")

# 设置浏览器最大化
driver.maximize_window()

# 设置浏览器 最小化
driver.minimize_window()

# 参数数字为 像素点
driver.set_window_size(600, 600)

driver.quit()

2. 控制浏览器操作

  • driver.bach() : 后退
  • driver.forward() : 前进
  • driver.refresh() : 刷新
  • driver.quit() : 退出

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from selenium import webdriver

driver = webdriver.Firefox()

# 访问百度首页
driver.get("http://www.baidu.com")

# 访问新闻页面
driver.get("http://news.baidu.com")

# 返回(后退)到百度首页
driver.back()

# 前进到新闻页
driver.forward()

# 刷新界面
driver.refresh()

driver.quit()

五、页面操作

1. 鼠标操作 —- ActionChains

用 selenium 做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击、双击、点击鼠标右键、拖拽等等。

ActionChains 类提供了鼠标操作的常用方法:

  • perform() : 执行操作
  • click() : 左键单击
  • context_click() : 右键单击
  • double_click() : 双击
  • drag_and_drop() : 拖拽
  • move_to_element() : 鼠标悬停

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 要想使用鼠标事件,得导入鼠标事件类
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")

# 定位到要悬停的元素
ele = driver.find_element_by_name("tj_briicon")

# 对元素进行鼠标悬停的操作,当代码中有鼠标事件的时候,自己就不能动鼠标了
ActionChains(driver).move_to_element(ele).perform()

# 右键操作
ActionChains(driver).context_click(ele).perform()

# 单击操作
ActionChains(driver).click(ele).perform()

# 双击
ActionChains(driver).double_click(ele).perform()

# 拖拽, 将元素1 拖动到元素2上面
ActionChains(driver).drag_and_drop(ele1, ele2).perform()

driver.quit()

2. 键盘事件

Keys()类提供了键盘上几乎所有按键的方法。

send_keys()方法可以用来模拟键盘输入,还可以用它来输入键盘上的按键,如Ctrl+A、 Ctrl+C 等

Keys() 常用 的键盘操作:

  • send_keys(Keys.BACK_SPACE) : 删除键 (BackSpace)
  • send_keys(Keys.SPACE) : 空格键 (Space)
  • send_keys(Keys.TAB) : 制表键 (Tab)
  • send_keys(Keys.ESCAPE) : 回退键( Esc)
  • send_keys(Keys.ENTER) : 回车键( Enter)
  • send_keys(Keys.CONTROL,'a') : 全选( Ctrl+A)
  • send_keys(Keys.CONTROL,'c') : 复制( Ctrl+C)
  • send_keys(Keys.CONTROL,'x') : 剪切( Ctrl+X)
  • send_keys(Keys.CONTROL,'v') : 粘贴( Ctrl+V)
  • send_keys(Keys.F1) : 键盘 F1
  • ……
  • send_keys(Keys.F12) : 键盘 F12
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from selenium import webdriver
# 引入 Keys 模块
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")

# 输入框输入内容
driver.find_element_by_id("kw").send_keys("seleniumm")

# 删除多输入的一个 m
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)

# 输入空格键+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
driver.find_element_by_id("kw").send_keys("教程")

# ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')

# ctrl+x 剪切输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')

# ctrl+v 粘贴内容到输入框
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v')

# 通过回车键来代替单击操作
driver.find_element_by_id("su").send_keys(Keys.ENTER)

driver.quit()

3. 文件上传

1. input 标签

对于 input 标签实现的文件上传功能,可以将其看做是一个输入框

直接 send_keys 指定 本地文件的路径 就可以实现文件上传

1
driver.find_element_by_id("albumUpload").send_keys("D:\\day4\qwe.png")
上传多个文件 :
1
driver.find_element_by_id("albumUpload").send_keys(   "D:\\day4\qwe.png\nD:\\day4\qwe1.png")

2. 非 imput 标签

对于非 input 标签实现的文件上传功能

我们可以用模拟键盘敲击的方式实现

安装 pypiwin32
1
python -m pip install pypiwin32
1
2
3
4
5
6
ActionChains(driver).click(driver.find_element_by_id("albumUpload")).perform()

sh = win32com.client.Dispatch("WScript.shell")
time.sleep(3)

sh.Sendkeys("D:\\qwe.png\r\n")
上传多个文件
1
sh.Sendkeys('"D:\\day4\qwe.png" "day4\qwe1.png"\r\n')

1、代码不联想

2、输入法要保持英文输入状态

3、无法处理中文

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from selenium import webdriver
import win32com.client
import time

driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get("https://tinypng.com/")

# 触发上传文件的操作
driver.find_element_by_css_selector("#top .icon").click()
sh = win32com.client.Dispatch("WScript.shell")
time.sleep(3)

sh.Sendkeys("D:\\day6\qqjt.png\n")

driver.quit()

WebDriver 提供了操作 Cookie 的相关方法,可以读取、添加和删除 cookie 信息

WebDriver 操作 cookie 的方法:

  • get_cookies(): 获得所有 cookie 信息

  • get_cookie(name): 返回字典的 key 为“name” 的 cookie 信息

  • add_cookie(cookie_dict) : 添加 cookie。

    • cookie_dict指字典对象,必须有 name 和 value 值
  • delete_cookie(name,optionsString):删除 cookie 信息。

    • name” 是要删除的 cookie 的名称,
    • optionsString” 是该 cookie 的选项,目前支持的选项包括 “路径” , “域”
  • delete_all_cookies(): 删除所有 cookie 信息

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://www.youdao.com")

# 获得 cookie 信息
cookie = driver.get_cookies()

# 将获得 cookie 的信息打印
print(cookie)

driver.quit()

5. 内嵌网页切换 —- iframe

iframe,又叫浮动帧标记,是内嵌的网页元素,可以将一个 html 文件嵌入到另一个 html 文件中显示

对 iframe 进行操作,需要用到以下三种方法:

  • switch_to_iframe() 切换到 iframe 上 ( 未来会被删除,不建议使用 )
  • switch_to.frame() : 切换到 iframe 上
  • switch_to.default_content() : 切换回原主页面

切入内嵌网页后,若想再操作内嵌网页外的元素,需要再切出来

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(5) # 隐式等待
driver.get("http://127.0.0.1:8088/login")

driver.find_element_by_name("username").send_keys("libai")
driver.find_element_by_name("password").send_keys("opmsopms123")
driver.find_element_by_class_name("btn-login").click()

driver.find_element_by_css_selector("[href=\"/project/manage\"] > i").click()
driver.find_element_by_css_selector("[class=\"pull-right\"]").click()

# 定位到内嵌网页
ele = driver.find_element_by_css_selector("[class=\"ke-edit-iframe\"]")

# 切入内嵌网页中
driver.switch_to.frame(ele)
driver.find_element_by_css_selector("[class=\"ke-content\"]").send_keys("123")

# 切入内嵌网页后,若想再操作内嵌网页外的元素,需要再切出来
driver.switch_to.default_content()
driver.find_element_by_css_selector("input + [class=\"btn btn-primary\"]").click()

6. 多标签页切换

在页面操作过程中点击某个链接会弹出新的窗口,这时就需要切换到新打开的窗口上进行操作。

WebDriver 提供了以下方法 :

  • current_window_handle:获得当前标签页句柄

  • window_handles:返回所有便签页的句柄

  • switch_to.window(标签页句柄):切换到对应的标签页

  • 关闭标签页使用 close 方法

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from selenium import webdriver

# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 访问网址
driver.get("http://www.baidu.com")

# 找到搜索按钮
input_element = driver.find_element_by_id("kw")

# 输入搜索内容
input_element.send_keys("成龙\n")

# 点击松勤教育官网
driver.find_element_by_css_selector("#content_left [tpl='se_com_default']:nth-child(3) .c-title [target]").click()

# 获得当前所有打开的窗口的句柄
all_handles = driver.window_handles
print(all_handles)
for handle in all_handles:
driver.switch_to.window(handle)
print(driver.title)

# 退出浏览器
driver.quit()

7. 页面滚动

如果 web 页面过长,而我们需要的元素并不在当前可视页面中,那么 selenium 就无法对其进行操作;

此时,我们就需要像平时操作浏览器一样来滚动页面,使我们需要操作的对象可见!

window.scrollBy()

  • window.scrollBy(0,500) : 向下滚动 500 个像素
  • window.scrollBy(0,-500) : 向上滚动 500 个像素
  • window.scrollBy(500,0) : 向右滚动 500 个像素
  • window.scrollBy(-500,0) : 向左滚动 500 个像素

Selenium 中实现滚动页面

  • driver.execute_script("window.scrollBy(0,500)")
  • driver.execute_script("arguments[0].scrollIntoView();", ele) 滚动至元素 ele 可见

如果页面中的某个元素 有滚动条 :

竖向滚动 :

1
2
3
4
js="document.querySelector("这里填 css 表达式").scrollTop=100"

# 修改这个元素的 scrollTop 就可以
dr.execute_script(js)

控制横向滚动

1
js="document.querySelector("这里填 css 表达式").scrollLeft=100"  

六、 高级元素处理

1. 窗口截图

截屏,整个页面 :

1
driver.get_screenshot_as_file("./all.png")

截屏,某个元素

1
2
ele = driver.find_element_by_id("form")
ele.screenshot("./ele.png")

实例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from selenium import webdriver

# 创建浏览器驱动对象
driver = webdriver.Chrome()

# 访问网址
driver.get("https://www.baidu.com/")

# 截屏,截取整个页面
driver.get_screenshot_as_file("./all.png")

# 截屏,截取单个元素
ele = driver.find_element_by_id("form")
ele.screenshot("./ele.png")

driver.quit()

2. 警告处理

在 WebDriver 中处理 JavaScript 所生成的 alert、 confirm 以及 prompt 十分简单,具体做法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后使用 text/accept/dismiss/ send_keys 等方法进行操作

  • text :返回 alert/confirm/prompt 中的文字信息
  • accept() :接受现有警告框
  • dismiss() :取消现有警告框
  • send_keys(“haha”) :发送文本至警告框
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(5)
driver.get("file:///D:/Users/lenovo/PycharmProjects/script/seleniumStu/test.html")

# 触发对话框
driver.find_element_by_id("bu1").click()
# 获取对话框对象
al = driver.switch_to.alert
# 确认对话框
al.accept()


# 触发确认框
driver.find_element_by_id("bu2").click()
# 获取确认框对象
al = driver.switch_to.alert
# 取消
al.dismiss()

# 触发提示框
driver.find_element_by_id("bu3").click()
# 获取提示框对象
al = driver.switch_to.alert
# 输入内容
al.send_keys("123")

al.accept()

3. 下拉框选择

WebDriver 提供了 Select 类来处理下拉框。注意,只有当下拉框是 select 标签的时候使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from selenium import webdriver
from selenium.webdriver.support.select import Select
import time

# 实例化一个浏览器对象
driver = webdriver.Chrome("D:\\tool\...\chromedriver")
# 访问网址
driver.get("D:\\test\...\selectStu.html")

# 定位到下拉框元素
ele = driver.find_element_by_id("bc288089-c52d-497b-aa4d-71f81b24faa3")

# # 根据 value 属性选择
Select(ele).select_by_value("3")

# 根据下拉框文本选择
Select(ele).select_by_visible_text("3333333")

time.sleep(3)
driver.quit()