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

Side by Side Diff: build/android/pylib/host_driven/setup.py

Issue 19537004: [Android] Converts host driven tests to common test_dispatcher (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sharding_refactoring
Patch Set: Created 7 years, 5 months 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
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 """Runs the Python tests (relies on using the Java test runner).""" 5 """Runs the Python tests (relies on using the Java test runner)."""
6 6
7 import functools
7 import logging 8 import logging
8 import os 9 import os
9 import sys 10 import sys
10 import types 11 import types
11 12
12 from pylib import android_commands 13 from pylib import android_commands
13 from pylib.base import base_test_result 14 from pylib.base import base_test_result
14 from pylib.instrumentation import test_package 15 from pylib.base import shard
15 from pylib.instrumentation import test_runner
16 from pylib.utils import report_results 16 from pylib.utils import report_results
17 17
18 import instrumentation_test_base
18 import python_test_base 19 import python_test_base
19 from python_test_sharder import PythonTestSharder 20 import test_runner
20 from test_info_collection import TestInfoCollection 21 import test_info_collection
21 22
22 23
23 def _GetPythonFiles(root, files): 24 def _GetPythonFiles(root, files):
24 """Returns all files from |files| that end in 'Test.py'. 25 """Returns all files from |files| that end in 'Test.py'.
25 26
26 Args: 27 Args:
27 root: A directory name with python files. 28 root: A directory name with python files.
28 files: A list of file names. 29 files: A list of file names.
29 30
30 Returns: 31 Returns:
31 A list with all Python driven test file paths. 32 A list with all Python driven test file paths.
32 """ 33 """
33 return [os.path.join(root, f) for f in files if f.endswith('Test.py')] 34 return [os.path.join(root, f) for f in files if f.endswith('Test.py')]
34 35
35 36
36 def _InferImportNameFromFile(python_file): 37 def _InferImportNameFromFile(python_file):
37 """Given a file, infer the import name for that file. 38 """Given a file, infer the import name for that file.
38 39
39 Example: /usr/foo/bar/baz.py -> baz. 40 Example: /usr/foo/bar/baz.py -> baz.
40 41
41 Args: 42 Args:
42 python_file: path to the Python file, ostensibly to import later. 43 python_file: Path to the Python file, ostensibly to import later.
43 44
44 Returns: 45 Returns:
45 The module name for the given file. 46 The module name for the given file.
46 """ 47 """
47 return os.path.splitext(os.path.basename(python_file))[0] 48 return os.path.splitext(os.path.basename(python_file))[0]
48 49
49 50
50 def DispatchPythonTests(options):
51 """Dispatches the Python tests. If there are multiple devices, use sharding.
52
53 Args:
54 options: command line options.
55
56 Returns:
57 A tuple of (base_test_result.TestRunResults object, exit code)
58
59 Raises:
60 Exception: If there are no attached devices.
61 """
62
63 attached_devices = android_commands.GetAttachedDevices()
64 if not attached_devices:
65 raise Exception('You have no devices attached or visible!')
66 if options.test_device:
67 attached_devices = [options.test_device]
68
69 test_collection = TestInfoCollection()
70 all_tests = _GetAllTests(options.python_test_root, options.official_build)
71 test_collection.AddTests(all_tests)
72 test_names = [t.qualified_name for t in all_tests]
73 logging.debug('All available tests: ' + str(test_names))
74
75 available_tests = test_collection.GetAvailableTests(
76 options.annotations, options.exclude_annotations, options.test_filter)
77
78 if not available_tests:
79 logging.warning('No Python tests to run with current args.')
80 return (base_test_result.TestRunResults(), 0)
81
82 test_names = [t.qualified_name for t in available_tests]
83 logging.debug('Final list of tests to run: ' + str(test_names))
84
85 # Copy files to each device before running any tests.
86 for device_id in attached_devices:
87 logging.debug('Pushing files to device %s', device_id)
88 test_pkg = test_package.TestPackage(options.test_apk_path,
89 options.test_apk_jar_path)
90 test_files_copier = test_runner.TestRunner(
91 options.build_type, options.test_data, options.install_apk,
92 options.save_perf_json, options.screenshot_failures, options.tool,
93 options.wait_for_debugger, options.disable_assertions,
94 options.push_deps, options.cleanup_test_files, device_id, 0, test_pkg,
95 [])
96 test_files_copier.InstallTestPackage()
97 if options.push_deps:
98 logging.info('Pushing data deps to device.')
99 test_files_copier.PushDataDeps()
100 else:
101 logging.warning('Skipping pushing data deps to device.')
102
103 # Actually run the tests.
104 if len(attached_devices) > 1 and options.wait_for_debugger:
105 logging.warning('Debugger can not be sharded, '
106 'using first available device')
107 attached_devices = attached_devices[:1]
108 logging.debug('Running Python tests')
109 sharder = PythonTestSharder(attached_devices, available_tests, options)
110 test_results = sharder.RunShardedTests()
111
112 if not test_results.DidRunPass():
113 return (test_results, 1)
114
115 return (test_results, 0)
116
117
118 def _GetTestModules(python_test_root, is_official_build): 51 def _GetTestModules(python_test_root, is_official_build):
119 """Retrieve a sorted list of pythonDrivenTests. 52 """Retrieve a sorted list of pythonDrivenTests.
120 53
121 Walks the location of pythonDrivenTests, imports them, and provides the list 54 Walks the location of pythonDrivenTests, imports them, and provides the list
122 of imported modules to the caller. 55 of imported modules to the caller.
123 56
124 Args: 57 Args:
125 python_test_root: the path to walk, looking for pythonDrivenTests 58 python_test_root: the path to walk, looking for pythonDrivenTests
126 is_official_build: whether to run only those tests marked 'official' 59 is_official_build: whether to run only those tests marked 'official'
127 60
(...skipping 30 matching lines...) Expand all
158 91
159 def _GetTestsFromClass(test_class): 92 def _GetTestsFromClass(test_class):
160 """Create a list of test objects for each test method on this class. 93 """Create a list of test objects for each test method on this class.
161 94
162 Test methods are methods on the class which begin with 'test'. 95 Test methods are methods on the class which begin with 'test'.
163 96
164 Args: 97 Args:
165 test_class: class object which contains zero or more test methods. 98 test_class: class object which contains zero or more test methods.
166 99
167 Returns: 100 Returns:
168 A list of test objects, each of which is bound to one test. 101 A list of partially applied constructor, each one for a particular test
102 name. To get the test objects from this, call the partial constructors
103 with any remaining arguments.
169 """ 104 """
170 test_names = [m for m in dir(test_class) 105 test_names = [m for m in dir(test_class)
171 if _IsTestMethod(m, test_class)] 106 if _IsTestMethod(m, test_class)]
172 return map(test_class, test_names) 107 return [functools.partial(test_class, name) for name in test_names]
173 108
174 109
175 def _GetTestClassesFromModule(test_module): 110 def _GetTestClassesFromModule(test_module, base_class):
111 """Get all test classes from |test_module|."""
112
176 tests = [] 113 tests = []
177 for name in dir(test_module): 114 for name in dir(test_module):
178 attr = getattr(test_module, name) 115 attr = getattr(test_module, name)
179 if _IsTestClass(attr): 116 if _IsTestClass(attr, base_class):
180 tests.extend(_GetTestsFromClass(attr)) 117 tests.extend(_GetTestsFromClass(attr))
181 return tests 118 return tests
182 119
183 120
184 def _IsTestClass(test_class): 121 def _IsTestClass(test_class, base_class):
185 return (type(test_class) is types.TypeType and 122 return (type(test_class) is types.TypeType and
186 issubclass(test_class, python_test_base.PythonTestBase) and 123 issubclass(test_class, base_class) and
187 test_class is not python_test_base.PythonTestBase) 124 test_class is not base_class)
188 125
189 126
190 def _IsTestMethod(attrname, test_case_class): 127 def _IsTestMethod(attrname, test_case_class):
191 """Checks whether this is a valid test method. 128 """Checks whether this is a valid test method.
192 129
193 Args: 130 Args:
194 attrname: the method name. 131 attrname: the method name.
195 test_case_class: the test case class. 132 test_case_class: the test case class.
196 133
197 Returns: 134 Returns:
198 True if test_case_class.'attrname' is callable and it starts with 'test'; 135 True if test_case_class.'attrname' is callable and it starts with 'test';
199 False otherwise. 136 False otherwise.
200 """ 137 """
201 attr = getattr(test_case_class, attrname) 138 attr = getattr(test_case_class, attrname)
202 return callable(attr) and attrname.startswith('test') 139 return callable(attr) and attrname.startswith('test')
203 140
204 141
205 def _GetAllTests(test_root, is_official_build): 142 def _GetAllTests(test_root, is_official_build, base_class):
206 """Retrieve a list of Python test modules and their respective methods. 143 """Retrieve a list of Python test modules and their respective methods.
207 144
208 Args: 145 Args:
209 test_root: path which contains Python-driven test files 146 test_root: Path which contains Python-driven test files
210 is_official_build: whether this is an official build 147 is_official_build: Whether this is an official build
148 base_class: Base class that all tests should derive from
211 149
212 Returns: 150 Returns:
213 List of test case objects for all available test methods. 151 List of test case objects for all available test methods.
214 """ 152 """
215 if not test_root: 153 if not test_root:
216 return [] 154 return []
217 all_tests = [] 155 all_tests = []
218 test_module_list = _GetTestModules(test_root, is_official_build) 156 test_module_list = _GetTestModules(test_root, is_official_build)
219 for module in test_module_list: 157 for module in test_module_list:
220 all_tests.extend(_GetTestClassesFromModule(module)) 158 all_tests.extend(_GetTestClassesFromModule(module, base_class))
221 return all_tests 159 return all_tests
160
161
162 def InstrumentationSetup(python_test_root, official_build, annotations,
bulach 2013/07/23 17:27:52 as above, Setup is an incredibly overloaded term i
gkanwar1 2013/07/23 18:38:55 This is named setup.py to match the recent shardin
163 exclude_annotations, test_filter, tool, build_type,
164 push_deps, cleanup_test_files, test_apk_path,
165 test_apk_jar_path, test_data, install_apk,
166 save_perf_json, screenshot_failures,
167 wait_for_debugger, disable_assertions):
168 """Creates test set of python tests and test runner factory.
169
170 Args:
171 python_test_root: Directory where the Python tests are.
172 official_build: True if this is an official build.
173 annotations: Annotations for the tests.
174 exclude_annotations: Any annotations to exclude from running.
175 test_filter: Filter string for tests.
176 tool: Name of the Valgrind tool.
177 build_type: 'Release' or 'Debug'.
178 push_deps: If True, push all dependencies to the device.
179 cleanup_test_files: If True, cleanup test files on device.
180 test_apk_path: Path to the test apk file.
181 test_apk_jar_path: Path to the accompanying jar file.
182 test_data: Location of the test data.
183 install_apk: Re-installs the apk if opted.
184 save_perf_json: Whether or not to save the JSON file from UI perf tests.
185 screenshot_failures: Take a screenshot for a test failure
186 wait_for_debugger: Blocks until the debugger is connected.
187 disable_assertions: Whether to disable java assertions on the device.
188
189 Returns:
190 A tuple of (TestRunnerFactory, tests).
191 """
192
193 test_collection = test_info_collection.TestInfoCollection()
194 all_test_constructors = _GetAllTests(
195 python_test_root, official_build,
196 instrumentation_test_base.InstrumentationPythonTestBase)
197 all_tests = [constructor(test_apk_path, test_apk_jar_path, test_data,
198 install_apk, save_perf_json, screenshot_failures,
199 tool, wait_for_debugger, disable_assertions)
200 for constructor in all_test_constructors]
201 test_collection.AddTests(all_tests)
202 test_names = [t.qualified_name for t in all_tests]
203 logging.debug('All available tests: ' + str(test_names))
204
205 available_tests = test_collection.GetAvailableTests(
206 annotations, exclude_annotations, test_filter)
207
208 def TestRunnerFactory(device, shard_index):
209 return test_runner.PythonTestRunner(
210 device, shard_index, tool, build_type, push_deps, cleanup_test_files)
211
212 return (TestRunnerFactory, available_tests)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698