Chromium Code Reviews| Index: presubmit_canned_checks.py |
| diff --git a/presubmit_canned_checks.py b/presubmit_canned_checks.py |
| index 24ae89f5751b946bbcbe0f0819683c8030c47c46..952e3ac9e29d77bae23022fa1a8d45a0fb9e5b41 100755 |
| --- a/presubmit_canned_checks.py |
| +++ b/presubmit_canned_checks.py |
| @@ -256,35 +256,53 @@ def CheckTreeIsOpen(input_api, output_api, url, closed): |
| return [] |
| -def _RunPythonUnitTests_LoadTests(input_api, module_name): |
| - """Meant to be stubbed out during unit testing.""" |
| - module = __import__(module_name) |
| - for part in module_name.split('.')[1:]: |
| - module = getattr(module, part) |
| - return input_api.unittest.TestLoader().loadTestsFromModule(module)._tests |
| - |
| - |
| def RunPythonUnitTests(input_api, output_api, unit_tests): |
| - """Imports the unit_tests modules and run them.""" |
| + """Run the unit tests out of process, capture the output and use the result |
| + code to determine success. |
| + """ |
| # We don't want to hinder users from uploading incomplete patches. |
| if input_api.is_committing: |
| message_type = output_api.PresubmitError |
| else: |
| message_type = output_api.PresubmitNotifyResult |
| - tests_suite = [] |
| outputs = [] |
| for unit_test in unit_tests: |
| - try: |
| - tests_suite.extend(_RunPythonUnitTests_LoadTests(input_api, unit_test)) |
| - except ImportError: |
| - outputs.append(message_type("Failed to load %s" % unit_test, |
| - long_text=input_api.traceback.format_exc())) |
| - |
| - buffer = input_api.cStringIO.StringIO() |
| - results = input_api.unittest.TextTestRunner(stream=buffer, verbosity=0).run( |
| - input_api.unittest.TestSuite(tests_suite)) |
| - if not results.wasSuccessful(): |
| - outputs.append(message_type("%d unit tests failed." % |
| - (len(results.failures) + len(results.errors)), |
| - long_text=buffer.getvalue())) |
| - return outputs |
| + # Run the unit tests out of process. This is because some unit tests |
| + # stub out base libraries and don't clean up their mess. It's too easy to |
| + # get subtle bugs. |
| + cwd = None |
| + env = None |
| + unit_test_name = unit_test |
| + # "python -m test.unit_test" doesn't work. We need to change to the right |
| + # directory instead. |
| + if '.' in unit_test: |
| + # Tests imported in submodules (subdirectories) assume that the current |
| + # directory is in the PYTHONPATH. Manually fix that. |
| + unit_test = unit_test.replace('.', '/') |
| + cwd = input_api.os_path.dirname(unit_test) |
| + unit_test = input_api.os_path.basename(unit_test) |
| + env = input_api.environ.copy() |
| + backpath = [';'.join(['..'] * (cwd.count('/') + 1))] |
| + if env.get('PYTHONPATH'): |
| + backpath.append(env.get('PYTHONPATH')) |
| + env['PYTHONPATH'] = ';'.join((backpath)) |
| + subproc = input_api.subprocess.Popen( |
| + [ |
| + input_api.python_executable, |
| + "-m", |
| + "%s" % unit_test |
| + ], |
| + cwd=cwd, |
| + env=env, |
| + stdin=input_api.subprocess.PIPE, |
| + stdout=input_api.subprocess.PIPE, |
| + stderr=input_api.subprocess.PIPE) |
| + stdoutdata, stderrdata = subproc.communicate() |
| + # Discard the output if returncode != 0 |
|
Jói Sigurðsson
2009/06/23 20:03:51
!= -> ==
|
| + if subproc.returncode: |
| + outputs.append("Test '%s' failed with code %d\n%s\n%s\n" % ( |
| + unit_test_name, subproc.returncode, stdoutdata, stderrdata)) |
| + if outputs: |
| + return [message_type("%d unit tests failed." % len(outputs), |
| + long_text='\n'.join(outputs))] |
| + return [] |