文档说明
Selenium是一个用于Web应用程序自动化测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。
Selenium测试的主要功能包括:
测试与浏览器的兼容性:测试应用程序是否能很好的工作在不同的浏览器和操作系统之上。
测试系统功能:创建回归测试,检验软件功能和用户需求。
本文以Python语言为例,主要系统介绍Selenium3.0自动化测试框架的使用中的各种基础、常规操作。
通过学习和实践,达到能够在Python + Selenium的技术架构下进行Web自动化入门测试的目的。
Web自动化测试的技术选型
Web自动化测试工具种类繁多,选择标准应该从以下几个方面重点考虑:
开源免费
业界主流,发展趋势稳定上升
支持主流的浏览器(Chrome、 Firefox、IE等)
支持主流编程语言(Python、Java等)
Selenium的特点
开源免费
多浏览器支持:Chrome、Firefox、IE、Edge、Opera、Safari
多平台支持:Windows、Linux、Mac
多语言支持:Python、Java、Ruby、JavaScript、C#、C++
支持录制、回放和脚本生成(使用Selenium IDE)
支持分布式测试(使用Selenium Grid)
Selenium三剑客
通常所说的Selenium是对Selenium的总称,其中包含三个项目:
Selenium WebDriver,Selenium IDE,Selenium Grid
Selenium WebDriver是客户端API接口,测试人员通过调用这些接口,来访问浏览器驱动,浏览器驱动再访问浏览器。
Selenium IDE是一个浏览器插件,支持Chrome和Firefox浏览器,可以将手动测试过程记录下来生成自动化测试脚本,可以回放。对于初学者的学习脚本和回归测试很有帮助。
Selenium Grid适合分布式测试,例如电商平台的618、双11这种高并发的测试。可以再多台计算机上进行分布式扩容,并从一个中心点管理多个环境,从而轻松的多多种浏览器/OS的组合运行测试。
Selenium的前世今生
Selenium的命名
Selenium官网:www.seleniumhq.org
Selenium的命名比较有意思,ThoughtWorks的Jason Huggins在2004年发起了Selenium项目,当时的QTP mercury是主流的商业自化工具,是化学元素汞(俗称水银),而Selenium是开源自动化工具,是化学元素硒,硒可以对抗汞。
Selenium 1.0
用简单的公式:
Selenium 1.0 = Selenium IDE + Selenium Grid + Selenium RC
Selenium IDE
Selenium IDE是嵌入到Firefox浏览器中的一个插件,实现简单的浏览器操作的录制与回放功能。
Selenium Grid
Selenium Grid是一种自动化的测试辅助工具,Grid通过利用现有的计算机基础设施,能加快Web-App的功能测试。利用Grid可以很方便地实现在多台机器上和异构环境中运行测试用例。
Selenium RC
Selenium RC(Remote Control)是Selenium家族的核心部分。Selenium RC 支持多种不同语言编写的自动化测试脚本,通过Selenium RC的服务器作为代理服务器去访问应用,从而达到测试的目的。
Selenium RC分为Client Libraries和Selenium Server。Client Libraries库主要用于编写测试脚本,用来控制Selenium Server的库。Selenium Server负责控制浏览器行为。
Selenium1.0的核心是RC,它的工作原理是这样的:
在2006年的时候,Google的工程师Simon Stewart发起了WebDriver的项目;因为长期以来Google一直是Selenium的重度用户,但却被限制在有限的操作范围内。
Selenium RC 是在浏览器中运行JavaScript应用,使用浏览器内置的JavaScript翻译器来翻译和执行selenese命令(selenese是Selenium命令集合)。
WebDriver是通过原生浏览器支持或者浏览器扩展来直接控制浏览器。WebDriver针对各个浏览器而开发,取代了嵌入到被测Web应用中的JavaScript,与浏览器紧密集成,因此支持创建更高级的测试,避免了JavaScript安全模型导致的限制。除了来自浏览器厂商的支持之外,WebDriver还利用操作系统级的调用,模拟用户输入。
Selenium与WebDriver原是属于两个不同的项目,WebDriver的创建者Simon Stewart早在2009年8月的一份邮件中解释了项目合并的原因。
Selenium与WebDriver合并原因:为何把两个项目合并?部分原因是WebDriver解决了Selenium存在的缺点(例如能够绕过JavaScript沙箱,我们有出色的API),部分原因是Selenium解决了WebDriver存在的问题(例如支持广泛的浏览器),部分原因是因为Selenium的主要贡献者和我都觉得合并项目是为用户提供最优秀框架的最佳途径。
Selenium 2.0
因为Selenium和Webdriver的合并,所以,Selenium 2.0由此诞生。
简单用公式表示为:Selenium 2.0 = Selenium 1.0 + WebDriver
需要强调的是,在Selenium 2.0中主推的是WebDriver,可以将其看作Selenium RC的替代品。因为Selenium为了保持向下的兼容性,所以在Selenium 2.0中并没有彻底地抛弃Selenium RC。
Selenium2.0的核心是WebDriver。
Selenium 3.0
Selenium 3.0 = Selenium 2.0 - Selenium RC(Remote Control)
= Selenium IDE + Selenium Grid + WebDriver (Selenium三剑客)
Selenium 2.0 = Selenium 1.0 + WebDriver
Selenium 1.0 = Selenium IDE + Selenium Grid + Selenium RC
Selenium 3.0做了如下的更新:
1,去掉了RC
2,Selenium3.0只支持Java8版本以上。
3,Selenium3.0中的Firefox浏览器驱动独立了,以前装完selenium2就可以驱动Firefox浏览器了,现在和Chrome一样,必须下载和设置浏览器驱动。
4,MAC OS 集成Safari的浏览器驱动。默认在/usr/bin/safaridriver 目录下。
5,只支持IE 9.0版本以上。
Selenium 4.0
目前已经更新到4.X版本了,有新的特性以及更新了一些方法的使用。本文以3.0作为说明。
安装Selenium
先安装Python,再安装Selenium。
通过pip命令来安装Selenium:
浏览器驱动
为什么要下载浏览器驱动
Selenium升级到3.0之后,对不同的浏览器驱动进行了规范。如果想使用selenium驱动不同的浏览器,必须单独下载并设置不同的浏览器驱动。
常用浏览器驱动的官方下载地址:
selenium · PyPI
设置浏览器驱动
浏览器的驱动要下载和浏览器配套的版本。
将下载的浏览器驱动放到Python的安装目录下,并且配置系统环境变量:
配置系统环境变量路径:此电脑-->属性-->高级系统设置-->环境变量-->系统变量-->Path,将“C:\Python379”目录添加到Path的值中
测试浏览器驱动是否正常
IDE以Pycharm为例,创建 baidu.py文件,输入以下内容:
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
print(driver.title)
driver.quit()
若不报错,成功打印百度主页的title,说明浏览器驱动设置成功,可以继续进行接下来的操作了。
如报错,请根据报错提示检查和修复。
元素定位
Selenium定位方法
Selenium提供了8种定位方式。
id
name
class name
tag name
link text
partial link text
xpath
css selector
这8种定位方式在Python selenium中所对应的方法为:
find_element_by_id()
find_element_by_name()
find_element_by_class_name()
find_element_by_tag_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_xpath()
find_element_by_css_selector()
定位方法的用法
假如我们有一个Web页面,通过前端工具(如:Firebug 官网:https://getfirebug.com)查看到一个元素的属性是如下这样的:
<html>
<head>
<body link="#0000cc">
<a id="result_logo" href="/" οnmοusedοwn="return c({'fm':'tab','tab':'logo'})">
<form id="form" class="fm" name="f" action="/s">
<span class="soutu-btn"></span>
<input id="kw" class="s_ipt" name="wd" value="" maxlength="255" autocomplete="off">
如果我们的目的是要定位input标签的输入框。
通过id定位:
dr.find_element_by_id("kw")
通过name定位:
dr.find_element_by_name("wd")
通过class name定位:
dr.find_element_by_class_name("s_ipt")
通过tag name定位:
dr.find_element_by_tag_name("input")
通过xpath定位,xpath定位有N种写法,这里列几个常用写法:
dr.find_element_by_xpath("//*[@id='kw']")
dr.find_element_by_xpath("//*[@name='wd']")
dr.find_element_by_xpath("//input[@class='s_ipt']")
dr.find_element_by_xpath("/html/body/form/span/input")
dr.find_element_by_xpath("//span[@class='soutu-btn']/input")
dr.find_element_by_xpath("//form[@id='form']/span/input")
dr.find_element_by_xpath("//input[@id='kw' and @name='wd']")
通过css定位,css定位有N种写法,这里列几个常用写法:
dr.find_element_by_css_selector("#kw")
dr.find_element_by_css_selector("[name=wd]")
dr.find_element_by_css_selector(".s_ipt")
dr.find_element_by_css_selector("html > body > form > span > input")
dr.find_element_by_css_selector("span.soutu-btn> input#kw")
dr.find_element_by_css_selector("form#form > span > input")
页面上有一组文本链接:
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
<a class="mnav" href="http://www.hao123.com" name="tj_trhao123">hao123</a>
通过link text定位:
dr.find_element_by_link_text("新闻")
dr.find_element_by_link_text("hao123")
通过link text定位:
dr.find_element_by_partial_link_text("新")
dr.find_element_by_partial_link_text("hao")
dr.find_element_by_partial_link_text("123")
关于xpah和css的定位比较复杂,需要用到时可以单独学习,本文不展开:
XPath 语法
CSS 选择器参考手册
控制浏览器操作
控制浏览器窗口大小
有时候我们希望能以某种浏览器尺寸打开,让访问的页面在这种尺寸下运行。例如可以将浏览器设置成移动端大小(480* 800),然后访问移动站点,对其样式进行评估;WebDriver提供了set_window_size()方法来设置浏览器的大小。
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("http://m.baidu.com")
# 参数数字为像素点
print("设置浏览器宽480、高800显示")
driver.set_window_size(480, 800)
time.sleep(10)
driver.quit()
在PC端执行自动化测试脚本大多的情况下是希望浏览器在全屏幕模式下执行,可以使用maximize_window()方法使打开的浏览器全屏显示,其用法与set_window_size() 相同,它不需要参数。
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 设置浏览器宽全屏显示,不需要参数
print("设置浏览器宽全屏显示")
driver.maximize_window()
time.sleep(10)
driver.quit()
控制浏览器后退、前进
在使用浏览器浏览网页时,浏览器提供了后退和前进按钮,可以方便地在浏览过的网页之间切换,WebDriver也提供了对应的back()和forward()方法来模拟后退和前进按钮。下面通过例子来演示这两个方法的使用。
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
# 访问百度首页
first_url = 'http://www.baidu.com'
print("now access %s" %(first_url))
driver.get(first_url)
print(driver.title)
# 访问新闻页面
second_url='http://news.baidu.com'
print("now access %s" %(second_url))
driver.get(second_url)
print(driver.title)
# 返回(后退)到百度首页
print("back to %s "%(first_url))
driver.back()
print(driver.title)
# 前进到新闻页
print("forward to %s"%(second_url))
driver.forward()
print(driver.title)
driver.quit()
为了看清脚本的执行过程,下面每操作一步都通过print()来打印当前的URL地址。
刷新页面
有时候需要手动刷新(F5) 页面,使用方法driver.refresh() ,刷新当前页面
WebDriver常用方法
点击和输入
定位元素只是第一步, 定位之后需要对这个元素进行操作, 或单击(按钮) 或输入(输入框) , 下面认识 WebDriver 中最常用的几个方法:
clear(): 清除文本。
send_keys (value): 模拟按键输入。
click(): 单击元素。
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.find_element_by_id("kw").clear()
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
driver.quit()
提交
submit()
submit()方法用于提交表单。 例如, 在搜索框输入关键字之后的“回车” 操作, 就可以通过该方法模拟。
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
search_text = driver.find_element_by_id('kw')
search_text.send_keys('selenium')
search_text.submit()
driver.quit()
有时候 submit()可以与 click()方法互换来使用, submit()同样可以提交一个按钮, 但 submit()的应用范围远不及 click()广泛。
其他常用方法
size: 返回元素的尺寸。
text: 获取元素的文本。
get_attribute(name): 获得属性值。
is_displayed(): 设置该元素是否用户可见。
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 获得输入框的尺寸
size = driver.find_element_by_id('kw').size
print(size)
# 返回百度页面底部备案信息
text = driver.find_element_by_class_name('s-bottom-layer-content').text
print(text)
# 返回元素的属性值, 可以是 id、 name、 type 或其他任意属性
attribute = driver.find_element_by_id("kw").get_attribute('type')
print(attribute)
# 返回元素的结果是否可见, 返回结果为 True 或 False
result = driver.find_element_by_id("kw").is_displayed()
print(result)
time.sleep(10)
driver.quit()
输出结果:
{'height': 44, 'width': 548}
设为首页关于百度About Baidu百度营销使用百度前必读意见反馈帮助中心京公网安备11000002000001号京ICP证030173号©2021 Baidu (京)-经营性-2017-0020
text
True
执行上面的程序并查看结果: size 方法用于获取百度输入框的宽、 高, text 方法用于获得百度底部的备案信息, get_attribute()用于获得百度输入的 type 属性的值, is_displayed()用于返回一个元素是否可见, 如果可见则返回 True, 否则返回 False。
鼠标事件
在 WebDriver 中, 将这些关于鼠标操作的方法封装在 ActionChains 类中提供。
ActionChains 类提供了鼠标操作的常用方法:
perform(): 执行所有 ActionChains 中存储的行为;
context_click(): 右击;
double_click(): 双击;
drag_and_drop(): 拖动;
move_to_element(): 鼠标悬停。
鼠标悬停操作
from selenium import webdriver
# 引入 ActionChains 类
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 定位到要悬停的元素
above = driver.find_element_by_link_text("更多")
# 对定位到的元素执行鼠标悬停操作
ActionChains(driver).move_to_element(above).perform()
说明:
from selenium.webdriver import ActionChains
导入提供鼠标操作的 ActionChains 类。
ActionChains(driver)
调用 ActionChains()类, 将浏览器驱动 driver 作为参数传入。
move_to_element(above)
context_click()方法用于模拟鼠标右键操作, 在调用时需要指定元素定位。
perform()
执行所有 ActionChains 中存储的行为, 可以理解成是对整个操作的提交动作。
键盘事件
Keys()类提供了键盘上几乎所有按键的方法。 前面了解到, send_keys()方法可以用来模拟键盘输入, 除此 之外, 我们还可以用它来输入键盘上的按键, 甚至是组合键, 如 Ctrl+A、 Ctrl+C 等。
from selenium import webdriver
# 引入 Keys 模块
from selenium.webdriver.common.keys import Keys
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
# 输入框输入内容
driver.find_element_by_id("kw").send_keys("seleniumm")
time.sleep(2)
# 删除多输入的一个 m
driver.find_element_by_id("kw").send_keys(Keys.BACK_SPACE)
time.sleep(2)
# 输入空格键+“教程”
driver.find_element_by_id("kw").send_keys(Keys.SPACE)
time.sleep(2)
driver.find_element_by_id("kw").send_keys("教程")
time.sleep(2)
# ctrl+a 全选输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
time.sleep(2)
# ctrl+x 剪切输入框内容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
time.sleep(2)
# ctrl+v 粘贴内容到输入框
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'v')
time.sleep(2)
# 通过回车键来代替单击操作
driver.find_element_by_id("su").send_keys(Keys.ENTER)
time.sleep(10)
driver.quit()
演示代码为了能看清楚执行过程,可以加入sleep(2),正式测试代码不能加sleep等待方法。
上面的演示代码没有实际意义, 仅展示模拟键盘各种按键与组合键的用法。
说明:
from selenium.webdriver.common.keys import Keys
在使用键盘按键方法前需要先导入 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
断言
不管是在做功能测试还是自动化测试,最后一步需要拿实际结果与预期进行比较。这个比较的称之为断言。
通常可以通过获取title 、URL和text等信息进行断言。text方法在前面已经讲过,它用于获取标签对之间的文本信息。 下面同样以百度为例,介绍如何获取这些信息。
from selenium import webdriver
from time import sleep
driver = webdriver.Firefox()
driver.get("https://www.baidu.com")
print('Before search================')
# 打印当前页面title
title = driver.title
print(title)
# 打印当前页面URL
now_url = driver.current_url
print(now_url)
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
sleep(1)
print('After search================')
# 再次打印当前页面title
title = driver.title
print(title)
# 打印当前页面URL
now_url = driver.current_url
print(now_url)
# 获取结果数目
sleep(3)
user = driver.find_element_by_class_name('nums').text
print(user)
sleep(10)
driver.quit()
脚本运行结果如下:
Before search================
百度一下,你就知道
https://www.baidu.com/
After search================
selenium_百度搜索
https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=selenium&fenlei=256&rsv_pq=f58b739f00005ced&rsv_t=dfc6adhvTMwlLK0URN0HpQmDI5YhaCf%2F%2ByTAk9xmtH9V8Vutx%2FSGErJI3DU&rqlang=cn&rsv_enter=0&rsv_dl=tb&rsv_sug3=8&rsv_btype=i&inputT=194&rsv_sug4=194
搜索工具
百度为您找到相关结果约75,500,000个
说明:
title:用于获得当前页面的标题。
current_url:用户获得当前页面的URL。
text:获取搜索条目的文本信息。
设置元素等待
WebDriver提供了两种类型的等待:显式等待和隐式等待。
显式等待
显式等待使WebDriver等待某个条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException)。
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://www.baidu.com")
element = WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located((By.ID, "kw")))
element.send_keys('selenium')
driver.quit()
WebDriverWait类是由WebDirver 提供的等待方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。具体格式如下:
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver :浏览器驱动。
timeout :最长超时时间,默认以秒为单位。
poll_frequency :检测的间隔(步长)时间,默认为0.5S。
ignored_exceptions :超时后的异常信息,默认情况下抛NoSuchElementException异常。
WebDriverWait()一般由until()或until_not()方法配合使用,下面是until()和until_not()方法的说明。
until(method, message=‘’)
调用该方法提供的驱动程序作为一个参数,直到返回值为True。
until_not(method, message=‘’)
调用该方法提供的驱动程序作为一个参数,直到返回值为False。
在本例中,通过as关键字将expected_conditions 重命名为EC,并调用presence_of_element_located()方法判断元素是否存在。
隐式等待
WebDriver提供了implicitly_wait()方法来实现隐式等待,默认设置为0。它的用法相对来说要简单得多。
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from time import ctime
driver = webdriver.Firefox()
# 设置隐式等待为10秒
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
try:
print(ctime())
driver.find_element_by_id("kw22").send_keys('selenium')
except NoSuchElementException as e:
print(e)
finally:
print(ctime())
driver.quit()
implicitly_wait() 默认参数的单位为秒,本例中设置等待时长为10秒。首先这10秒并非一个固定的等待时间,它并不影响脚本的执行速度。其次,它并不针对页面上的某一元素进行等待。当脚本执行到某个元素定位时,如果元素可以定位,则继续执行;如果元素定位不到,则它将以轮询的方式不断地判断元素是否被定位到。假设在第6秒定位到了元素则继续执行,若直到超出设置时长(10秒)还没有定位到元素,则抛出异常。
定位一组元素
WebDriver提供了8种用于定位一组元素的方法。
find_elements_by_id()
find_elements_by_name()
find_elements_by_class_name()
find_elements_by_tag_name()
find_elements_by_link_text()
find_elements_by_partial_link_text()
find_elements_by_xpath()
find_elements_by_css_selector()
定位一组元素的方法与定位单个元素的方法类似,唯一的区别是在单词element后面多了一个s表示复数。
接下来通过例子演示定位一组元素的使用:
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.find_element_by_id("kw").send_keys("selenium")
driver.find_element_by_id("su").click()
sleep(1)
# 定位一组元素
texts = driver.find_elements_by_xpath('//div/h3/a')
# 循环遍历出每一条搜索结果的标题
for t in texts:
print(t.text)
sleep(10)
driver.quit()
程序运行结果:
MeterSphere - 开源自动化测试平台
Selenium automates browsers. That's it!
Selenium(WEB自动化工具) - 百度百科
selenium中文网 | selenium安装、selenium使用、selenium...
Python+Selenium详解(超全)
Selenium Python 测试教程网
Python Selenium库的使用_凯耐的博客-CSDN博客_selenium
功能自动化测试工具——Selenium篇
selenium - 百度翻译
Selenium环境安装配置 - 环境配置 - 测试人社区
多表单切换
在Web应用中经常会遇到frame/iframe表单嵌套页面的应用,WebDriver只能在一个页面上对元素识别与定位,对于frame/iframe表单内嵌页面上的元素无法直接定位。需要通过switch_to.frame()方法将当前定位的主体切换为frame/iframe表单的内嵌页面中。
"""多表单切换"""
from selenium import webdriver
from time import sleep
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.get('http://sahitest.com/demo/framesTest.htm')
def test1(self):
top = self.driver.find_element_by_name('top')
self.driver.switch_to.frame(top)
self.driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[1]').click()
self.driver.switch_to.default_content()
sleep(3)
second = self.driver.find_element_by_xpath('/html/frameset/frame[2]')
self.driver.switch_to.frame(second)
self.driver.find_element_by_xpath('/html/body/table/tbody/tr/td[1]/a[2]').click()
sleep(5)
self.driver.quit()
if __name__ == '__main__':
case = TestCase()
case.test1()
switch_to.frame(reference) :切换frame,reference是传入的参数,用来定位frame,可以传入id、name、index以及selenium的WebElement对象
switch_to_default_content() :返回主文档
switch_to_parent_frame() :返回父文档
多窗口切换
页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要主机切换到新打开的窗口上进行操作。WebDriver提# 多窗口切换
from selenium import webdriver
from time import sleep
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
# 获得百度搜索窗口句柄
search_windows = driver.current_window_handle
driver.find_element_by_link_text('登录').click()
driver.find_element_by_link_text("立即注册").click()
# 获得当前所有打开的窗口的句柄
all_handles = driver.window_handles
# 进入注册窗口
for handle in all_handles:
if handle != search_windows:
driver.switch_to.window(handle)
print('欢迎注册!')
sleep(3)
pass
driver.quit()供了switch_to.window()方法,可以实现在不同的窗口之间切换。
说明:
current_window_handle:获得当前窗口句柄。
window_handles:返回所有窗口的句柄到当前会话。
switch_to.window():用于切换到相应的窗口,与上一节的switch_to.frame()类似,前者用于不同窗口的切换,后者用于不同表单之间的切换。
警告框处理
WebDriver中处理JavaScript所生成的alert、confirm、prompt的具体做法是使用 switch_to.alert 方法定位到 alert/confirm/prompt,然后使用text/accept/dismiss/ send_keys等方法进行操作。
说明:
text:返回 alert/confirm/prompt 中的文字信息。
accept():接受现有警告框。
dismiss():解散现有警告框。
send_keys(keysToSend):发送文本至警告框。keysToSend:将文本发送至警告框。
例如,百度搜索设置弹出的窗口是不能通过前端工具对其进行定位的,这个时候就可以通过switch_to_alert()方法接受这个弹窗。
# 警告框处理
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from time import sleep
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get('http://www.baidu.com')
driver.maximize_window()
# 鼠标悬停至“设置”链接
link = driver.find_element_by_xpath('//span[@id="s-usersetting-top"]')
ActionChains(driver).move_to_element(link).perform()
# 打开搜索设置
sleep(2)
driver.find_element_by_xpath('//div[@class="s-user-setting-pfmenu"]/a[@class="setpref"]').click()
# 保存设置
driver.find_element_by_xpath('//div[@id="se-setting-7"]/a[@class="prefpanelgo setting-btn c-btn c-btn-primary"]').click()
sleep(2)
# 接受警告框
driver.switch_to.alert.accept()
driver.quit()通过switch_to_alert()方法获取当前页面上的警告框,并使用accept()方法接受警告框。
下拉框选择
WebDriver提供了Select工具类来处理下拉框:
"""下拉框选择"""
from selenium import webdriver
from time import sleep
import os
from selenium.webdriver.support.select import Select
class TestCase(object):
def __init__(self):
self.driver = webdriver.Chrome()
path = os.path.dirname(os.path.abspath(__file__))
file_path = 'file:///' + path + '/form.html'
self.driver.get(file_path)
def test_select(self):
se = self.driver.find_element_by_id('province')
select = Select(se)
select.select_by_index(0)
sleep(2)
select.select_by_value('sh')
sleep(2)
select.select_by_visible_text('西安')
sleep(2)
self.driver.quit()
if __name__ == '__main__':
case = TestCase()
case.test_select()
代码中的form表单的form.html代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="javascript:alert('test')">
provide:
<select name="province" id="province">
<option value="bj">北京</option>
<option value="xa">西安</option>
<option value="sh">上海</option>
</select>
</form>
</body>
</html>
说明:
Select类用于定位select标签。
Select_by_index() 根据索引选择。
select_by_value() 根据值选择。
select_by_visible_text()根据文本选择。
文件上传
对于通过input标签实现的上传功能,可以将其看作是一个输入框,即通过send_keys()指定本地文件路径的方式实现文件上传。
首先在Python工程同目录下创建upfile.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>upload_file</title>
</head>
<body>
<div class="row-fluid">
<div class="span6 well">
<h1>upload_file</h1>
<input type="file" name="file" />
</div>
</div>
</body>
</html>
通过浏览器打开upfile.html文件,功能如下:
接着通过send_keys()方法来实现文件上传。
"""文件上传"""
from selenium import webdriver
from time import sleep
import os
driver = webdriver.Chrome()
file_path = 'file:///' + os.path.abspath('upfile.html')
driver.get(file_path)
# 定位上传按钮,添加本地文件
driver.find_element_by_name('file').send_keys('C:\\Users\\pc\\PycharmProjects\\pythonProject1\\upload_file.txt')
sleep(3)
driver.quit()
cookie操作
因为基于真实cookie的测试是无法通过白盒和集成测试进行的。有时候我们需要验证浏览器中cookie是否正确,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信息。
举例:通过get_cookies()来获取当前浏览器的cookie信息。
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.youdao.com")
# 获得cookie信息
cookie= driver.get_cookies()
# 将获得cookie的信息打印
print(cookie)
driver.quit()
从执行结果可以看出,cookie数据是以字典的形式进行存放的:
[{'domain': '.baidu.com', 'expiry': 1614657905, 'httpOnly': False, 'name': 'BA_HECTOR', 'path': '/', 'secure': False, 'value': '8t8k212h0ga500cg2h1g3rar10q'},
{'domain': '.baidu.com', 'httpOnly': False, 'name': 'H_PS_PSSID', 'path': '/', 'secure': False, 'value': '33515_33272_31660_33595_33570_33601_26350_22159'},
{'domain': 'www.baidu.com', 'expiry': 1614654305, 'httpOnly': False, 'name': 'BD_LAST_QID', 'path': '/', 'secure': False, 'value': '9538733699940937218'},
{'domain': '.baidu.com', 'expiry': 1646190304, 'httpOnly': False, 'name': 'BAIDUID', 'path': '/', 'secure': False, 'value': '7663FBCB3A34639C54E8F25076262EF7:FG=1'},
{'domain': '.baidu.com', 'expiry': 3762137951, 'httpOnly': False, 'name': 'BIDUPSID', 'path': '/', 'secure': False, 'value': '7663FBCB3A34639CA4A078B880E2933D'},
{'domain': '.baidu.com', 'expiry': 3762137951, 'httpOnly': False, 'name': 'PSTM', 'path': '/', 'secure': False, 'value': '1614654304'},
{'domain': 'www.baidu.com', 'expiry': 1615518305, 'httpOnly': False, 'name': 'BD_UPN', 'path': '/', 'secure': False, 'value': '12314753'},
{'domain': 'www.baidu.com', 'httpOnly': False, 'name': 'BD_HOME', 'path': '/', 'secure': False, 'value': '1'}
]
知道了cookie的存放形式,就可以按照这种形式向浏览器中写入cookie信息。
"""向浏览器添加cookie"""
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
# 向cookie的name 和value中添加会话信息
driver.add_cookie({'name': 'AAAAA', 'value': 'BBBBB'})
# 遍历cookies中的name 和value信息并打印,当然还有上面添加的信息
for cookie in driver.get_cookies():
print("%s -> %s" % (cookie['name'], cookie['value']))
driver.quit()
输出结果:
C:\Python379\python.exe C:/Users/pc/PycharmProjects/pythonProject1/add_cookie.py
AAAAA -> BBBBB
BA_HECTOR -> 0t8100052l802l6l281g3rbbn0r
H_PS_PSSID -> 33516_33638_33273_31254_33570
BD_LAST_QID -> 15048048474274682553
BAIDUID -> 3D16A792E75CDD10BFF718B4812751EE:FG=1
BIDUPSID -> 3D16A792E75CDD10F3EFD20DBFC21C54
PSTM -> 1614654838
BD_UPN -> 12314753
BD_HOME -> 1
Process finished with exit code 0从执行结果可以看到,第一条cookie信息是在脚本执行过程中通过add_cookie()方法添加的。通过遍历得到所有的cookie信息,从而找到key为“name”和“value”的特定cookie的value。
调用JavaScript代码
虽然WebDriver提供了操作浏览器的前进和后退方法,但对于浏览器滚动条并没有提供相应的操作方法。在这种情况下,就可以借助JavaScript来控制浏览器的滚动条。WebDriver提供了execute_script()方法来执行JavaScript代码。
"""调用js代码"""
from selenium import webdriver
from time import sleep
# 访问百度
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
# 搜索
driver.find_element_by_id("kw").send_keys("测试")
driver.find_element_by_id('su').send_keys(Keys.ENTER)
sleep(2)
# 设置浏览器窗口大小
driver.set_window_size(500, 500)
# 通过javascript设置浏览器窗口的滚动条位置
js = "window.scrollTo(100,450);"
driver.execute_script(js)
sleep(10)
driver.quit()
通过Chrome浏览器打开百度进行搜索,并且提前通过set_window_size()方法将浏览器窗口设置为固定宽高显示,目的是让窗口出现水平和垂直滚动条。然后通过execute_script()方法执行JavaScripts代码来移动滚动条的位置。
窗口截图
自动化用例是由程序去执行的,因此有时候打印的错误信息并不十分明确。如果在脚本执行出错的时候能对当前窗口截图保存,那么通过图片就可以非常直观地看出出错的原因。WebDriver提供了截图函数get_screenshot_as_file()来截取当前窗口。
"""窗口截图"""
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.get('http://www.baidu.com')
driver.find_element_by_id('kw').send_keys('selenium')
driver.find_element_by_id('su').send_keys(Keys.ENTER)
sleep(2)
# 截取当前窗口,并指定截图图片的保存位置
driver.get_screenshot_as_file("C:\\Users\\pc\\PycharmProjects\\pythonProject1\\baidu_img.png")
driver.quit()
脚本运行完成后打设置的截图保存的路径,就可以找到baidu_img.png图片文件了。
关闭浏览器
在前面的例子中我们一直使用quit()方法,其含义为退出相关的驱动程序和关闭所有窗口。除此之外,WebDriver还提供了close()方法,用来关闭当前窗口。多窗口的处理,在用例执行的过程中打开了多个窗口,我们想要关闭其中的某个窗口,这时就要用到close()方法进行关闭了。
close() 关闭单个窗口
quit() 关闭所有窗口
这是我整理的《2024最新Python自动化测试全套教程》,以及配套的接口文档/项目实战【网盘资源】,需要的朋友可以下方视频的置顶评论获取。肯定会给你带来帮助和方向。
【已更新】B站讲的最详细的Python接口自动化测试实战教程全集(实战最新版)