基于Selenium和ChromeDriver的自动化页面性能测试
Posted 皖南笑笑生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于Selenium和ChromeDriver的自动化页面性能测试相关的知识,希望对你有一定的参考价值。
由于最近工作一直很紧张,拖了很久才在五一假期将Selenium实现自动化页面性能测试的代码实现部分补上,希望今后自己能更勤勉,多一些知识产出。
Selenium WebDriver(以下简称SW)提供了一套用于Web应用程序的自动化测试工具。SW按其应用场景不同可以分为(1)基于htmlUnit的无界面实现,并非驱动真实浏览器进行测试;(2)模拟真实输入,对多浏览器的支持和测试,包括FirefoxDriver、InternetExplorerDriver、OperaDriver和ChromeDriver;(3)对移动应用的测试,包括androidDriver和iPhoneDriver。
针对SW进行功能性测试的文章和书已经很多了,比如如何操作获取页面元素内容。而本文所要写的是如何基于Selenium和ChromeDriver做页面性能测试,比如获取页面请求的加载时间、获取页面的DOM元素加载完成时间等等。类似于一些成熟的拨测产品的实现原型(这也是笔者正在做的项目)。我想这是非常有意义的一次探索。
1. Maven依赖
首先,项目需要引入依赖的相关selenium包:selenium-api和selenium-java,要考虑不同版本和JDK版本的兼容性,笔者是JDK 1.8。
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-api -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>3.5.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.5.3</version>
</dependency>
2、ChromeDriver使用详解
本节内容参考https://sites.google.com/a/chromium.org/chromedriver/home,另外ChromeDriver的安装,笔者在《CentOS 7.x环境下搭建: Headless chrome + Selenium + ChromeDriver 实现自动化测试》中有详述。
2.1、DesiredCapabilities & ChromeOptions
Capabilities
属性可以定义和配置你的ChromeDriver会话,以满足对应功能和需求。
在Java实现中,类ChromeOptions
和类DesiredCapabilities
都可以用于具体定义Capabilities
。
比如以下代码,通过ChromeOptions
来定义Chrome的window-size属性:
// 设置chromedriver路径
System.setProperty("webdriver.chrome.driver","/opt/drivers/chromedriver");
ChromeOptions options = new ChromeOptions();
// 设置chrome启动时size大小
options.addArguments("--window-size=1980,1000");
// 根据ChromeOptions实例化ChromeDriver
WebDriver driver = new ChromeDriver(options);
try
// 打开苏宁易购
driver.get("https://www.suning.com");
catch (Exception e)
e.printStackTrace();
finally
// 关闭浏览器
driver.quit();
当然,以上例子也可以改写为通过DesiredCapabilities
来实现:
// 设置chromedriver路径
System.setProperty("webdriver.chrome.driver","/opt/drivers/chromedriver");
ChromeOptions options = new ChromeOptions();
// 设置chrome启动时size大小
options.addArguments("--window-size=1980,1000");
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, options);
// 根据DesiredCapabilities实例化ChromeDriver
WebDriver driver = new ChromeDriver(cap);
try
// 打开苏宁易购
driver.get("https://www.suning.com");
catch (Exception e)
e.printStackTrace();
finally
// 关闭浏览器
driver.quit();
2.2、Performance Log
ChromeDriver支持性能日志(Performance Log)数据的采集。想想看Chrome的F12控制台,我们能够采集到”Network”、Page”等,而这些是实现页面性能测试的基础。
Performance Log并非是默认开启的属性,所以我们可以通过上节说的DesiredCapabilities
在创建新会话的时候开启Performance Log。
而采集到的日志,我们可以通过LogEntry
对象输出到Console。具体代码实现如下:
package com.suning.webdrivertest.chromedemo;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import java.util.logging.Level;
/**
*
* Created by zhuyiquan90 on 2018/1/3.
*/
public class ChromeDriverDemo1
public static void main(String[] args)
// 设置chromedriver路径
System.setProperty("webdriver.chrome.driver", "/opt/drivers/chromedriver");
DesiredCapabilities cap = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
// 启用Performance Log日志采集
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
// 根据DesiredCapabilities实例化ChromeDriver
WebDriver driver = new ChromeDriver(cap);
try
// 打开苏宁易购
driver.get("https://www.suning.com");
for (LogEntry entry : driver.manage().logs().get(LogType.PERFORMANCE))
// 输出采集到的性能日志
System.out.println(Thread.currentThread().getName() + entry.toString());
catch (Exception e)
e.printStackTrace();
finally
// 关闭浏览器
driver.quit();
其输出结果如下:
Starting ChromeDriver 2.34.522932 (4140ab217e1ca1bec0c4b4d1b148f3361eb3a03e) on port 29777
Only local connections are allowed.
四月 30, 2018 3:06:27 下午 org.openqa.selenium.remote.ProtocolHandshake createSession
信息: Detected dialect: OSS
main[2018-04-30T15:06:27+0800] [INFO] "message":"method":"Page.frameAttached","params":"frameId":"49C70573CE1145CEB5B38A270213A48","parentFrameId":"28DAFE9FE90E9292F1B8EDB3315608EC","stack":"callFrames":["columnNumber":240,"functionName":"","lineNumber":0,"scriptId":"21","url":""],"webview":"28DAFE9FE90E9292F1B8EDB3315608EC"
main[2018-04-30T15:06:27+0800] [INFO] "message":"method":"Page.frameStartedLoading","params":"frameId":"49C70573CE1145CEB5B38A270213A48","webview":"28DAFE9FE90E9292F1B8EDB3315608EC"
main[2018-04-30T15:06:27+0800] [INFO] "message":"method":"Page.frameNavigated","params":"frame":"id":"49C70573CE1145CEB5B38A270213A48","loaderId":"EE699DC52C8ACA226069D24DC92E16","mimeType":"text/html","name":"chromedriver dummy frame","parentId":"28DAFE9FE90E9292F1B8EDB3315608EC","securityOrigin":"://","url":"about:blank","webview":"28DAFE9FE90E9292F1B8EDB3315608EC"
2.3、Chrome DevTools Protocol View
这一节,我们来讲讲Network和Page包含的内容,即针对上一节输出的内容,我们如何有效利用,通过它们来计算页面性能(参考Chrome DevTools Protocol)。
2.3.1、Network
Network中我们用到的事件主要是requestWillBeSent、responseReceived、loadingFailed和loadingFinished四种:
Network.requestWillBeSent
当页面即将发送HTTP请求时触发,其Json格式为:
"message":
"method": "Network.requestWillBeSent",
"params":
"documentURL": "about:blank",
"frameId": "C80F96297F4216E35079CFD86251AB8B",
"initiator":
"lineNumber": 0,
"type": "parser",
"url": "https://www.suning.com/"
,
"loaderId": "58DDB2CF16600EAE484A541DF9440089",
"redirectResponse":
"connectionId": 639,
"connectionReused": false,
"encodedDataLength": 497,
"fromDiskCache": false,
"fromServiceWorker": false,
"headers":
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Length": "0",
"Date": "Mon, 30 Apr 2018 07:06:42 GMT",
"Expires": "Thu, 01 Jan 1970 00:00:00 GMT",
"Location": "https://cm.g.doubleclick.net/pixel?google_nid=ipy&google_cm",
"P3P": "CP=\\"NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC\\"",
"Pragma": "no-cache",
"Server": "nginx/1.10.2",
"Set-Cookie": "CMBMP=IWl; Domain=.ipinyou.com; Expires=Thu, 10-May-2018 07:06:42 GMT; Path=/" ,
"headersText": "HTTP/1.1 302 Found\\r\\nServer: nginx/1.10.2\\r\\nDate: Mon, 30 Apr 2018 07:06:42 GMT\\r\\nContent-Length: 0\\r\\nConnection: keep-alive\\r\\nCache-Control: no-cache\\r\\nPragma: no-cache\\r\\nExpires: Thu, 01 Jan 1970 00:00:00 GMT\\r\\nP3P: CP=\\"NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC\\"\\r\\nSet-Cookie: CMBMP=IWl; Domain=.ipinyou.com; Expires=Thu, 10-May-2018 07:06:42 GMT; Path=/\\r\\nLocation: https://cm.g.doubleclick.net/pixel?google_nid=ipy&google_cm\\r\\n\\r\\n",
"mimeType": "",
"protocol": "http/1.1",
"remoteIPAddress": "127.0.0.1",
"remotePort": 1086,
"requestHeaders":
"Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Cookie": "sessionId=I4UF6b1WcgGMC; PYID=I4UF6b1Wcg99; CMTMS=p7Ik3Ve; CMSTMS=p7Ik3Ve; CMPUB=ADV-DefaultAdv; CMBMP=IW2",
"Host": "cm.ipinyou.com",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" ,
"requestHeadersText": "GET /baidu/cms.gif?baidu_error=1×tamp=1525072001 HTTP/1.1\\r\\nHost: cm.ipinyou.com\\r\\nConnection: keep-alive\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\\r\\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\\r\\nAccept-Encoding: gzip, deflate, br\\r\\nAccept-Language: zh-CN,zh;q=0.9\\r\\nCookie: sessionId=I4UF6b1WcgGMC; PYID=I4UF6b1Wcg99; CMTMS=p7Ik3Ve; CMSTMS=p7Ik3Ve; CMPUB=ADV-DefaultAdv; CMBMP=IW2\\r\\n",
"securityDetails":
"certificateId": 0,
"cipher": "AES_256_GCM",
"issuer": "RapidSSL SHA256 CA",
"keyExchange": "ECDHE_RSA",
"keyExchangeGroup": "P-256",
"protocol": "TLS 1.2",
"sanList": ["*.ipinyou.com", "ipinyou.com"],
"signedCertificateTimestampList": [ "hashAlgorithm": "SHA-256", "logDescription": "Symantec log", "logId": "DDEB1D2B7A0D4FA6208B81AD8168707E2E8E9D01D55C888D3D11C4CDB6ECBECC", "origin": "Embedded in certificate", "signatureAlgorithm": "ECDSA", "signatureData": "3045022024364934CBC90A8529E327E6EF853E3EF5E48B7F1598414E0F10059DC92685FC022100A74F93A8CF23D6572D7597C072368D69EC43AFB6A9EDAA4B01B43921AADEFDC2", "status": "Verified", "timestamp": 1511173770857.0 , "hashAlgorithm": "SHA-256", "logDescription": "Google 'Pilot' log", "logId": "A4B90990B418581487BB13A2CC67700A3C359804F91BDFB8E377CD0EC80DDC10", "origin": "Embedded in certificate", "signatureAlgorithm": "ECDSA", "signatureData": "3046022100F319D0F56F27C82228E2B01934A1C7F46915A1509F094EE91508F08C3B5AE2B2022100B0D94DD6FD00CB435EC33B916B52EC76FE5FFCC5D5BD8CB559248243AEDFE3CE", "status": "Verified", "timestamp": 1511173770923.0 ],
"subjectName": "*.ipinyou.com",
"validFrom": 1511136000,
"validTo": 1547942399 ,
"securityState": "secure",
"status": 302,
"statusText": "Found",
"timing":
"connectEnd": 772.852999994939,
"connectStart": 0.566999995498918,
"dnsEnd": -1,
"dnsStart": -1,
"proxyEnd": -1,
"proxyStart": -1,
"pushEnd": 0,
"pushStart": 0,
"receiveHeadersEnd": 1226.29800000141,
"requestTime": 42129.997749,
"sendEnd": 773.012999998173,
"sendStart": 772.960999995121,
"sslEnd": 772.844999999506,
"sslStart": 1.62599999748636,
"workerReady": -1,
"workerStart": -1 ,
"url": "https://cm.ipinyou.com/baidu/cms.gif?baidu_error=1×tamp=1525072001"
,
"request":
"headers":
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" ,
"initialPriority": "Low",
"method": "GET",
"mixedContentType": "none",
"referrerPolicy": "no-referrer-when-downgrade",
"url": "https://cm.g.doubleclick.net/pixel?google_nid=ipy&google_cm"
,
"requestId": "20524.247",
"timestamp": 42131.225431,
"type": "Image",
"wallTime": 1525072000.35906
,
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC"
参数说明:
参数 | 类型 | 说明 |
---|---|---|
requestId | String | 唯一请求ID |
loaderId | String | 加载ID |
documentURL | String | 页面文档URL |
request | Request | 请求数据对象 |
timestamp | float | 以过去某个任意时间点为基点,从打开页面开始,以秒为单位单调递增的时间戳 |
wallTime | float | UTC时间 |
initiator | Initiator | 请求初始化对象 |
redirectResponse | Response | 重定向响应对象 |
type | String | 资源类型 |
frameId | String | FrameID |
hasUserGesture | boolean | Whether the request is initiated by a user gesture. Defaults to false. |
其中,
Request对象:
参数 | 类型 | 说明 |
---|---|---|
url | String | 请求url |
method | String | HTTP请求类型 |
headers | Object | 请求头信息 |
postData | String | Post请求数据 |
hasPostData | boolean | 如果是Post请求,则为true |
mixedContentType | String | 是否存在混淆内容问题:blockable, optionally-blockable, none. |
initialPriority | String | 资源加载优先级:VeryLow, Low, Medium, High, VeryHigh. |
referrerPolicy | String | 跨域策略:no-referrer-when-downgrade, no-referrer, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin |
isLinkPreload | boolean | 是否通过预加载方式加载 |
Response对象:
参数 | 类型 | 说明 |
---|---|---|
url | String | 请求url |
status | int | 响应状态码 |
statusText | String | 状态码内容 |
headers | Object | 响应头部,json格式 |
headersText | String | 响应头部,文本格式 |
mimeType | String | Resource mimeType |
requestHeaders | Obeject | 请求头部,json格式 |
requestHeadersText | String | 请求头部,文本格式 |
connectionReused | boolean | 连接是否被复用 |
connectionId | long | 物理连接ID |
remoteIPAddress | String | Remote IP address |
remotePort | int | Remote port |
fromDiskCache | boolean | 是否直接从浏览器缓存获取资源 |
fromServiceWorker | boolean | Specifies that the request was served from the ServiceWorker |
encodedDataLength | long | 响应字节数 |
timing | ResourceTiming | ResourceTiming对象 |
protocol | String | 协议 |
securityState | String | Security state of the request resource:unknown, neutral, insecure, secure, info |
securityDetails | SecurityDetails | Security details for the request |
ResourceTiming对象:
参数 | 类型 | 说明 |
---|---|---|
requestTime | float | 时间基线 |
proxyStart | float | Started resolving proxy. |
proxyEnd | float | Finished resolving proxy. |
dnsStart | float | Started DNS address resolve. |
dnsEnd | float | Finished DNS address resolve. |
connectStart | float | Started connecting to the remote host. |
connectEnd | float | Connected to the remote host. |
sslStart | float | Started SSL handshake. |
sslEnd | float | Finished SSL handshake. |
workerStart | float | Started running ServiceWorker. |
workerReady | float | Finished Starting ServiceWorker. |
sendStart | float | Started sending request. |
sendEnd | float | Finished sending request. |
pushStart | float | Time the server started pushing request. |
pushEnd | float | Time the server finished pushing request. |
receiveHeadersEnd | float | Finished receiving response headers. |
Network.responseReceived
当HTTP响应可用时触发,其Json格式为:
"message":
"method": "Network.responseReceived",
"params":
"frameId": "28DAFE9FE90E9292F1B8EDB3315608EC",
"loaderId": "44DBCD0BEBFCEE5AED6388366BCB719B",
"requestId": "20524.277",
"response":
"connectionId": 468,
"connectionReused": true,
"encodedDataLength": 439,
"fromDiskCache": false,
"fromServiceWorker": false,
"headers":
"Cache-Control": "no-cache, max-age=0, must-revalidate",
"Connection": "keep-alive",
"Content-Length": "43",
"Content-Type": "image/gif",
"Date": "Mon, 30 Apr 2018 07:06:42 GMT",
"Expires": "Fri, 01 Jan 1980 00:00:00 GMT",
"Last-Modified": "Mon, 28 Sep 1970 06:00:00 GMT",
"Pragma": "no-cache",
"Server": "nginx/1.6.3",
"X-Dscp-Value": "0",
"X-Via": "1.1 dxun38:1 (Cdn Cache Server V2.0), 1.1 shb115:4 (Cdn Cache Server V2.0), 1.1 ls10:0 (Cdn Cache Server V2.0)" ,
"headersText": "HTTP/1.1 200 OK\\r\\nDate: Mon, 30 Apr 2018 07:06:42 GMT\\r\\nServer: nginx/1.6.3\\r\\nContent-Type: image/gif\\r\\nContent-Length: 43\\r\\nLast-Modified: Mon, 28 Sep 1970 06:00:00 GMT\\r\\nExpires: Fri, 01 Jan 1980 00:00:00 GMT\\r\\nPragma: no-cache\\r\\nCache-Control: no-cache, max-age=0, must-revalidate\\r\\nX-Dscp-Value: 0\\r\\nX-Via: 1.1 dxun38:1 (Cdn Cache Server V2.0), 1.1 shb115:4 (Cdn Cache Server V2.0), 1.1 ls10:0 (Cdn Cache Server V2.0)\\r\\nConnection: keep-alive\\r\\n\\r\\n",
"mimeType": "image/gif",
"protocol": "http/1.1",
"remoteIPAddress": "127.0.0.1",
"remotePort": 1086,
"requestHeaders":
"Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "keep-alive",
"Cookie": "_snstyxuid=ADFD3F4299718846; _snvd=152507199416958111",
"Host": "sa.suning.cn",
"Referer": "https://www.suning.com/",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" ,
"requestHeadersText": "GET /ajaxSiteExpro.gif?oId=152507199969277498&pvId=152507199147454663&expoInfo=index3_homepage1_32618013033_word03,index3_homepage1_32618013033_word04,index3_homepage1_newUser_tankuang&expoType=1&pageUrl=https://www.suning.com/&visitorId=&loginUserName=&memberID=-&sessionId=&pageType=web&hidUrlPattern=&iId=log_1525071999692 HTTP/1.1\\r\\nHost: sa.suning.cn\\r\\nConnection: keep-alive\\r\\nUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\\r\\nAccept: image/webp,image/apng,image/*,*/*;q=0.8\\r\\nReferer: https://www.suning.com/\\r\\nAccept-Encoding: gzip, deflate, br\\r\\nAccept-Language: zh-CN,zh;q=0.9\\r\\nCookie: _snstyxuid=ADFD3F4299718846; _snvd=152507199416958111\\r\\n",
"securityDetails":
"certificateId": 0,
"cipher": "AES_256_GCM",
"issuer": "WoSign OV SSL CA",
"keyExchange": "ECDHE_RSA",
"keyExchangeGroup": "P-256",
"protocol": "TLS 1.2",
"sanList": ["*.suning.cn", "suning.cn"],
"signedCertificateTimestampList": [],
"subjectName": "*.suning.cn",
"validFrom": 1479721356,
"validTo": 1574329356 ,
"securityState": "secure",
"status": 200,
"statusText": "OK",
"timing":
"connectEnd": -1,
"connectStart": -1,
"dnsEnd": -1,
"dnsStart": -1,
"proxyEnd": -1,
"proxyStart": -1,
"pushEnd": 0,
"pushStart": 0,
"receiveHeadersEnd": 656.157999997959,
"requestTime": 42130.56839,
"sendEnd": 1.03800000215415,
"sendStart": 0.979999997070991,
"sslEnd": -1,
"sslStart": -1,
"workerReady": -1,
"workerStart": -1 ,
"url": "https://sa.suning.cn/ajaxSiteExpro.gif?oId=152507199969277498&pvId=152507199147454663&expoInfo=index3_homepage1_32618013033_word03,index3_homepage1_32618013033_word04,index3_homepage1_newUser_tankuang&expoType=1&pageUrl=https://www.suning.com/&visitorId=&loginUserName=&memberID=-&sessionId=&pageType=web&hidUrlPattern=&iId=log_1525071999692"
,
"timestamp": 42131.22618,
"type": "Image"
,
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC"
参数说明:
参数 | 类型 | 说明 |
---|---|---|
requestId | String | 唯一请求ID |
timestamp | float | 以过去某个任意时间点为基点,从打开页面开始,以秒为单位单调递增的时间戳 |
type | String | 资源类型 |
response | Response | 响应对象 |
frameId | String | FrameID |
应用场景:根据Response可以快速识别请求的各种异常状态码(5XX、4XX),以及时间的分布。
Network.loadingFailed
当HTTP请求无法加载时触发,其Json格式为:
"message":
"method": "Network.loadingFailed",
"params":
"canceled": true,
"errorText": "net::ERR_ABORTED",
"requestId": "20524.271",
"timestamp": 42130.877864,
"type": "Image"
,
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC"
参数说明:
参数 | 类型 | 说明 |
---|---|---|
requestId | String | 唯一请求ID |
loaderId | String | 加载ID |
timestamp | float | 以过去某个任意时间点为基点,从打开页面开始,以秒为单位单调递增的时间戳 |
type | String | 资源类型 |
errorText | String | 错误原因提示 |
canceled | boolean | 如果请求加载被取消,则为true |
blockedReason | String | 请求被阻塞的原因 |
应用场景:我们可以通过loadingFailed和requestWillBeSent确定哪些请求加载失败。
Network.loadingFinished
当HTTP请求完成加载时触发,其Json格式为:
"message":
"method": "Network.loadingFinished",
"params":
"blockedCrossSiteDocument": false,
"encodedDataLength": 327,
"requestId": "20524.262",
"timestamp": 42130.87542
,
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC"
参数说明:
参数 | 类型 | 说明 |
---|---|---|
requestId | String | 唯一请求ID |
timestamp | float | 以过去某个任意时间点为基点,从打开页面开始,以秒为单位单调递增的时间戳 |
encodedDataLength | long | 响应字节数 |
blockedCrossSiteDocument | boolean | 如果由于跨域阻塞了响应,则为true |
应用场景:根据encodedDataLength,计算响应的最终大小。
针对requestWillBeSent、responseReceived、loadingFailed和loadingFinished四种对象,Java构建Model如下所示:
2.3.2、Page
Page中我们用到的事件主要是domContentEventFired和loadEventFired两种:
Page.domContentEventFired
页面Dom内容加载完成时间。
"message":
"method": "Page.domContentEventFired",
"params":
"timestamp": 42124.003701
,
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC"
Page.loadEventFired
页面加载完成时间。
"message":
"method": "Page.loadEventFired",
"params":
"timestamp": 42133.108263
,
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC"
以上,我们可以根据ChromeDriver来完成对页面加载性能分析的自动化测试了。
3、持久化ChromeDriverService的使用
本节介绍ChromeDriverService
,这完全是出于提高测试性能的考虑。我们知道每次创建一个ChromeDriver,完成测试以后再释放掉这个对象,等下次来了一个新的测试,仍要再新建一个对象,如此反复。这相当于每次都打开浏览器,再关闭浏览器,再打开浏览器。这种实现方式并不利于高并发的测试场景。
我们希望如Java的池化设计思想一样,初始化生成多个持久化的浏览器对象,后面每次测试都用这些浏览器对象进行,这样会极大提升测试性能(想想看,避免了往复创建和关闭进程的过程啊!)。因此引入ChromeDriverService
,ChromeDriverService
是一个管理ChromeDriver serve
以上是关于基于Selenium和ChromeDriver的自动化页面性能测试的主要内容,如果未能解决你的问题,请参考以下文章
使用Postman或requests结合chromedriver模拟Selenium操作浏览器
ubuntu下安装selenium和安装chromedriver
selenium 中的 ChromeDriver 和 WebDriver 有啥区别?