一文讲透彻selenium

发展历史

selenium core

2004年在 ThoughtWorks 公司,一个叫做 Jason Huggins 为了减少手工测试的工作,自己写了一套 JavaScript 的库,这套库可以进行页面交互,并且可以重复的在不同浏览器上进行重复的测试操作。
这套库后来变为了 Selenium Core,为Selenium Remote Control (RC) 和 Selenium IDE提供了坚实的核心基础能力。[1]

selenium RC

Selenium Core是第一个工具。但是,由于同源政策,Selenium Core在跨域测试方面遇到了障碍。同源策略禁止JavaScript代码访问托管在与JavaScript启动位置不同的域上的Web元素。为了克服同源策略问题,测试人员需要安装Selenium Core(一个JavaScript程序)和包含被测试Web应用程序的Web服务器的本地副本,以便它们属于相同的域。这导致了Selenium RC的诞生,它被认为是当时的ThoughtWork的工程师保罗·哈曼特(Paul Hammant)。[2]
补充:同源策略问题,测试用例部署在与被测应用相同的服务器上(只要被测应用和测试脚本同源就可以)。这也意味着,你无法测试别人的网站,比如 https://www.baidu.com


基于上述问题,selenium RC 做了两点[3]:

  • The Selenium Server which launches and kills browsers, interprets and runs the Selenese commands passed from the test program, and acts as an HTTP proxy, intercepting and verifying HTTP messages passed between the browser and the AUT.
  • Client libraries which provide the interface between each programming language and the Selenium RC Server.
    在这里插入图片描述
早期的webdriver

就在Selenium处于开发阶段的同时,另一款浏览器自动化框架WebDriver也正在ThoughtWorks公司的酝酿之中。WebDriver的最初代码在2007年初发布。WebDriver项目的初衷是把端对端测试与底层测试工具隔离开。通常情况下,这种隔离手段通过适配器(Adapter)模式完成。WebDriver正是来源于该方法在许多项目上的不断实践应用,最初是HtmlUnit的封装,工具发布后很快开始支持Internet Explorer和Firefox。[4]

Selenium 2.0 = Selenium 1.0 + WebDriver

2009年8月由 Selenium 1.0 和 WebDriver 项目合并而成,需要注意的是,在 Selenium 2.0 中主推的是 WebDriver,可以将其看作 Selenium RC 的替代品。为了保持向下的兼容性,Selenium 2.0 并没有彻底抛弃 Selenium RC。

Selenium RC 是在浏览器中运行 JavaScript 应用,使用浏览器内置的 JavaScript 翻译器来翻译和执行 selenese 的(selenese 是 Selenium 命令集合)。
WebDriver 通过原生浏览器支持或者浏览器扩展来直接控制浏览器。WebDriver 是针对各个浏览器而开发的,取代了嵌入被测 Web 应用中的 JavaScript。WebDriver 与浏览器紧密集成,支持创建更高级的测试,避免了 JavaScript 安全模型导致的限制。除来自浏览器厂商的支持外,WebDriver 还可利用操作系统级的调用,模拟用户输入。
Selenium 与 WebDriver 原本属于两个不同的项目,WebDriver 的创建者 Simon Stewart早在 2009 年 8 月的一封邮件中解释了项目合并的原因[5]。
在这里插入图片描述

Selenium 3.0 = Selenium 2.0 −Selenium RC
  • Selenium 3.0在Selenium2.0的基础上有了更多的改进,支持的原生驱动方面更为丰富[6]
  • 去掉了对SeleniumRC的支持。
  • JDK的最低版本要求为JDK8(只有在测试分布式的时候,才需要Java环境)。

w3c WebDriver

W3C组织制定了一套浏览器自动化的规范叫做WebDriver,这套规范规定了所有的浏览器生产商都必须遵守这个规范[7]。
其实定义了好多的遵循的接口和WebDriver的概念。对于Chrome、Firefox、Opera、Safari他们都需要遵守这个规范并且实现规范里面的接口,这些实现一般都是伴随浏览器的开发进行的。
Selenium不管是WebDriver还是Remote WebDriver都是W3C WebDriver的一种实现而已。真正的核心浏览器的交互在对应的浏览器的WebDriver上,其实你有了对应的浏览器的WebDriver,参考W3C的标准接口文档HTTP-based wire protocol你就可以单独实现浏览器的操作

webdriver 基于的协议:JSON Wire protocol

JSON Wire protocol是在http协议基础上,对http请求及响应的body部分的数据的进一步规范。
我们知道在HTTP请求及响应中常常包括以下几个部分:http请求方法、http请求及响应内容body、http响应状态码等[8]。
http请求方法:

  • GET:用来从服务器获取信息。比如获取网页的标题信息
  • POST:向服务器发送操作请求。比如findElementClick

http响应状态码:
在WebDriver中为了给用户以更明确的反馈信息,提供了更细化的http响应状态码,比如:

  • 7: NoSuchElement
  • 11:ElementNotVisible
  • 200:Everything OK

http请求及响应的body部分:

  • body部分主要传送具体的数据,在WebDriver中这些数据都是以JSON的形式存在并进行传送的,这就是JSON Wire protocol。

JSON是一种数据交换的格式,是对XML的升级与替代,下面是一个JSON文件的例子:

{
  "firstname": "Alex",
  "lastname": "Smith",
  "moble": "13300000000"
}

下面的例子是WebDriver中在成功找到一个元素后JSON Wire Protocol的返回:

{"status" : 0, "value" : {"element" : "123422"}}

所以在ClientServer之间,只要是基于JSON Wire Protocol来传递数据,就与具体的脚本语言无关了,这样同一个浏览器的驱动就即可以处理Java语言的脚本,也可以处理Python语言的脚本了。

webDriver使用案例

抛开selenium,我们通过 w3c webDriver协议,也可以调用浏览器进行自动化进行操作。以通过调用ChromeDriver.exe 为例。

ChromeDriver.exe是一个可以独立运行的服务器程序,适用于Chrome浏览器。它实现了 WebDriver 协议。(下载地址:http://chromedriver.storage.googleapis.com/index.html

C:\Users\yangbo>chromeDriver.exe -h
Usage: chromeDriver.exe [OPTIONS]

Options
  --port=PORT                     port to listen on
  --adb-port=PORT                 adb server port
  --log-path=FILE                 write server log to file instead of stderr, increases log level to INFO
  --log-level=LEVEL               set log level: ALL, DEBUG, INFO, WARNING, SEVERE, OFF
  --verbose                       log verbosely (equivalent to --log-level=ALL)
  --silent                        log nothing (equivalent to --log-level=OFF)
  --append-log                    append log file instead of rewriting
  --replayable                    (experimental) log verbosely and don't truncate long strings so that the log can be replayed.
  --version                       print the version number and exit
  --url-base                      base URL path prefix for commands, e.g. wd/url
  --readable-timestamp            add readable timestamps to log
  --enable-chrome-logs            show logs from the browser (overrides other logging options)
  --allowed-ips=LIST              comma-separated allowlist of remote IP addresses which are allowed to connect to ChromeDriver
  --allowed-origins=LIST          comma-separated allowlist of request origins which are allowed to connect to ChromeDriver. Using `*` to allow any host origin is dangerous!

首先启动chromedriver,默认端口9515,更改端口-port=xxxx参数,请求本地driverSerice创建session,并新打开一个浏览器界面:

import requests
import time
driver_url = 'http://localhost:9515/session'
driver_value = {"capabilities":
                {"firstMatch": [{}],
                 "alwaysMatch":
                 {"browserName":
                  "chrome",
                  "platformName": "any",
                  "goog:chromeOptions":
                  {"extensions": [], "args": []}}},
                "desiredCapabilities":
                {"browserName":
                 "chrome",
                 "version": "",
                 "platform": "ANY",
                 "goog:chromeOptions": {"extensions": [],
                                        "args": []}}}

response_session = requests.post(driver_url, json = driver_value)
print(response_session.json())

获取sessionId,添加到请求参数中,执行一个百度一下的完整案例:

import requests
import time
driver_url = 'http://localhost:9515/session'
driver_value = {"capabilities":
                    {"firstMatch": [{}],
                     "alwaysMatch":
                         {"browserName":
                              "chrome",
                          "platformName": "any",
                          "goog:chromeOptions":
                              {"extensions": [], "args": []}}},
                "desiredCapabilities":
                    {"browserName":
                         "chrome",
                     "version": "",
                     "platform": "ANY",
                     "goog:chromeOptions": {"extensions": [],
                                            "args": []}}}

response_session = requests.post(driver_url, json = driver_value)


sessionId = response_session.json()["value"]["sessionId"]
url = driver_url+'/'+sessionId+'/url'
value = {"url": "https://www.baidu.com/", "sessionId": sessionId}
res = requests.post(url = url,json = value)


time.sleep(1)
url = driver_url+'/'+sessionId+'/element'
pars = {"using": "css selector", "value": "#kw", "sessionId": sessionId}
r = requests.post(url,json=pars)
elementIdInput = list(r.json()['value'].values())[0]

time.sleep(1)
url = driver_url+'/'+sessionId+'/element/'+elementIdInput+'/value'
pars = {"text": "test"}
r = requests.post(url,json=pars)

time.sleep(1)
url = driver_url+'/'+sessionId+'/element'
pars =  {"using":"css selector","value":"#su", "sessionId": sessionId}
r = requests.post(url,json=pars)
print(r.json())
elementIdSearch = list(r.json()['value'].values())[0]


url = driver_url+'/'+sessionId+'/element/'+elementIdSearch+'/click'
r = requests.post(url,json=pars)

通过上述案例发现,chromeDriver.exe,启动一个client端,client 端通过携带sessionremote server端发送请求,浏览器实现了webdriver的统一接口,所以就行进行相应的动作。
各大浏览器都遵循w3c webdriver的规范,于是有了对应的IEDriverFireFoxDriverchromeDriver等等。
以上内容仅仅是webdriver本身API提供的能力,没有用到任何selenium相关。

selenium 的工作原理

当看懂上述webDriver的原理后,就不难理解selenium webdriver了。selenium webdriver不需要直接操作浏览器,而是通过HTTP接口向驱动发出符合WebDriver规范的指令,就可以完成对浏览器的控制。
在这里插入图片描述
python+ selenium+chrome浏览器环境部署 为例

selenium依赖安装
C:\Users\name>pip install selenium
Collecting selenium
  Downloading selenium-3.4.3-py2.py3-none-any.whl (931kB)
    26% |████████                       | 245kB 576kB/s eta 0:00:02    
    27% |█████████                      | 256kB 570kB/s eta 0:00:02    
    28% |██████████                     | 266kB 536kB/s eta 0:00:0    
    29% |███████████                    | 276kB 530kB/s eta 0:00:0    
    30% |████████████                   | 286kB 586kB/s eta 0:00:0
……
常用webdriver下载地址

*浏览器版本要和webDriver版本一一对应,否则可能出现执行报错。需要将webDriver加入到环境变量,浏览器.exe添加到环境变量。

IE浏览器:http://docs.seleniumhq.org/download/
Firfox浏览器:https://github.com/mozilla/geckodriver/releases
Chrome浏览器:http://chromedriver.storage.googleapis.com/index.html
Edge浏览器:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/

quick start

环境配置完毕,就可以创建一个测试脚本:

#test.py
from selenium import webdriver

driver = webdriver.Chrome()    # Chrome浏览器
driver.get('https://www.baidu.com')

print(driver.title)

driver.quit()
部分源码

在这里插入图片描述

#remote_connection.py 

...
self._commands = {
            Command.STATUS: ('GET', '/status'),
            Command.NEW_SESSION: ('POST', '/session'),
            Command.GET_ALL_SESSIONS: ('GET', '/sessions'),
            Command.QUIT: ('DELETE', '/session/$sessionId'),
            Command.GET_CURRENT_WINDOW_HANDLE:
                ('GET', '/session/$sessionId/window_handle'),
            Command.W3C_GET_CURRENT_WINDOW_HANDLE:
                ('GET', '/session/$sessionId/window'),
            Command.GET_WINDOW_HANDLES:
                ('GET', '/session/$sessionId/window_handles'),
            Command.W3C_GET_WINDOW_HANDLES:
                ('GET', '/session/$sessionId/window/handles'),
            Command.GET: ('POST', '/session/$sessionId/url'),
            Command.GO_FORWARD: ('POST', '/session/$sessionId/forward'),
            Command.GO_BACK: ('POST', '/session/$sessionId/back'),
            Command.REFRESH: ('POST', '/session/$sessionId/refresh'),
            Command.EXECUTE_SCRIPT: ('POST', '/session/$sessionId/execute'),
            Command.W3C_EXECUTE_SCRIPT:
                ('POST', '/session/$sessionId/execute/sync'),
            Command.W3C_EXECUTE_SCRIPT_ASYNC:
                ('POST', '/session/$sessionId/execute/async'),
            Command.GET_CURRENT_URL: ('GET', '/session/$sessionId/url'),
            Command.GET_TITLE: ('GET', '/session/$sessionId/title'),
            Command.GET_PAGE_SOURCE: ('GET', '/session/$sessionId/source'),
            Command.SCREENSHOT: ('GET', '/session/$sessionId/screenshot'),
            Command.ELEMENT_SCREENSHOT: ('GET', '/session/$sessionId/element/$id/screenshot'),
            Command.FIND_ELEMENT: ('POST', '/session/$sessionId/element'),
            Command.FIND_ELEMENTS: ('POST', '/session/$sessionId/elements'),
            Command.W3C_GET_ACTIVE_ELEMENT: ('GET', '/session/$sessionId/element/active'),
            Command.GET_ACTIVE_ELEMENT:
                ('POST', '/session/$sessionId/element/active'),
            Command.FIND_CHILD_ELEMENT:
                ('POST', '/session/$sessionId/eleme
                ... ...
部分常用方法
1. 创建对象driver
driver = webdriver.Chrome()

2. 浏览器中加载url
driver.get(url)

3. 浏览器窗口最大化
driver.maximize_window()

4. 浏览器窗口固定大小
driver.set_window_size(x, y)

5. 向前
driver.forward()

6. 后退
driver.back()

7. 刷新
driver.refresh()

8. 截屏
driver.get_screenshot_as_file(filename)

9. 设置等待时间:时间单位为s,有时候页面元素加载不全的时候,我们需要去用等待时间,等待页面加载完全。显示等待,隐式等待
time.sleep(n)
driver.implicitly_wait(10)  # seconds

10. 获得当前页面的url
driver.current_url

11. 获得当前页面的标题
driver.title

12. 退出
driver.quit()   用于结束进程,关闭所有的窗口,最后测试结束的时候,建议大家用quit

13.获取元素的文本
driver.find_element_by_id("kw).text

14.设置该元素是否用户可见
driver.find_element_by_id("kw").is_displayed()  #布尔值

参考文档:

[1] http://www.aosabook.org/en/selenium.html
[2] https://zhuanlan.zhihu.com/p/377124962
[3] https://www.selenium.dev/documentation/legacy/selenium_1/
[4] http://aosabook.org/en/selenium.html
[5] https://zhuanlan.zhihu.com/p/445477977
[6] https://www.bbsmax.com/A/GBJrQW7Zz0/
[7] https://www.w3.org/TR/webdriver/
[8] https://www.cnblogs.com/rowlingtech8/articles/15983394.html

顺便一提,欢迎加入软件测试交流Q群【209092584】。如果有任何问题,你可以在这里留言

Selenium Core 是一个用来测试 Web 应用的测试工具Selenium Core的测试直接运行在浏览器中,就像真实的用户在操作一样。它可以分别运行在 Windows,Linux 和 Macintosh 系统的 Internet Explorer,Mozilla 和 Firefox 浏览器中。 浏览器兼容性测试 测试你的应用看是否可以在不同的操作系统的不同浏览器上正常工作。同样的脚本可以运行在任何 Selenium 平台上。< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> 系统功能测试 创建回归测试用来检验应用的功能以及用户的满意度。 Selenium Core 使用了一个独特的机制让它可以运行在如此多的平台。测试脚本采用纯JavaScript或DHTML写成,你将 Selenium Core 的测试脚本直接放置到你的应用程序所在的 Web 服务器中,就可以在客户端使用任何受支持的浏览器运行测试了。 Selenium 使用 JavaScript 和 Iframe 自动化的测试引擎嵌入到你的浏览器中。这项技术应该可以工作在任何启用 JavaScript 的浏览器中。因为不同的浏览器处理 JavaScript 有些不同,所以我们通常不得不调整引擎以便更广泛的支持 Windows,Mac OS X 和 Linux 上的不同浏览器。 下面说下运行Selenium Core需要的环境: l 去Open QA下载最新的Selenium Core包selenium-core-< xmlnamespace prefix ="st1" ns ="urn:schemas-microsoft-com:office:smarttags" />0.8.2.zip l 把下载的selenium-core-0.8.2.zip解压到你的web服务器中,下面我将在Tomcat中演示。 安装步骤: 第一步:去apache.org下载tomcat安装包。 第二步:正确安装tomcat 第三步:去Open QA下载Selenium Core包 第四步:解压Selenium Core包到D:\selenium下 第五步:配置tomcat文件,配置一个sc.xml,其他配置项为<Context path="/sc" docBase="D:/selenium/selenium-core-0.8.2" debug="0" privileged="true"> 第六步:运行tomcat服务 第七步:打开浏览器,输入:http://localhost:8080/sc/ 这时你能看到下图界面: < xmlnamespace prefix ="v" ns ="urn:schemas-microsoft-com:vml" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件测试技术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值