Всем привет, мы снова встретились, я ваш друг Цюаньчжаньцзюнь.
Потому что работа в последнее время была очень напряженной,На первомайские праздники пришлось долго откладывать это дело.SeleniumВнедрить автоматизированные страницыпроизводительностьтестДобавлена часть реализации кода,Надеюсь, в будущем я смогу быть более прилежным,Больше производства знаний。 Selenium WebDriver (далее — ПО) предоставляет набор инструментов автоматического тестирования веб-приложений. Программное обеспечение можно разделить на различные сценарии применения в соответствии со сценариями его применения: (1) реализация без интерфейса на основе HtmlUnit, которая не использует для тестирования реальные браузеры (2) имитирует реальный ввод, поддерживает и тестирует несколько браузеров, включая FirefoxDriver; InternetExplorerDriver, OperaDriver и ChromeDriver (3) Тестирование мобильных приложений, включая AndroidDriver и iPhoneDriver; Уже существует множество статей и книг по функциональному проектированию ПО.,Например, как получить содержимое элемента страницы。В этой статье речь пойдет о том, как на основеSeleniumиChromeDriverСоздать страницупроизводительностьтест,Например, получите время загрузки запроса страницы, получите время завершения загрузки элемента DOM страницы и т. д. Он похож на прототипы реализации некоторых зрелых продуктов для дозвона (это тоже проект, над которым работает автор). Я думаю, что это очень значимое исследование.
Прежде всего, в проекте необходимо ввести зависимые пакеты селена: 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>
Ссылка на этот разделhttps://sites.google.com/a/chromium.org/chromedriver/home,Кроме того, установка ChromeDriver,Автор находится в《CentOS Сборка в среде 7.x: Headless chrome + Selenium + ChromeDriver выполнить Автоматизация》Подробно в。
Capabilities
Свойства могут быть определеныинастроить свойChromeDriverсессия,для выполнения соответствующих функцийинуждаться。
существоватьJavaвыполнитьсередина,добрыйChromeOptions
идобрыйDesiredCapabilities
может использоваться для конкретных определенийCapabilities
。
Например, следующий код,проходитьChromeOptions
определитьChromeизwindow-sizeсвойство:
// Установить путь к хромдрайверу
System.setProperty("webdriver.chrome.driver","/opt/drivers/chromedriver");
ChromeOptions options = new ChromeOptions();
// Установить размер при запуске Chrome
options.addArguments("--window-size=1980,1000");
// Создать экземпляр ChromeDriver на основе ChromeOptions
WebDriver driver = new ChromeDriver(options);
try {
// Открыть Suning.com
driver.get("https://www.suning.com");
} catch (Exception e) {
e.printStackTrace();
} finally {
// Закрыть браузер
driver.quit();
}
конечно,Приведенный выше пример также можно переписать какпроходитьDesiredCapabilities
Приходитьвыполнить:
// Установить путь к хромдрайверу
System.setProperty("webdriver.chrome.driver","/opt/drivers/chromedriver");
ChromeOptions options = new ChromeOptions();
// Установить размер при запуске Chrome
options.addArguments("--window-size=1980,1000");
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY, options);
// Создание экземпляра ChromeDriver на основе желаемых возможностей
WebDriver driver = new ChromeDriver(cap);
try {
// Открыть Suning.com
driver.get("https://www.suning.com");
} catch (Exception e) {
e.printStackTrace();
} finally {
// Закрыть браузер
driver.quit();
}
ChromeDriver поддерживает журналы производительности (Производительность Журнал) сбор данных. Подумайте о консоли Chrome F12. Мы можем собрать «Сеть», «Страница» и т. д., и это основа для тестирования производительности страницы.
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) {
// Установить путь к хромдрайверу
System.setProperty("webdriver.chrome.driver", "/opt/drivers/chromedriver");
DesiredCapabilities cap = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
// Включить производительность Сбор журналов
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
// Создание экземпляра ChromeDriver на основе желаемых возможностей
WebDriver driver = new ChromeDriver(cap);
try {
// Открыть Suning.com
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"}
этот раздел,Давайте поговорим об этомNetworkиPageВключатьизсодержание,То есть для вывода контента в предыдущем разделе,Как мы можем эффективно использовать,проходить它们Приходить计算页面производительность(ссылкаChrome DevTools Protocol)。
Основными событиями, которые мы используем в Network, являются requestWillBeSent, responseReceived, loadingFailed и loadingFinished:
Срабатывает, когда страница собирается отправить 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 | Уникальный идентификатор запроса |
loaderId | String | Идентификатор загрузки |
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 | Данные запроса публикации |
hasPostData | boolean | True, если это запрос на публикацию |
mixedContentType | String | Есть ли проблема с запутанным контентом: блокируемый, опционально блокируемый, нет. |
initialPriority | String | Приоритет загрузки ресурсов: VeryLow, Low, Medium, High, VeryHigh. |
referrerPolicy | String | Междоменная политика: без реферера при переходе на более раннюю версию, без реферера, происхождение, происхождение при перекрестном происхождении, одно и то же происхождение, строгое происхождение, строгое происхождение при перекрестном происхождении |
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 | Идентификатор физического соединения |
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 | Ресурс Тиминг Обжект |
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. |
Запускается, когда доступен 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 | Уникальный идентификатор запроса |
timestamp | float | В качестве базовой точки принимается произвольный момент времени в прошлом, временная метка, которая монотонно увеличивается в секундах с момента открытия страницы. |
type | String | Тип ресурсов |
response | Response | объект ответа |
frameId | String | FrameID |
Сценарии применения:в соответствии сResponseМожет быстро идентифицировать запросыиз Различные коды состояния исключений(5XX、4XX),и распределение времени.
Срабатывает, когда 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 | Уникальный идентификатор запроса |
loaderId | String | Идентификатор загрузки |
timestamp | float | В качестве базовой точки принимается произвольный момент времени в прошлом, временная метка, которая монотонно увеличивается в секундах с момента открытия страницы. |
type | String | Тип ресурсов |
errorText | String | Подскажите причину ошибки |
canceled | boolean | Истинно, если запрошенная загрузка была отменена |
blockedReason | String | Причина, по которой запрос заблокирован |
Сценарии применения:мы можемпроходитьloadingFailedиrequestWillBeSentОпределите, какие запросы не удалось загрузить。
Срабатывает, когда HTTP-запрос завершает загрузку, его формат Json:
{
"message": { "method": "Network.loadingFinished", "params": { "blockedCrossSiteDocument": false, "encodedDataLength": 327, "requestId": "20524.262", "timestamp": 42130.87542 } },
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC" }
Описание параметра:
параметр | тип | иллюстрировать |
---|---|---|
requestId | String | Уникальный идентификатор запроса |
timestamp | float | В качестве базовой точки принимается произвольный момент времени в прошлом, временная метка, которая монотонно увеличивается в секундах с момента открытия страницы. |
encodedDataLength | long | Байты ответа |
blockedCrossSiteDocument | boolean | Истинно, если ответ заблокирован из-за перекрестного происхождения |
Сценарии применения:в соответствии сencodedDataLength,Рассчитайте окончательный размер ответа.
Для четырех объектов requestWillBeSent, responseReceived, loadingFailed и loadingFinished модель построения Java выглядит следующим образом:
События, которые мы используем в Page, в основном — это domContentEventFired и loadEventFired:
Время завершения загрузки содержимого страницы.
{
"message": { "method": "Page.domContentEventFired", "params": { "timestamp": 42124.003701 } },
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC" }
Время завершения загрузки страницы.
{
"message": { "method": "Page.loadEventFired", "params": { "timestamp": 42133.108263 } },
"webview": "28DAFE9FE90E9292F1B8EDB3315608EC" }
Выше мы можем завершить автоматическое тестирование анализа производительности загрузки страниц на основе ChromeDriver.
Введение в этот разделChromeDriverService
,Это сделано исключительно ради улучшения вашей производительности. Мы знаем, что каждый раз, когда создается ChromeDriver,Освободите этот объект после завершения теста,Подожди, пока в следующий раз не придет новый,Все еще хочу создать новый объект,Неоднократно. Это эквивалентно открытию браузера каждый раз.,Снова Закрыть браузер,Откройте браузер еще раз. Этот метод реализации не подходит для сценариев с высоким уровнем параллелизма.
Мы надеемся, что у нас будет та же идея, что и в конструкции пула Java.,Инициализация генерирует несколько постоянных объектов браузера.,Каждый последующий тест будет выполняться с использованием этих объектов браузера.,Это значительно улучшит тестпроизводительность (подумайте об этом,Избегайте повторного созданияизакрыть процессиз Процесс!)。Поэтому введеныChromeDriverService
,ChromeDriverService
это менеджментChromeDriver Пример персистентности сервера:
The purpose of ChromeDriverService is to manage a persistent instance of the ChromeDriver server. Standard practice is to use the ChromeDriver class or the Selenium standalone server to obtain Chrome driver instances, but this practice sacrifices performance for convenience. In this scenario, each driver instance is associated with its own instance of the ChromeDriver server, which gets launched when the driver is requested and terminated when the driver exits. This per-instance server management adds overhead to test execution, both in terms of run-time and resource utilization. Using ChromeDriverService, this overhead can be reduced to a minimum by enabling your test framework to launch a server instance at the start of the test suite and shut it down when the suite finishes. An example of this approach can be found on the ChromeDriver Getting started page under the heading Controlling ChromeDriver’s lifetime.
Его использование можетссылка:Java Code Examples for org.openqa.selenium.chrome.ChromeDriverService。 Ниже приведена реализованная мной демонстрация. Я создал три потока, каждый из которых содержит объект ChromeDrvierService, что эквивалентно каждому потоку, управляющему процессом браузера. Блокирующая очередь BQ используется для реализации модели производитель-потребитель. Когда в очереди есть задача, она будет назначена потоку для тестирования. ChromeDrvierService не будет уничтожен, если в очереди нет задач. Глубину очереди блокировки и размер пула потоков можно динамически регулировать в зависимости от производительности сервера.
package com.suning.webdrivertest.chromedemo;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
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.io.File;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
/** * Created by zhuyiquan90 on 2018/1/9. */
public class ChromeDriverDemo2 {
// Длина очереди блокировки
private static final int BLOCK_QUEUE_SIZE = 100;
// Количество потоков драйвера браузера
private static final int THREAD_SIZE = 3;
// адрес хромдрайвера
private static final String chromedriverPath = "opt/drivers/chromedriver";
private static final BlockingQueue<String> reqQuene = new ArrayBlockingQueue<String>(BLOCK_QUEUE_SIZE);
static class DriverRunnable implements Runnable {
private WebDriver driver;
CountDownLatch latch;
public DriverRunnable(CountDownLatch latch) {
ChromeDriverService chromeDriverService = new ChromeDriverService.Builder()
.usingDriverExecutable(new File(chromedriverPath))
.usingAnyFreePort()
.build();
DesiredCapabilities cap = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
driver = new ChromeDriver(chromeDriverService, cap);
this.latch = latch;
}
public void run() {
while (true) {
try {
driver.get(reqQuene.take());
for (LogEntry entry : driver.manage().logs().get(LogType.PERFORMANCE)) {
System.out.println(Thread.currentThread().getName() + entry.toString());
}
latch.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < THREAD_SIZE; i++) {
Thread driverThread = new Thread(new DriverRunnable(latch), "driverThread" + i);
driverThread.start();
}
for (int i = 0; i < 10; i++) {
reqQuene.put("https://www.suning.com");
}
// Цель использования latch.await() — сделать последовательность вывода демо-версии интуитивно понятной и не имеет никакого другого эффекта.
// Вы можете снять защелку
latch.await();
}
}
Ниже приводится последняя часть этой статьи. Я хочу закончить ее относительно полным примером приложения. Этот пример взят из реального сценария приложения. Требуется собрать следующие данные для каждой страницы: Над сгибомпроизводительность,включать:
以及全页面производительность,То есть после открытия страницы вы завершите просмотр всей страницы.,включать:
Окончательная реализация выглядит следующим образом:
package com.suning.webdrivertest.chrome;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.suning.webdrivertest.networkdto.NetworkLoadingFailedDTO;
import com.suning.webdrivertest.networkdto.NetworkLoadingFinishedDTO;
import com.suning.webdrivertest.networkdto.NetworkRequestWillBeSentDTO;
import com.suning.webdrivertest.networkdto.NetworkResponseReceivedDTO;
import com.suning.webdrivertest.performancedto.*;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
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.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
/** * Created by zhuyiquan90 on 2018/1/10. */
public class ChromeTest {
// Длина очереди блокировки
private static final int BLOCK_QUEUE_SIZE = 100;
// Количество потоков драйвера браузера
private static final int THREAD_SIZE = 1;
// Fired when page is about to send HTTP request.
public static final String NETWORK_REQUEST_WILL_BE_SENT = "Network.requestWillBeSent";
// Fired when HTTP response is available.
public static final String NETWORK_RESPONSE_RECEIVED = "Network.responseReceived";
// Fired when HTTP request has finished loading.
public static final String NETWORK_LOADING_FAILED = "Network.loadingFailed";
// Fired when HTTP request has failed to load.
public static final String NETWORK_LOADING_FINISHED = "Network.loadingFinished";
// DOM Length JS
public static final String JS_DOM_LENGTH = "return document.getElementsByTagName('*').length";
// ScrollingTop JS
public static final String JS_SCROLLINGTOP = "return $(window).scrollTop( {0} * 1000)";
// Scrolling Y JS
public static final String JS_SCROLLINGY = "return window.scrollY";
// Performance Timing JS
public static final String JS_PERFORMANCE_TIMING = "return performance.timing";
private static final BlockingQueue<String> reqQuene = new ArrayBlockingQueue<String>(BLOCK_QUEUE_SIZE);
static class DriverRunnable implements Runnable {
private WebDriver driver;
public DriverRunnable() {
System.setProperty(ChromeDriverService.CHROME_DRIVER_LOG_PROPERTY,
System.getProperty("user.dir") + "/target/chromedriver.log");
System.setProperty(ChromeDriverService.CHROME_DRIVER_EXE_PROPERTY,
System.getProperty("user.dir") + "/drivers/chromedriver");
ChromeDriverService chromeDriverService = new ChromeDriverService.Builder()
.withVerbose(true)
.usingAnyFreePort()
.build();
ChromeOptions options = new ChromeOptions();
// options.addArguments("--headless");
options.addArguments("--window-size=1980,1000");
options.addArguments("--disable-web-security");
// options.addArguments("--start-fullscreen");
// options.addArguments("--screenshot");
// options.addArguments("--golden-screenshots-dir=" + chromedriverPath);
DesiredCapabilities cap = DesiredCapabilities.chrome();
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
cap.setCapability(CapabilityType.LOGGING_PREFS, logPrefs);
cap.setCapability(ChromeOptions.CAPABILITY, options);
driver = new ChromeDriver(chromeDriverService, cap);
}
public void run() {
while (true) {
try {
String url = reqQuene.take();
TotalPerformanceDTO totalPerformance = new TotalPerformanceDTO();
totalPerformance.setFirstScreenPerformance(
detectFirstScreenPerformance(url, driver));
totalPerformance.setFullPagePerformance(
detectFullPagePerformance(url, driver));
System.out.println(totalPerformance.toString());
// Сдвинуть страницу в самый низ страницы
// long scrollStart = 0, scrollEnd = 1;
// int i = 1;
// while (scrollStart != scrollEnd) {
// scrollStart = (Long) js.executeScript("return window.scrollY");
// String scrollTo = "return $(window).scrollTop(" + i++ + " * 1000)";
// js.executeScript(scrollTo);
// Thread.sleep(200);
// scrollEnd = (Long) js.executeScript("return window.scrollY");
// System.out.println(scrollTo + ":" + scrollEnd);
// }
// System.out.println(Thread.currentThread().getName() + ": " +
// js.executeScript("return document.getElementsByTagName('*').length"));
// for (LogEntry entry : driver.manage().logs().get(LogType.PERFORMANCE)) {
// System.out.println(Thread.currentThread().getName() + entry.getMessage());
// }
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/** * Статистика первого экрана * * @param url * @param driver * @return */
private static FirstScreenPerformanceDTO detectFirstScreenPerformance(String url, WebDriver driver) {
driver.get(url);
// объект операции js
JavascriptExecutor js = (JavascriptExecutor) driver;
FirstScreenPerformanceDTO firstScreenPerformance = new FirstScreenPerformanceDTO();
List<NetworkRequestWillBeSentDTO> firstscreenRequestList =
new ArrayList<NetworkRequestWillBeSentDTO>();
List<NetworkResponseReceivedDTO> firstscreenResponseList =
new ArrayList<NetworkResponseReceivedDTO>();
List<NetworkLoadingFailedDTO> firstscreenFailList =
new ArrayList<NetworkLoadingFailedDTO>();
List<NetworkLoadingFinishedDTO> firstscreenFinishedList =
new ArrayList<NetworkLoadingFinishedDTO>();
int pageRequestNum = 0;
double pageSize = 0.0;
for (LogEntry entry : driver.manage().logs().get(LogType.PERFORMANCE)) {
JSONObject jsonObj = JSON.parseObject(entry.getMessage()).getJSONObject("message");
String method = jsonObj.getString("method");
String params = jsonObj.getString("params");
if (method.equals(NETWORK_REQUEST_WILL_BE_SENT)) {
NetworkRequestWillBeSentDTO request = JSON.parseObject(
params, NetworkRequestWillBeSentDTO.class);
pageRequestNum++;
// System.out.println(method + ":" + request.toString());
firstscreenRequestList.add(request);
} else if (method.equals(NETWORK_RESPONSE_RECEIVED)) {
NetworkResponseReceivedDTO response = JSON.parseObject(
params, NetworkResponseReceivedDTO.class);
// System.out.println(method + ":" + response.getResponse().getUrl());
firstscreenResponseList.add(response);
} else if (method.equals(NETWORK_LOADING_FINISHED)) {
NetworkLoadingFinishedDTO finished = JSON.parseObject(
params, NetworkLoadingFinishedDTO.class);
pageSize += finished.getEncodedDataLength();
// System.out.println(method + ":" + finished.toString());
firstscreenFinishedList.add(finished);
} else if (method.equals(NETWORK_LOADING_FAILED)) {
NetworkLoadingFailedDTO failed = JSON.parseObject(
params, NetworkLoadingFailedDTO.class);
// System.out.println(method + ":" + failed.toString());
firstscreenFailList.add(failed);
}
}
// Получите номер DOM первого экрана
firstScreenPerformance.setPageDomNum(executeDomLengthJS(js));
// получать Время завершения загрузки DOM первого экрана и Время завершения полной загрузки первого экрана
PerformanceTimingDTO performanceTiming = executePerformanceTimingJS(js);
firstScreenPerformance.setDomContentLoadedCost(
performanceTiming.getDomContentLoadedEventEnd() - performanceTiming.getConnectStart());
firstScreenPerformance.setLoadEventCost(
performanceTiming.getLoadEventEnd() - performanceTiming.getConnectStart());
// получать Размер выше сгиба
firstScreenPerformance.setPageSize(pageSize / (1000 * 1000));
// получать Количество запросов первого экрана
firstScreenPerformance.setPageRequestNum(pageRequestNum);
System.out.println("страница" + url + ":Количество запросов первого экрана:"
+ firstScreenPerformance.getPageRequestNum() + ", Размер выше сгиба:"
+ firstScreenPerformance.getPageSize() + "MB, Общее количество DOM на первом экране:"
+ firstScreenPerformance.getPageDomNum() + ", Время завершения загрузки DOM первого экрана:"
+ firstScreenPerformance.getDomContentLoadedCost() + "ms, Время завершения полной загрузки первого экрана:"
+ firstScreenPerformance.getLoadEventCost() + "ms");
// Анализируйте ненормальные реакции
PageErrorsDTO pageErrorsDTO = new PageErrorsDTO();
pageErrorsDTO.setCodeErrorResponseList(
analysisCodeErrorResponse(firstscreenResponseList));
if (!pageErrorsDTO.getCodeErrorResponseList().isEmpty()) {
System.out.println("Ненормальный ответ первого экрана:");
for (int i = 0; i < pageErrorsDTO.getCodeErrorResponseList().size(); i++) {
System.out.println(pageErrorsDTO.
getCodeErrorResponseList().get(i).getUrl() + ": " + pageErrorsDTO.
getCodeErrorResponseList().get(i).getStatus());
}
}
// Анализ реакции на отказ
pageErrorsDTO.setFailResponseList(
analysisFailResponse(firstscreenFailList, firstscreenRequestList));
if (!pageErrorsDTO.getFailResponseList().isEmpty()) {
System.out.println("Не удалось ответить на первый экран:");
for (int i = 0; i < pageErrorsDTO.getFailResponseList().size(); i++) {
System.out.println(pageErrorsDTO.
getFailResponseList().get(i).getUrl() + ": " + pageErrorsDTO.
getFailResponseList().get(i).getErrorText() + " " + pageErrorsDTO.
getFailResponseList().get(i).getBlockedReason());
}
}
// Анализируйте медленные ответы
pageErrorsDTO.setSlowReponseList(
analysisSlowResponse(firstscreenRequestList, firstscreenFinishedList, 3.0));
if (!pageErrorsDTO.getSlowReponseList().isEmpty()) {
System.out.println("Медленный ответ на первом экране:");
for (int i = 0; i < pageErrorsDTO.getSlowReponseList().size(); i++) {
System.out.println(pageErrorsDTO.
getSlowReponseList().get(i).getUrl() + ": " + pageErrorsDTO.
getSlowReponseList().get(i).getCost());
}
}
firstScreenPerformance.setPageErrorsDTO(pageErrorsDTO);
return firstScreenPerformance;
}
/** * Полная статистика страницы * * @param url * @param driver * @return */
private static FullPagePerformanceDTO detectFullPagePerformance(String url, WebDriver driver) {
driver.get(url);
// объект операции js
JavascriptExecutor js = (JavascriptExecutor) driver;
FullPagePerformanceDTO fullPagePerformance = new FullPagePerformanceDTO();
// Прокрутите страницу вниз
scrollToBottom(js);
List<NetworkRequestWillBeSentDTO> fullPageRequestList =
new ArrayList<NetworkRequestWillBeSentDTO>();
List<NetworkResponseReceivedDTO> fullPageResponseList =
new ArrayList<NetworkResponseReceivedDTO>();
List<NetworkLoadingFailedDTO> fullPageFailList =
new ArrayList<NetworkLoadingFailedDTO>();
List<NetworkLoadingFinishedDTO> fullPageFinishedList =
new ArrayList<NetworkLoadingFinishedDTO>();
int pageRequestNum = 0;
double pageSize = 0.0;
for (LogEntry entry : driver.manage().logs().get(LogType.PERFORMANCE)) {
JSONObject jsonObj = JSON.parseObject(entry.getMessage()).getJSONObject("message");
String method = jsonObj.getString("method");
String params = jsonObj.getString("params");
if (method.equals(NETWORK_REQUEST_WILL_BE_SENT)) {
NetworkRequestWillBeSentDTO request = JSON.parseObject(
params, NetworkRequestWillBeSentDTO.class);
pageRequestNum++;
// System.out.println(method + ":" + request.toString());
fullPageRequestList.add(request);
} else if (method.equals(NETWORK_RESPONSE_RECEIVED)) {
NetworkResponseReceivedDTO response = JSON.parseObject(
params, NetworkResponseReceivedDTO.class);
// System.out.println(method + ":" + response.getResponse().getUrl());
fullPageResponseList.add(response);
} else if (method.equals(NETWORK_LOADING_FINISHED)) {
NetworkLoadingFinishedDTO finished = JSON.parseObject(
params, NetworkLoadingFinishedDTO.class);
pageSize += finished.getEncodedDataLength();
// System.out.println(method + ":" + finished.toString());
fullPageFinishedList.add(finished);
} else if (method.equals(NETWORK_LOADING_FAILED)) {
NetworkLoadingFailedDTO failed = JSON.parseObject(
params, NetworkLoadingFailedDTO.class);
// System.out.println(method + ":" + failed.toString());
fullPageFailList.add(failed);
}
}
// Получить номер DOM полной страницы
fullPagePerformance.setPageDomNum(executeDomLengthJS(js));
// получать Время завершения загрузки полной страницы DOM и Время завершения полной загрузки первого экрана
PerformanceTimingDTO performanceTiming = executePerformanceTimingJS(js);
fullPagePerformance.setDomContentLoadedCost(
performanceTiming.getDomContentLoadedEventEnd() - performanceTiming.getConnectStart());
fullPagePerformance.setLoadEventCost(
performanceTiming.getLoadEventEnd() - performanceTiming.getConnectStart());
// получатьполный размер страницы
fullPagePerformance.setPageSize(pageSize / (1000 * 1000));
// получать Количество полностраничных запросов
fullPagePerformance.setPageRequestNum(pageRequestNum);
System.out.println("страница" + url + ":Количество полностраничных запросов:"
+ fullPagePerformance.getPageRequestNum() + ", полный размер страницы:"
+ fullPagePerformance.getPageSize() + "MB, Общее количество DOM на всей странице:"
+ fullPagePerformance.getPageDomNum() + ", Время завершения загрузки полной страницы DOM:"
+ fullPagePerformance.getDomContentLoadedCost() + "ms, Время завершения полной загрузки страницы:"
+ fullPagePerformance.getLoadEventCost() + "ms");
// Анализируйте ненормальные реакции
PageErrorsDTO pageErrorsDTO = new PageErrorsDTO();
pageErrorsDTO.setCodeErrorResponseList(
analysisCodeErrorResponse(fullPageResponseList));
if (!pageErrorsDTO.getCodeErrorResponseList().isEmpty()) {
System.out.println("Полный ответ на исключение страницы:");
for (int i = 0; i < pageErrorsDTO.getCodeErrorResponseList().size(); i++) {
System.out.println(pageErrorsDTO.
getCodeErrorResponseList().get(i).getUrl() + ": " + pageErrorsDTO.
getCodeErrorResponseList().get(i).getStatus());
}
}
// Анализ реакции на отказ
pageErrorsDTO.setFailResponseList(
analysisFailResponse(fullPageFailList, fullPageRequestList));
if (!pageErrorsDTO.getFailResponseList().isEmpty()) {
System.out.println("Полный ответ на ошибку страницы:");
for (int i = 0; i < pageErrorsDTO.getFailResponseList().size(); i++) {
System.out.println(pageErrorsDTO.
getFailResponseList().get(i).getUrl() + ": " + pageErrorsDTO.
getFailResponseList().get(i).getErrorText() + " " + pageErrorsDTO.
getFailResponseList().get(i).getBlockedReason());
}
}
// Анализируйте медленные ответы
pageErrorsDTO.setSlowReponseList(
analysisSlowResponse(fullPageRequestList, fullPageFinishedList, 3.0));
if (!pageErrorsDTO.getSlowReponseList().isEmpty()) {
System.out.println("Полная страница медленный ответ:");
for (int i = 0; i < pageErrorsDTO.getSlowReponseList().size(); i++) {
System.out.println(pageErrorsDTO.
getSlowReponseList().get(i).getUrl() + ": " + pageErrorsDTO.
getSlowReponseList().get(i).getCost());
}
}
fullPagePerformance.setPageErrorsDTO(pageErrorsDTO);
return fullPagePerformance;
}
/** * Прокрутите страницу вниз * * @param js * @return */
private static long scrollToBottom(JavascriptExecutor js) {
long scrollStart = 0, scrollEnd = 1;
int i = 1;
while (scrollStart != scrollEnd) {
scrollStart = (Long) js.executeScript(JS_SCROLLINGY);
String scrollTo = MessageFormat.format(JS_SCROLLINGTOP, i++);
System.out.println(scrollTo);
js.executeScript(scrollTo);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
scrollEnd = (Long) js.executeScript(JS_SCROLLINGY);
// System.out.println(scrollTo + ":" + scrollEnd);
}
return scrollEnd;
}
/** * Выполните js, чтобы получить номер DOM страницы. * * @param js * @return */
private static long executeDomLengthJS(JavascriptExecutor js) {
return (Long) js.executeScript(JS_DOM_LENGTH);
}
/** * Выполните js и получите производительность Timing * * @param js * @return */
private static PerformanceTimingDTO executePerformanceTimingJS(JavascriptExecutor js) {
String performance = js.executeScript(JS_PERFORMANCE_TIMING).toString();
performance = performance.replace("unloadEventEnd=", "\"unloadEventEnd\":")
.replace("responseEnd=", "\"responseEnd\":")
.replace("responseStart=", "\"responseStart\":")
.replace("domInteractive=", "\"domInteractive\":")
.replace("domainLookupEnd=", "\"domainLookupEnd\":")
.replace("unloadEventStart=", "\"unloadEventStart\":")
.replace("domComplete=", "\"domComplete\":")
.replace("domContentLoadedEventStart=", "\"domContentLoadedEventStart\":")
.replace("domainLookupStart=", "\"domainLookupStart\":")
.replace("redirectEnd=", "\"redirectEnd\":")
.replace("redirectStart=", "\"redirectStart\":")
.replace("connectEnd=", "\"connectEnd\":")
.replace("toJSON={},", "")
.replace("connectStart=", "\"connectStart\":")
.replace("loadEventStart=", "\"loadEventStart\":")
.replace("navigationStart=", "\"navigationStart\":")
.replace("requestStart=", "\"requestStart\":")
.replace("secureConnectionStart=", "\"secureConnectionStart\":")
.replace("fetchStart=", "\"fetchStart\":")
.replace("domContentLoadedEventEnd=", "\"domContentLoadedEventEnd\":")
.replace("domLoading=", "\"domLoading\":")
.replace("loadEventEnd=", "\"loadEventEnd\":");
// System.out.println(performance);
return JSON.parseObject(
performance, PerformanceTimingDTO.class);
}
/** * Анализ ответов на коды состояния исключений * * @param networkResponseReceivedList * @return */
private static List<CodeErrorResponseDTO> analysisCodeErrorResponse
(List<NetworkResponseReceivedDTO> networkResponseReceivedList) {
List<CodeErrorResponseDTO> codeErrorResponseList = new ArrayList<CodeErrorResponseDTO>();
for (NetworkResponseReceivedDTO r : networkResponseReceivedList) {
if (r.getResponse().getStatus() >= 400
&& r.getResponse().getStatus() <= 599) {
CodeErrorResponseDTO codeErrorResponseDTO = new CodeErrorResponseDTO();
codeErrorResponseDTO.setUrl(r.getResponse().getUrl());
codeErrorResponseDTO.setStatus(r.getResponse().getStatus());
System.out.println(r.toString());
codeErrorResponseList.add(codeErrorResponseDTO);
}
}
return codeErrorResponseList;
}
/** * Анализируйте неудачные ответы * * @param networkLoadingFailedList * @param networkRequestWillBeSentList * @return */
private static List<FailResponseDTO> analysisFailResponse(
List<NetworkLoadingFailedDTO> networkLoadingFailedList,
List<NetworkRequestWillBeSentDTO> networkRequestWillBeSentList) {
List<FailResponseDTO> failResponseList = new ArrayList<FailResponseDTO>();
for (NetworkLoadingFailedDTO f : networkLoadingFailedList) {
for (NetworkRequestWillBeSentDTO r : networkRequestWillBeSentList) {
if (f.getRequestId().equals(r.getRequestId())) {
FailResponseDTO failResponseDTO = new FailResponseDTO();
failResponseDTO.setUrl(r.getRequest().getUrl());
failResponseDTO.setErrorText(f.getErrorText());
failResponseDTO.setBlockedReason(f.getBlockedReason());
failResponseList.add(failResponseDTO);
}
}
}
return failResponseList;
}
/** * Анализируйте медленные ответы,единицаs * * @param networkRequestWillBeSentList * @param networkLoadingFinishedList * @param slowThreshold * @return */
private static List<SlowReponseDTO> analysisSlowResponse(
List<NetworkRequestWillBeSentDTO> networkRequestWillBeSentList,
List<NetworkLoadingFinishedDTO> networkLoadingFinishedList,
double slowThreshold) {
List<SlowReponseDTO> slowReponseList = new ArrayList<SlowReponseDTO>();
for (NetworkRequestWillBeSentDTO r : networkRequestWillBeSentList) {
for (NetworkLoadingFinishedDTO f : networkLoadingFinishedList) {
if (r.getRequestId().equals(f.getRequestId())) {
double cost = f.getTimestamp() - r.getTimestamp();
if (cost >= slowThreshold) {
SlowReponseDTO slowReponseDTO = new SlowReponseDTO();
slowReponseDTO.setUrl(r.getRequest().getUrl());
slowReponseDTO.setCost(cost);
slowReponseList.add(slowReponseDTO);
}
}
}
}
return slowReponseList;
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < THREAD_SIZE; i++) {
Thread driverThread = new Thread(new DriverRunnable(), "driverThread" + i);
driverThread.start();
}
for (int i = 0; i < 1; i++) {
reqQuene.put("https://www.suning.com");
}
}
}
Издатель: Лидер стека программистов полного стека, укажите источник для перепечатки: https://javaforall.cn/158899.html Исходная ссылка: https://javaforall.cn