目录
文档说明
Web自动化测试的技术选型
Selenium的特点
Selenium三剑客
Selenium的前世今生
Selenium的命名
Selenium 1.0
Selenium 2.0
Selenium 3.0
Selenium 4.0
安装Selenium
浏览器驱动
为什么要下载浏览器驱动
设置浏览器驱动
测试浏览器驱动是否正常
元素定位
Selenium定位方法
定位方法的用法
通过id定位:
通过name定位:
通过class name定位:
通过tag name定位:
通过xpath定位,xpath定位有N种写法,这里列几个常用写法:
通过css定位,css定位有N种写法,这里列几个常用写法:
控制浏览器操作
控制浏览器窗口大小
控制浏览器后退、前进
刷新页面
WebDriver常用方法
点击和输入
提交
其他常用方法
鼠标事件
鼠标悬停操作
键盘事件
断言
设置元素等待
显式等待
隐式等待
定位一组元素
多表单切换
多窗口切换
警告框处理
下拉框选择
文件上传
调用JavaScript代码
窗口截图
关闭浏览器
Selenium是一个用于Web应用程序自动化测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。
Selenium测试的主要功能包括:
测试与浏览器的兼容性:测试应用程序是否能很好的工作在不同的浏览器和操作系统之上。
测试系统功能:创建回归测试,检验软件功能和用户需求。
本文以Python语言为例,主要系统介绍Selenium3.0自动化测试框架的使用中的各种基础、常规操作。
通过学习和实践,达到能够在Python + Selenium的技术架构下进行Web自动化入门测试的目的。
Web自动化测试工具种类繁多,选择标准应该从以下几个方面重点考虑:
开源免费
业界主流,发展趋势稳定上升
支持主流的浏览器(Chrome、 Firefox、IE等)
支持主流编程语言(Python、Java等)
开源免费
多浏览器支持:Chrome、Firefox、IE、Edge、Opera、Safari
多平台支持:Windows、Linux、Mac
多语言支持:Python、Java、Ruby、JavaScript、C#、C++
支持录制、回放和脚本生成(使用Selenium IDE)
支持分布式测试(使用Selenium Grid)
通常所说的Selenium是对Selenium的总称,其中包含三个项目:
Selenium WebDriver,Selenium IDE,Selenium Grid
Selenium WebDriver是客户端API接口,测试人员通过调用这些接口,来访问浏览器驱动,浏览器驱动再访问浏览器。
Selenium IDE是一个浏览器插件,支持Chrome和Firefox浏览器,可以将手动测试过程记录下来生成自动化测试脚本,可以回放。对于初学者的学习脚本和回归测试很有帮助。
Selenium Grid适合分布式测试,例如电商平台的618、双11这种高并发的测试。可以再多台计算机上进行分布式扩容,并从一个中心点管理多个环境,从而轻松的多多种浏览器/OS的组合运行测试。
Selenium官网:www.seleniumhq.org
Selenium的命名比较有意思,ThoughtWorks的Jason Huggins在2004年发起了Selenium项目,当时的QTP mercury是主流的商业自化工具,是化学元素汞(俗称水银),而Selenium是开源自动化工具,是化学元素硒,硒可以对抗汞。
用简单的公式:
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和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 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版本以上。
目前已经更新到4.X版本了,有新的特性以及更新了一些方法的使用。本文以3.0作为说明。
先安装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提供了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)查看到一个元素的属性是如下这样的:
说明:
Select类用于定位select标签。
Select_by_index() 根据索引选择。
select_by_value() 根据值选择。
select_by_visible_text()根据文本选择。
对于通过input标签实现的上传功能,可以将其看作是一个输入框,即通过send_keys()指定本地文件路径的方式实现文件上传。
首先在Python工程同目录下创建upfile.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是否正确,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。
虽然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() 关闭所有窗口