2024最新最全面的Selenium 3.0 + Python自动化测试框架
文档说明
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接口自动化测试实战教程全集(实战最新版)
相关文章:

2024最新最全面的Selenium 3.0 + Python自动化测试框架
文档说明 Selenium是一个用于Web应用程序自动化测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。 Selenium测试的主要功能包括: 测试与浏览器的兼容性:测试应用程序是否能很好的工作在不同的浏览器和操作系统之上。…...

海运中的甩柜是怎么回事❓怎么才能避免❓
什么是甩柜? 甩柜又叫甩箱,是指集装箱船在起运离港时,船公司没有将此前计划装船的集装箱装运上船,导致部分货物滞留港口。多出现在海运旺季。 为什么会甩柜? 甩箱是集装箱物流中常见的事件,主要因为承运…...

Win11+docker+gpu+vscode+pytorch配置anomalib(2)
在上一篇文章中,我在Win11上通过Docker配置了pytorch,并顺利调用了GPU。在这篇文章中,我将继续完成anomalib的配置。 anomalib是一个非常完善的异常检测框架,我希望通过它来学习经典异常检测算法,并且测试这些算法在我自己的数据集上的效果。 步骤如下: 1. 从docker Hub上…...
AI在招聘市场趋势分析中的应用
一、引言 在数字化、智能化的时代背景下,人工智能(AI)技术正逐步渗透到各行各业,其中招聘市场也不例外。AI技术的运用不仅极大地提高了招聘的效率和精准度,还在招聘市场趋势分析方面展现出巨大的潜力。本文旨在探讨AI在…...

AMEYA360:太阳诱电应对 165℃的叠层金属类功率电感器实现商品化!
太阳诱电株式会社实现了可以满足车载被动部件认定的可靠性试验规格“AEC-Q200”的叠层金属类功率电感器 MCOIL™“LACNF2012KKTR24MAB”(2.0x1.25x1.0mm,高度为最大值)等 4 个产品的商品化。通过本公司独有的金属类材料和叠层工艺的提高,在叠层金属类功率…...

Nginx进阶-常见配置(三)
nginx 变量 Nginx的配置文件使用的语法的就是一门微型的编程语言。既然是编程语言,一般也就少不了“变量”这种东西。 Nginx配置文件使用的语法主要包括以下几个方面: (1)配置块 (Block Directives): Nginx配置文件由多个嵌套的…...
开源协作式书签管理器推荐
不知道有没有人和我一样,不怎么爱用app,反而喜欢保留用古老的浏览器浏览新闻和知识的习惯。那么归档网页和书签一定是你非常头疼的事情。 推荐一款开源软件:Linkwarden ,这是一款独立的开源协作式书签管理器。 Linkwarden 允许用户收集、组…...
【线性代数】【二】2.2极大线性无关组与向量空间的基
文章目录 前言一、极大线性无关组二、向量空间的基三、向量维数与向量空间维数总结 前言 上一篇中我们介绍了向量空间的概念,并且学习了对任意给出的一组向量,如果构造一个向量空间。本文将更加细致的去分析张成一个向量空间,具有哪些性质。…...

STM32常见的下载方式有三种
经过对比,推荐使用 SWD下载,只需要一个仿真器(如jLINK、ST LINK、 CMSIS DAP 等),比较方便。 不推荐使用串口下载(速度慢、无法仿真和调试)和 JTAG 下载(占用 IO 多)。...
RK3568-npu模型转换推理
1. rknn-toolkit2-1.4.0进行模型转换和模型推理 1.1 虚拟机转换和模拟器推理(要求ubuntu18+python3.6) sudo apt-get install python3 python3-dev python3-pip sudo apt-get install libxslt1-dev zlib1g-dev libglib2.0 libsm6 libgl1-mesa-glx libprotobuf-dev gcc cd ~…...

《C语言程序设计 第4版》笔记和代码 第十二章 数据体和数据结构基础
12.1从基本数据类型到抽象数据类型 1 所有的程序设计语言都不能将所有复杂数据对象作为其基本数据类型,因此需要允许用户自定义数据类型,在C语言中,就存在构造数据类型(复合数据类型)。 2 结构体是构造数据类型的一种…...

学习记录——day26 进程间的通信 无名管道 无名管道 信号通信 特殊的信号处理
目录 一、进程间通信引入 二、无名管道 1、无名管道相关概念 2、无名管道的API接口函数 pipe(int pipefd[2]); 3、管道通信的特点 4、管道的读写特点 三、有名管道 1、有名管道:有名字的管道文件,其他进程可以调用 2、可以用于亲缘进程间的通信&…...
WHAT - xmlhttprequest vs fetch vs wretch
目录 前言1. XMLHttpRequest (XHR)2. fetch3. wretch总结 fetch1. 简洁性和易用性2. 错误处理3. 默认行为和功能扩展4. 请求和响应的处理5. 跨域请求和 CORS6. 现代 Web 开发需求 fetch vs xhr 代码示例使用 XMLHttpRequest使用 fetch代码对比 前言 根据标题我们可以知道今天主…...

吴恩达老师机器学习作业-ex7(聚类)
导入库,读取数据,查看数据类型等进行分析,可视化数据 import matplotlib.pyplot as plt import numpy as np import scipy.io as sio#读取数据 path "./ex7data2.mat" data sio.loadmat(path) # print(type(data)) # print(data…...
lombok 驼峰命名缺陷,导致后台获取参数为null的解决办法
1.问题: 下面是我定义一个请求类的属性,采用Lombok注解,自动构建get和set方法。 Schema(description "父组织编码", requiredMode Schema.RequiredMode.REQUIRED) private String pOrgCode; 遇到这种命名,你会发现在…...

【dockerpython】亲测有效!适合新手!docker创建conda镜像+容器使用(挂载、端口映射、gpu使用)+云镜像仓库教程
文章目录 docker基本概念简介配置镜像加速源创建conda镜像1. 写 Dockerfile文件2. 创建镜像3. 创建容器并测试 容器的使用1. wsl挂载2. 端口映射3. 补充-gpu 云镜像仓库使用1. 登录2. 将本地镜像上传至云镜像仓库3. 从云镜像仓库下载镜像到本地 docker基本概念简介 简单来讲&a…...
矩阵,求矩阵秩、逆矩阵
求矩阵秩的方法: 高斯消元法:通过行变换将矩阵化为行阶梯形矩阵,然后数非零行的数量。LU分解:通过分解矩阵成上下三角矩阵,计算非零对角元素的数量。SVD分解:通过奇异值分解,计算非零奇异值的数…...
指针和const
const int* ptr,int* const ptr,const int* const ptr 这三种指针定义有什么区别?用法有什么不同? 指向的地址是否可变指向的地址上存储的内容是否可变const属性const int* ptr可改变不可改*ptr具有const属性int* const pts不可改…...

基于C#调用文心一言大模型制作桌面软件(可改装接口)
目录 开发前的准备账号注册应用创建应用接入 开始开发创建项目设计界面使用 AK,SK 生成鉴权签名窗体代码 百度智能云千帆大模型平台什么是百度智能云千帆大模型平台模型更新记录 开发前的准备 账号注册 访问百度智能云平台,通过百度账号登录或手机号验证…...

VScode插件安装
一、常用插件 Chinese (Simplified) (简体中文) Language Pack for Visual Studio Code vscode 中文插件 Auto Rename Tag 闭合标签 Path Intellisense 一个非常实用的工具,它提供了文件路径的自动补全功能,可以极大地提高开发效率。路径自动补全、…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
JS设计模式(4):观察者模式
JS设计模式(4):观察者模式 一、引入 在开发中,我们经常会遇到这样的场景:一个对象的状态变化需要自动通知其他对象,比如: 电商平台中,商品库存变化时需要通知所有订阅该商品的用户;新闻网站中࿰…...

毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...

算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...

UE5 音效系统
一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类,将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix,将上述三个类翻入其中,通过它管理每个音乐…...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...