Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 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 """Test fixture for tests involving installing/updating Chrome. | 5 """Test fixture for tests involving installing/updating Chrome. |
| 6 | 6 |
| 7 Provides an interface to install or update chrome from within a testcase, and | 7 Provides an interface to install or update chrome from within a testcase, and |
| 8 allows users to run tests using installed version of Chrome. User and system | 8 allows users to run tests using installed version of Chrome. User and system |
| 9 level installations are supported, and either one can be used for running the | 9 level installations are supported, and either one can be used for running the |
| 10 tests. Currently the only platform it supports is Windows. | 10 tests. Currently the only platform it supports is Windows. |
| 11 """ | 11 """ |
| 12 | 12 |
| 13 import atexit | 13 import atexit |
| 14 import fnmatch | |
| 14 import logging | 15 import logging |
| 15 import optparse | 16 import optparse |
| 16 import os | 17 import os |
| 17 import platform | 18 import platform |
| 18 import re | 19 import re |
| 19 import shutil | 20 import shutil |
| 20 import stat | 21 import stat |
| 21 import sys | 22 import sys |
| 22 import tempfile | 23 import tempfile |
| 23 import unittest | 24 import unittest |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 243 help='Specifies any additional Chrome options (i.e. --system-level).') | 244 help='Specifies any additional Chrome options (i.e. --system-level).') |
| 244 parser.add_option( | 245 parser.add_option( |
| 245 '--install-build', type='string', default='', dest='install_build', | 246 '--install-build', type='string', default='', dest='install_build', |
| 246 help='Specifies the build to be used for fresh install testing.') | 247 help='Specifies the build to be used for fresh install testing.') |
| 247 parser.add_option( | 248 parser.add_option( |
| 248 '--update-builds', type='string', default='', dest='update_builds', | 249 '--update-builds', type='string', default='', dest='update_builds', |
| 249 help='Specifies the builds to be used for updater testing.') | 250 help='Specifies the builds to be used for updater testing.') |
| 250 parser.add_option( | 251 parser.add_option( |
| 251 '--install-type', type='string', default='user', dest='install_type', | 252 '--install-type', type='string', default='user', dest='install_type', |
| 252 help='Type of installation (i.e., user, system, or both)') | 253 help='Type of installation (i.e., user, system, or both)') |
| 254 parser.add_option( | |
| 255 '-f', '--filter', type='string', default=None, dest='filter', | |
| 256 help='Filter that specifies the test or testsuite to run.') | |
| 253 self._opts, self._args = parser.parse_args() | 257 self._opts, self._args = parser.parse_args() |
| 254 self._ValidateArgs() | 258 self._ValidateArgs() |
| 255 if(self._opts.install_type == 'system' or | 259 if(self._opts.install_type == 'system' or |
| 256 self._opts.install_type == 'user'): | 260 self._opts.install_type == 'user'): |
| 257 install_type = ({ | 261 install_type = ({ |
| 258 'system' : chrome_installer_win.InstallationType.SYSTEM, | 262 'system' : chrome_installer_win.InstallationType.SYSTEM, |
| 259 'user' : chrome_installer_win.InstallationType.USER}).get( | 263 'user' : chrome_installer_win.InstallationType.USER}).get( |
| 260 self._opts.install_type) | 264 self._opts.install_type) |
| 261 InstallTest.SetInstallType(install_type) | 265 InstallTest.SetInstallType(install_type) |
| 262 update_builds = (self._opts.update_builds.split(',') if | 266 update_builds = (self._opts.update_builds.split(',') if |
| 263 self._opts.update_builds else []) | 267 self._opts.update_builds else []) |
| 264 options = self._opts.options.split(',') if self._opts.options else [] | 268 options = self._opts.options.split(',') if self._opts.options else [] |
| 265 InstallTest.InitTestFixture(self._opts.install_build, | 269 InstallTest.InitTestFixture(self._opts.install_build, update_builds, |
| 266 update_builds, | 270 self._opts.url, options) |
| 267 self._opts.url, | 271 self._mod_name = os.path.splitext(os.path.basename(sys.argv[0]))[0] |
| 268 options) | 272 if os.path.dirname(sys.argv[0]) not in sys.path: |
|
kkania
2012/10/24 15:19:54
I think this is unnecessary. sys.argv[0] was just
nkang
2012/10/24 23:35:14
I agree. I was thinking the same thing that it sho
| |
| 273 sys.path.append(os.path.dirname(sys.argv[0])) | |
| 269 | 274 |
| 270 def _ValidateArgs(self): | 275 def _ValidateArgs(self): |
| 271 """Verifies the sanity of the command arguments. | 276 """Verifies the sanity of the command arguments. |
| 272 | 277 |
| 273 Confirms that all specified builds have a valid version number, and the | 278 Confirms that all specified builds have a valid version number, and the |
| 274 build urls are valid. | 279 build urls are valid. |
| 275 """ | 280 """ |
| 276 builds = [] | 281 builds = [] |
| 277 if self._opts.install_build: | 282 if self._opts.install_build: |
| 278 builds.append(self._opts.install_build) | 283 builds.append(self._opts.install_build) |
| 279 if self._opts.update_builds: | 284 if self._opts.update_builds: |
| 280 builds.extend(self._opts.update_builds.split(',')) | 285 builds.extend(self._opts.update_builds.split(',')) |
| 281 builds = list(frozenset(builds)) | 286 builds = list(frozenset(builds)) |
| 282 for build in builds: | 287 for build in builds: |
| 283 if not re.match('\d+\.\d+\.\d+\.\d+', build): | 288 if not re.match('\d+\.\d+\.\d+\.\d+', build): |
| 284 raise RuntimeError('Invalid build number: %s' % build) | 289 raise RuntimeError('Invalid build number: %s' % build) |
| 285 if not pyauto_utils.DoesUrlExist('%s/%s/' % (self._opts.url, build)): | 290 if not pyauto_utils.DoesUrlExist('%s/%s/' % (self._opts.url, build)): |
| 286 raise RuntimeError('Could not locate build no. %s' % build) | 291 raise RuntimeError('Could not locate build no. %s' % build) |
| 287 | 292 |
| 288 def _SetLoggingConfiguration(self): | 293 def _SetLoggingConfiguration(self): |
| 289 """Sets the basic logging configuration.""" | 294 """Sets the basic logging configuration.""" |
| 290 log_format = '%(asctime)s %(levelname)-8s %(message)s' | 295 log_format = '%(asctime)s %(levelname)-8s %(message)s' |
| 291 logging.basicConfig(level=logging.INFO, format=log_format) | 296 logging.basicConfig(level=logging.INFO, format=log_format) |
| 292 | 297 |
| 293 def _GetTests(self): | 298 def _GetFilteredTests(self): |
|
kkania
2012/10/24 15:19:54
move this whole Main class out to a new file, call
nkang
2012/10/24 23:35:14
Moved Main to a new file called run_install_tests.
| |
| 294 """Returns a list of unittests from the calling script.""" | 299 """Returns a list of filtered unittests from the calling script.""" |
| 295 mod_name = [os.path.splitext(os.path.basename(sys.argv[0]))[0]] | 300 all_tests = unittest.defaultTestLoader.loadTestsFromName(self._mod_name) |
| 296 if os.path.dirname(sys.argv[0]) not in sys.path: | 301 return self._FilterTestSuite(all_tests, self._opts.filter) |
| 297 sys.path.append(os.path.dirname(sys.argv[0])) | 302 |
| 298 return unittest.defaultTestLoader.loadTestsFromNames(mod_name) | 303 def _GetTestsFromSuite(self, suite): |
| 304 """Returns all the tests from a given test suite. | |
| 305 | |
| 306 Args: | |
| 307 suite: A unittest.TestSuite object. | |
| 308 | |
| 309 Returns: | |
| 310 A list that contains all the tests found in the suite. | |
| 311 """ | |
| 312 tests = [] | |
| 313 for test in suite: | |
| 314 if isinstance(test, unittest.TestSuite): | |
| 315 tests += self._GetTestsFromSuite(test) | |
| 316 else: | |
| 317 tests += [test] | |
| 318 return tests | |
| 319 | |
| 320 def _GetTestName(self, test): | |
| 321 """Gets the test name of the given unittest test. | |
| 322 | |
| 323 Args: | |
| 324 test: A unittest test. | |
| 325 | |
| 326 Returns: | |
| 327 A string representing the full test name. | |
| 328 """ | |
| 329 return '.'.join([test.__module__, test.__class__.__name__, | |
| 330 test._testMethodName]) | |
| 331 | |
| 332 def _FilterTestSuite(self, suite, gtest_filter): | |
| 333 """Returns a new filtered test suite based on the given gtest filter. | |
| 334 | |
| 335 See http://code.google.com/p/googletest/wiki/AdvancedGuide for | |
| 336 gtest_filter specification. | |
| 337 | |
| 338 Args: | |
| 339 suite: A unittest.TestSuite object, which can be obtained by calling | |
| 340 |unittest.defaultTestLoader.loadTestsFromName|. | |
| 341 gtest_filter: The gtest filter to use. Filter can be passed as follows: | |
| 342 --filter=*className* or --filter=*testcaseName. | |
| 343 | |
| 344 Returns: | |
| 345 A unittest.TestSuite object that contains tests that match the gtest | |
| 346 filter. | |
| 347 """ | |
| 348 return unittest.TestSuite( | |
| 349 self._FilterTests(self._GetTestsFromSuite(suite), gtest_filter)) | |
| 350 | |
| 351 def _FilterTests(self, all_tests, gtest_filter): | |
| 352 """Returns a filtered list of tests based on the given gtest filter. | |
| 353 | |
| 354 Args: | |
| 355 all_tests: A list that contains all unittests in a given suite. This | |
| 356 list must be obtained by calling |_GetTestsFromSuite|. | |
| 357 gtest_filter: The gtest filter to use. Filter can be passed as follows: | |
| 358 *className* or *testcaseName. | |
| 359 | |
| 360 Returns: | |
| 361 A list that contains all tests that match the given gtest filter. | |
| 362 """ | |
| 363 pattern_groups = gtest_filter.split('-') | |
| 364 positive_patterns = pattern_groups[0].split(':') | |
| 365 negative_patterns = None | |
| 366 if len(pattern_groups) > 1: | |
| 367 negative_patterns = pattern_groups[1].split(':') | |
| 368 tests = [] | |
| 369 for test in all_tests: | |
| 370 test_name = self._GetTestName(test) | |
| 371 # Test name must by matched by one positive pattern. | |
| 372 for pattern in positive_patterns: | |
| 373 if fnmatch.fnmatch(test_name, pattern): | |
| 374 break | |
| 375 else: | |
| 376 continue | |
| 377 # Test name must not be matched by any negative patterns. | |
| 378 for pattern in negative_patterns or []: | |
| 379 if fnmatch.fnmatch(test_name, pattern): | |
| 380 break | |
| 381 else: | |
| 382 tests += [test] | |
| 383 return tests | |
| 299 | 384 |
| 300 def _Run(self): | 385 def _Run(self): |
| 301 """Runs the unit tests.""" | 386 """Runs the unit tests.""" |
| 302 tests = self._GetTests() | 387 if self._opts.filter: |
| 388 tests = self._GetFilteredTests() | |
| 389 else: | |
| 390 tests = unittest.defaultTestLoader.loadTestsFromName(self._mod_name) | |
| 303 result = pyauto_utils.GTestTextTestRunner(verbosity=1).run(tests) | 391 result = pyauto_utils.GTestTextTestRunner(verbosity=1).run(tests) |
| 304 del(tests) | 392 del(tests) |
| 305 if not result.wasSuccessful(): | 393 if not result.wasSuccessful(): |
| 306 print >>sys.stderr, ('Not all tests were successful.') | 394 print >>sys.stderr, ('Not all tests were successful.') |
| 307 sys.exit(1) | 395 sys.exit(1) |
| 308 sys.exit(0) | 396 sys.exit(0) |
| OLD | NEW |