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

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

Issue 2528483004: Adds skeleton of new integration test framework. (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
OLDNEW
(Empty)
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
3 # found in the LICENSE file.
4
5 import argparse
6 import json
7 import os
8 import shlex
9 import sys
10 import time
11 import traceback
12
13 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
14 os.pardir, 'third_party', 'webdriver', 'pylib'))
15 from selenium import webdriver
16 from selenium.webdriver.chrome.options import Options
17
18 # TODO(robertogden) add logging
19
20
21 def ParseFlags():
22 """
23 Parses the given command line arguments and returns an object with the flags
24 as properties.
25 """
26 parser = argparse.ArgumentParser()
27 parser.add_argument('--browser_args', nargs=1, type=str, help='Override '
28 'browser flags in code with these flags')
29 parser.add_argument('--via_header_matches', metavar='via_header', nargs=1,
RyanSturm 2016/11/29 19:31:46 nit: s/via_header_matchers/via_header_value/
30 default='1.1 Chrome-Compression-Proxy', help='What the via should match to '
31 'be considered valid')
32 parser.add_argument('--chrome_exec', nargs=1, type=str, help='The path to '
33 'the Chrome or Chromium executable')
RyanSturm 2016/11/29 19:31:46 Can you add that if no chrome_exec is supplied, th
34 parser.add_argument('chrome_driver', nargs=1, type=str, help='The path to '
35 'the ChromeDriver executable')
36 # TODO(robertogden) make this a logging statement
37 print 'DEBUG: Args=', json.dumps(vars(parser.parse_args(sys.argv[1:])))
38 return parser.parse_args(sys.argv[1:])
39
40 def HandleException():
41 """
42 Writes the exception being handled and a stack trace to stderr.
43 """
44 sys.stderr.write("**************************************\n")
45 sys.stderr.write("**************************************\n")
46 sys.stderr.write("** **\n")
47 sys.stderr.write("** UNCAUGHT EXCEPTION **\n")
48 sys.stderr.write("** **\n")
49 sys.stderr.write("**************************************\n")
50 sys.stderr.write("**************************************\n")
51 traceback.print_exception(*sys.exc_info())
52 sys.exit(1)
53
54 class TestDriver:
55 """
56 This class is the tool that is used by every integration test to interact with
57 the Chromium browser and validate proper functionality. This class sits on top
58 of the Selenium Chrome Webdriver with added utility and helper functions for
59 Chrome-Proxy. This class should be used with Python's 'with' operator.
60 """
61
62 def __init__(self):
63 self._flags = ParseFlags()
64 self._driver = None
65 self._args = {}
tbansal1 2016/11/29 18:38:53 Can this be renamed to chrome_args?
Robert Ogden 2016/11/29 18:53:54 Done.
66 self._url = ''
67
68 def __enter__(self):
69 return self
70
71 def __exit__(self, exc_type, exc_value, tb):
72 if self._driver:
73 self._StopDriver()
74
75 def _OverrideChromeArgs(self):
76 """
77 Overrides any given flags in the code with those given on the command line.
78 """
79 if self._flags.browser_args and len(self._flags.browser_args) > 0:
80 for a in shlex.split(self._flags.browser_args):
RyanSturm 2016/11/29 19:31:46 nit: s/a/arg/
81 self._args[a] = True
82
83 def _StartDriver(self):
84 """
85 Parses the flags to pass to Chromium, then starts the ChromeDriver.
86 """
87 opts = Options()
RyanSturm 2016/11/29 19:31:46 nit: s/opts/options/
88 for a in self._args:
RyanSturm 2016/11/29 19:31:46 nit: s/a/arg/
89 opts.add_argument(a)
90 caps = {'loggingPrefs': {'performance': 'INFO'}}
RyanSturm 2016/11/29 19:31:46 nit: s/caps/capabilities/
91 if self._flags.chrome_exec:
92 caps['chrome.binary'] = self._flags.chrome_exec
93 driver = webdriver.Chrome(executable_path=self._flags.chrome_driver[0],
94 chrome_options=opts, desired_capabilities=caps)
95 driver.command_executor._commands.update({
96 'getAvailableLogTypes': ('GET', '/session/$sessionId/log/types'),
97 'getLog': ('POST', '/session/$sessionId/log')})
98 self._driver = driver
99
100 def _StopDriver(self):
101 """
102 Nicely stops the ChromeDriver.
103 """
104 self._driver.quit()
105 del self._driver
106
107 def AddChromeArgs(self, args):
108 """
109 Adds multiple arguments that will be passed to Chromium at start.
110 """
111 if not self._args:
RyanSturm 2016/11/29 19:31:46 can self._args ever not be a value after __init__?
112 self._args = {}
113 for a in args:
114 self._args[a] = True
115
116 def AddChromeArg(self, arg):
tbansal1 2016/11/29 18:38:53 Is this being called somewhere?
Robert Ogden 2016/11/29 18:53:54 Not yet, but I think it is an important method to
117 """
118 Adds a single argument that will be passed to Chromium at start.
119 """
120 if not self._args:
121 self._args = {}
122 self._args[arg] = True
123
124 def RemoveChromeArgs(self, args):
125 """
126 Removes multiple arguments that will no longer be passed to Chromium at
127 start.
128 """
129 if not self._args:
130 self._args = {}
131 return
132 for a in args:
133 del self._args[a]
134
135 def RemoveChromeArg(self, arg):
tbansal1 2016/11/29 18:38:53 Is this being called somewhere?
Robert Ogden 2016/11/29 18:53:54 Same as above.
136 """
137 Removes a single argument that will no longer be passed to Chromium at
138 start.
139 """
140 if not self._args:
141 self._args = {}
142 return
143 del self._args[arg]
144
145 def ClearChromeArgs(self):
146 """
147 Removes all arguments from Chromium at start.
148 """
149 self._args = {}
150
151 def ClearCache(self):
152 """
153 Clears the browser cache. Important note: ChromeDriver automatically starts
154 a clean copy of Chrome on every instantiation.
155 """
156 self.ExecuteJavascript('if(window.chrome && chrome.benchmarking && '
157 'chrome.benchmarking.clearCache){chrome.benchmarking.clearCache(); '
158 'chrome.benchmarking.clearPredictorCache();chrome.benchmarking.'
159 'clearHostResolverCache();}')
160
161 # TODO(robertogden) use a smart page instead
162 def SetURL(self, url):
163 """
164 Sets the URL that the browser will navigate to during the test.
165 """
166 self._url = url
167
168 # TODO(robertogden) add timeout
169 def LoadPage(self):
170 """
171 Starts Chromium with any arguments previously given and navigates to the
172 previously given URL.
173 """
174 if not self._driver:
175 self._StartDriver()
176 self._driver.get(self._url)
177
178 # TODO(robertogden) add timeout
179 def ExecuteJavascript(self, script):
180 """
181 Executes the given javascript in the browser's current page as if it were on
182 the console. Returns a string of whatever the evaluation was.
183 """
184 if not self._driver:
185 self._StartDriver()
186 return self._driver.execute_script("return " + script)
187
188
189 class IntegrationTest:
190 """
191 A parent class for all integration tests with utility and assertion methods.
192 All methods starting with the word 'test' (ignoring case) will be called with
193 the RunAllTests() method which can be used in place of a main method.
194 """
195 def RunAllTests(self):
196 """
197 Runs all methods starting with the word 'test' (ignoring case) in the class.
198 Can be used in place of a main method to run all tests in a class.
199 """
200 methodList = [method for method in dir(self) if callable(getattr(self,
201 method)) and method.lower().startswith('test')]
202 for method in methodList:
203 try:
204 getattr(self, method)()
205 except Exception as e:
206 HandleException(e)
tbansal1 2016/11/29 18:38:53 Pass the name of the test in the HandleException s
Robert Ogden 2016/11/29 18:53:54 Done.
RyanSturm 2016/11/29 19:31:46 I think tbansal meant pass method and the exceptio
207
208 # TODO(robertogden) add some nice assertion functions
209
210 def Fail(self, msg):
211 sys.stderr.write("**************************************\n")
212 sys.stderr.write("**************************************\n")
213 sys.stderr.write("** **\n")
214 sys.stderr.write("** TEST FAILURE **\n")
215 sys.stderr.write("** **\n")
216 sys.stderr.write("**************************************\n")
217 sys.stderr.write("**************************************\n")
218 sys.stderr.write(msg, '\n')
219 sys.exit(1)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698