Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(324)

Side by Side Diff: tools/chrome_proxy/webdriver/common.py

Issue 2550433002: Add GetResponses() and related funcionality (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/chrome_proxy/webdriver/simple_smoke.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2016 The Chromium Authors. All rights reserved. 1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import argparse 5 import argparse
6 import json 6 import json
7 import os 7 import os
8 import re
8 import shlex 9 import shlex
9 import sys 10 import sys
10 import time 11 import time
11 import traceback 12 import traceback
12 13
13 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 14 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
14 os.pardir, 'third_party', 'webdriver', 'pylib')) 15 os.pardir, 'third_party', 'webdriver', 'pylib'))
15 from selenium import webdriver 16 from selenium import webdriver
16 from selenium.webdriver.chrome.options import Options 17 from selenium.webdriver.chrome.options import Options
17 18
18 # TODO(robertogden) add logging 19 # TODO(robertogden) add logging
19 20
20 21
21 def ParseFlags(): 22 def ParseFlags():
22 """ 23 """
23 Parses the given command line arguments and returns an object with the flags 24 Parses the given command line arguments and returns an object with the flags
24 as properties. 25 as properties.
25 """ 26 """
26 parser = argparse.ArgumentParser() 27 parser = argparse.ArgumentParser()
27 parser.add_argument('--browser_args', nargs=1, type=str, help='Override ' 28 parser.add_argument('--browser_args', nargs=1, type=str, help='Override '
28 'browser flags in code with these flags') 29 'browser flags in code with these flags')
29 parser.add_argument('--via_header_value', metavar='via_header', nargs=1, 30 parser.add_argument('--via_header_value', metavar='via_header', nargs=1,
30 default='1.1 Chrome-Compression-Proxy', help='What the via should match to ' 31 default='1.1 Chrome-Compression-Proxy', help='What the via should match to '
31 'be considered valid') 32 'be considered valid')
32 parser.add_argument('--chrome_exec', nargs=1, type=str, help='The path to ' 33 parser.add_argument('--chrome_exec', nargs=1, type=str, help='The path to '
33 'the Chrome or Chromium executable') 34 'the Chrome or Chromium executable')
34 parser.add_argument('chrome_driver', nargs=1, type=str, help='The path to ' 35 parser.add_argument('chrome_driver', nargs=1, type=str, help='The path to '
35 'the ChromeDriver executable. If not given, the default system chrome ' 36 'the ChromeDriver executable. If not given, the default system chrome '
36 'will be used.') 37 'will be used.')
37 # TODO(robertogden) make this a logging statement 38 # TODO(robertogden) make a logging statement here
sclittle 2016/12/06 00:09:49 style nit: You should have a colon after the "TODO
Robert Ogden 2016/12/06 16:57:16 Done.
38 print 'DEBUG: Args=', json.dumps(vars(parser.parse_args(sys.argv[1:])))
39 return parser.parse_args(sys.argv[1:]) 39 return parser.parse_args(sys.argv[1:])
40 40
41 def HandleException(test_name=None): 41 def HandleException(test_name=None):
42 """ 42 """
43 Writes the exception being handled and a stack trace to stderr. 43 Writes the exception being handled and a stack trace to stderr.
44 """ 44 """
45 sys.stderr.write("**************************************\n") 45 sys.stderr.write("**************************************\n")
46 sys.stderr.write("**************************************\n") 46 sys.stderr.write("**************************************\n")
47 sys.stderr.write("** **\n") 47 sys.stderr.write("** **\n")
48 sys.stderr.write("** UNCAUGHT EXCEPTION **\n") 48 sys.stderr.write("** UNCAUGHT EXCEPTION **\n")
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 # TODO(robertogden) add timeout 184 # TODO(robertogden) add timeout
185 def ExecuteJavascript(self, script): 185 def ExecuteJavascript(self, script):
186 """ 186 """
187 Executes the given javascript in the browser's current page as if it were on 187 Executes the given javascript in the browser's current page as if it were on
188 the console. Returns a string of whatever the evaluation was. 188 the console. Returns a string of whatever the evaluation was.
189 """ 189 """
190 if not self._driver: 190 if not self._driver:
191 self._StartDriver() 191 self._StartDriver()
192 return self._driver.execute_script("return " + script) 192 return self._driver.execute_script("return " + script)
193 193
194 def GetPerformanceLogs(self, method_filter=r'Network\.responseReceived'):
sclittle 2016/12/06 00:09:49 For all of these class and function definitions, y
Robert Ogden 2016/12/06 16:57:16 Done.
195 """
196 Returns all logged Performance events from Chrome as a list of dicts, since
197 the last time this function was called. method_filter accepts a regex to
198 match against the method type of the events to return.
199 """
200 all_messages = []
201 for log in self._driver.execute('getLog', {'type': 'performance'})['value']:
202 message = json.loads(log['message'])['message']
203 if re.match(method_filter, message['method']):
204 all_messages.append(message)
205 return all_messages
sclittle 2016/12/06 00:09:49 nit: This is minor, but if you don't need the enti
Robert Ogden 2016/12/06 16:57:16 Thought about that too. Kept it like this so that
206
207 def GetHTTPResponses(self, include_favicon=False):
208 """
209 Parses the Performance Logs and returns a list of HTTPResponse objects, each
210 representing a single completed HTTP transaction by Chrome. Optionally
211 allows favicon requests to be included in the result as well.
212 This function should be called exactly once after every page load.
213 """
214 def MakeHTTPResponse(log_dict):
215 params = log_dict['params']
216 response_dict = params['response']
217 response_headers = response_dict['headers']
218 request_headers = response_dict['requestHeaders']
219 url = response_dict['url']
220 protocol = request_headers[':scheme']
221 status = response_dict['status']
222 request_type = params['type']
223 return HTTPResponse(response_headers, request_headers, url, protocol,
sclittle 2016/12/06 00:09:49 nit: Instead of making so many local variables, co
Robert Ogden 2016/12/06 16:57:16 Done.
224 status, request_type)
225 all_responses = []
226 for message in self.GetPerformanceLogs():
227 response = MakeHTTPResponse(message)
228 is_favicon = response.url.endswith('favicon.ico')
229 if not is_favicon or include_favicon:
230 all_responses.append(response)
231 return all_responses
232
233 class HTTPResponse:
234 """
235 This class represents a single HTTP transaction (request and response) by
236 Chrome. This class also includes several convenience functions for ChromeProxy
237 specific assertions.
238 """
239
240 def __init__(self, response_headers, request_headers, url, protocol,
241 status, request_type):
242 self._response_headers = response_headers
243 self._request_headers = request_headers
244 self._url = url
245 self._protocol = protocol
246 self._status = status
247 self._request_type = request_type
248 self._flags = ParseFlags()
249
250 def __str__(self):
251 self_dict = {
252 'response_headers': self._response_headers,
253 'request_headers': self._request_headers,
254 'url': self._url,
255 'protocol': self._protocol,
256 'status': self._status,
257 'request_type': self._request_type
258 }
259 return json.dumps(self_dict)
260
261 @property
262 def response_headers(self):
263 return self._response_headers
264
265 @property
266 def request_headers(self):
267 return self._request_headers
268
269 @property
270 def url(self):
271 return self._url
272
273 @property
274 def protocol(self):
275 return self._protocol
276
277 @property
278 def status(self):
279 return self._status
280
281 @property
282 def request_type(self):
283 return self._request_type
284
285 def UsedHTTPS(self):
286 return self._protocol == 'https'
sclittle 2016/12/06 00:09:49 What do you intent |UsedHTTPS| to be used for? I h
Robert Ogden 2016/12/06 16:57:15 Correct, there are a number of tests where we need
287
288 def ResponseHasViaHeader(self):
289 return 'via' in self._response_headers and (self._response_headers['via'] ==
290 self._flags.via_header_value)
291
292 def WasXHR(self):
293 return self.request_type == 'XHR'
194 294
195 class IntegrationTest: 295 class IntegrationTest:
196 """ 296 """
197 A parent class for all integration tests with utility and assertion methods. 297 A parent class for all integration tests with utility and assertion methods.
198 All methods starting with the word 'test' (ignoring case) will be called with 298 All methods starting with the word 'test' (ignoring case) will be called with
199 the RunAllTests() method which can be used in place of a main method. 299 the RunAllTests() method which can be used in place of a main method.
200 """ 300 """
201 def RunAllTests(self): 301 def RunAllTests(self):
202 """ 302 """
203 Runs all methods starting with the word 'test' (ignoring case) in the class. 303 Runs all methods starting with the word 'test' (ignoring case) in the class.
(...skipping 13 matching lines...) Expand all
217 def Fail(self, msg): 317 def Fail(self, msg):
218 sys.stderr.write("**************************************\n") 318 sys.stderr.write("**************************************\n")
219 sys.stderr.write("**************************************\n") 319 sys.stderr.write("**************************************\n")
220 sys.stderr.write("** **\n") 320 sys.stderr.write("** **\n")
221 sys.stderr.write("** TEST FAILURE **\n") 321 sys.stderr.write("** TEST FAILURE **\n")
222 sys.stderr.write("** **\n") 322 sys.stderr.write("** **\n")
223 sys.stderr.write("**************************************\n") 323 sys.stderr.write("**************************************\n")
224 sys.stderr.write("**************************************\n") 324 sys.stderr.write("**************************************\n")
225 sys.stderr.write(msg, '\n') 325 sys.stderr.write(msg, '\n')
226 sys.exit(1) 326 sys.exit(1)
OLDNEW
« no previous file with comments | « no previous file | tools/chrome_proxy/webdriver/simple_smoke.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698