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

Side by Side Diff: build/android/pylib/host_driven/test_case.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: Converts --official-build into a boolean flag Created 7 years, 4 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 """Base class for Android Python-driven tests. 5 """Base class for host-driven test cases.
6 6
7 This test case is intended to serve as the base class for any Python-driven 7 This test case is intended to serve as the base class for any host-driven
8 tests. It is similar to the Python unitttest module in that the user's tests 8 test cases. It is similar to the Python unitttest module in that test cases
9 inherit from this case and add their tests in that case. 9 inherit from this class and add methods which will be run as tests.
10 10
11 When a PythonTestBase object is instantiated, its purpose is to run only one of 11 When a HostDrivenTestCase object is instantiated, its purpose is to run only one
12 its tests. The test runner gives it the name of the test the instance will 12 test method in the derived class. The test runner gives it the name of the test
13 run. The test runner calls SetUp with the Android device ID which the test will 13 method the instance will run. The test runner calls SetUp with the device ID
14 run against. The runner runs the test method itself, collecting the result, 14 which the test method will run against. The test runner runs the test method
15 and calls TearDown. 15 itself, collecting the result, and calls TearDown.
16 16
17 Tests can basically do whatever they want in the test methods, such as call 17 Tests can perform arbitrary Python commands and asserts in test methods. Tests
18 Java tests using _RunJavaTests. Those methods have the advantage of massaging 18 that run instrumentation tests can make use of the _RunJavaTests helper function
19 the Java test results into Python test results. 19 to trigger Java tests and convert results into a single host-driven test result.
20 """ 20 """
21 21
22 import logging 22 import logging
23 import os 23 import os
24 import time 24 import time
25 25
26 from pylib import android_commands 26 from pylib import android_commands
27 from pylib.base import base_test_result 27 from pylib.base import base_test_result
28 from pylib.instrumentation import test_options
29 from pylib.instrumentation import test_package 28 from pylib.instrumentation import test_package
30 from pylib.instrumentation import test_result 29 from pylib.instrumentation import test_result
31 from pylib.instrumentation import test_runner 30 from pylib.instrumentation import test_runner
32 31
33
34 # aka the parent of com.google.android 32 # aka the parent of com.google.android
35 BASE_ROOT = 'src' + os.sep 33 BASE_ROOT = 'src' + os.sep
36 34
37 35
38 class PythonTestBase(object): 36 class HostDrivenTestCase(object):
39 """Base class for Python-driven tests.""" 37 """Base class for host-driven test cases."""
40 38
41 def __init__(self, test_name): 39 _HOST_DRIVEN_TAG = 'HostDriven'
42 # test_name must match one of the test methods defined on a subclass which 40
43 # inherits from this class. 41 def __init__(self, test_name, instrumentation_options=None):
44 # It's stored so we can do the attr lookup on demand, allowing this class 42 """Create a test case initialized to run |test_name|.
45 # to be pickled, a requirement for the multiprocessing module. 43
44 Args:
45 test_name: The name of the method to run as the test.
46 instrumentation_options: An InstrumentationOptions object.
47 """
46 self.test_name = test_name 48 self.test_name = test_name
47 class_name = self.__class__.__name__ 49 class_name = self.__class__.__name__
48 self.qualified_name = class_name + '.' + self.test_name 50 self.qualified_name = '%s.%s' % (class_name, self.test_name)
51 # Use tagged_name when creating results, so that we can identify host-driven
52 # tests in the overall results.
53 self.tagged_name = '%s_%s' % (self._HOST_DRIVEN_TAG, self.qualified_name)
49 54
50 def SetUp(self, options): 55 self.instrumentation_options = instrumentation_options
51 self.options = options 56 self.ports_to_forward = []
52 self.shard_index = self.options.shard_index 57
53 self.device_id = self.options.device_id 58 def SetUp(self, device, shard_index, build_type, push_deps,
59 cleanup_test_files):
60 self.device_id = device
61 self.shard_index = shard_index
62 self.build_type = build_type
54 self.adb = android_commands.AndroidCommands(self.device_id) 63 self.adb = android_commands.AndroidCommands(self.device_id)
55 self.ports_to_forward = [] 64 self.push_deps = push_deps
65 self.cleanup_test_files = cleanup_test_files
56 66
57 def TearDown(self): 67 def TearDown(self):
58 pass 68 pass
59 69
60 def GetOutDir(self): 70 def GetOutDir(self):
61 return os.path.join(os.environ['CHROME_SRC'], 'out', 71 return os.path.join(os.environ['CHROME_SRC'], 'out',
62 self.options.build_type) 72 self.build_type)
63 73
64 def Run(self): 74 def Run(self):
65 logging.warning('Running Python-driven test: %s', self.test_name) 75 logging.info('Running host-driven test: %s', self.tagged_name)
76 # Get the test method on the derived class and execute it
66 return getattr(self, self.test_name)() 77 return getattr(self, self.test_name)()
67 78
68 def _RunJavaTest(self, fname, suite, test): 79 def __RunJavaTest(self, package_name, test_case, test_method):
69 """Runs a single Java test with a Java TestRunner. 80 """Runs a single Java test method with a Java TestRunner.
70 81
71 Args: 82 Args:
72 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py) 83 package_name: Package name in which the java tests live
73 suite: name of the Java test suite (e.g. FooTest) 84 (e.g. foo.bar.baz.tests)
74 test: name of the test method to run (e.g. testFooBar) 85 test_case: Name of the Java test case (e.g. FooTest)
86 test_method: Name of the test method to run (e.g. testFooBar)
75 87
76 Returns: 88 Returns:
77 TestRunResults object with a single test result. 89 TestRunResults object with a single test result.
78 """ 90 """
79 test = self._ComposeFullTestName(fname, suite, test) 91 test = '%s.%s#%s' % (package_name, test_case, test_method)
80 test_pkg = test_package.TestPackage( 92 test_pkg = test_package.TestPackage(
81 self.options.test_apk_path, self.options.test_apk_jar_path) 93 self.instrumentation_options.test_apk_path,
82 instrumentation_options = test_options.InstrumentationOptions( 94 self.instrumentation_options.test_apk_jar_path)
83 self.options.build_type, 95 java_test_runner = test_runner.TestRunner(self.instrumentation_options,
84 self.options.tool,
85 self.options.cleanup_test_files,
86 self.options.push_deps,
87 self.options.annotations,
88 self.options.exclude_annotations,
89 self.options.test_filter,
90 self.options.test_data,
91 self.options.save_perf_json,
92 self.options.screenshot_failures,
93 self.options.disable_assertions,
94 self.options.wait_for_debugger,
95 self.options.test_apk,
96 self.options.test_apk_path,
97 self.options.test_apk_jar_path)
98 java_test_runner = test_runner.TestRunner(instrumentation_options,
99 self.device_id, 96 self.device_id,
100 self.shard_index, test_pkg, 97 self.shard_index, test_pkg,
101 self.ports_to_forward) 98 self.ports_to_forward)
102 try: 99 try:
103 java_test_runner.SetUp() 100 java_test_runner.SetUp()
104 return java_test_runner.RunTest(test)[0] 101 return java_test_runner.RunTest(test)[0]
105 finally: 102 finally:
106 java_test_runner.TearDown() 103 java_test_runner.TearDown()
107 104
108 def _RunJavaTests(self, fname, tests): 105 def _RunJavaTests(self, package_name, tests):
109 """Calls a list of tests and stops at the first test failure. 106 """Calls a list of tests and stops at the first test failure.
110 107
111 This method iterates until either it encounters a non-passing test or it 108 This method iterates until either it encounters a non-passing test or it
112 exhausts the list of tests. Then it returns the appropriate Python result. 109 exhausts the list of tests. Then it returns the appropriate overall result.
110
111 Test cases may make use of this method internally to assist in running
112 instrumentation tests. This function relies on instrumentation_options
113 being defined.
113 114
114 Args: 115 Args:
115 fname: filename for the Python test 116 package_name: Package name in which the java tests live
116 tests: a list of Java test names which will be run 117 (e.g. foo.bar.baz.tests)
118 tests: A list of Java test names which will be run
117 119
118 Returns: 120 Returns:
119 A TestRunResults object containing a result for this Python test. 121 A TestRunResults object containing an overall result for this set of Java
122 tests. If any Java tests do not pass, this is a fail overall.
120 """ 123 """
121 test_type = base_test_result.ResultType.PASS 124 test_type = base_test_result.ResultType.PASS
122 log = '' 125 log = ''
123 126
124 start_ms = int(time.time()) * 1000 127 start_ms = int(time.time()) * 1000
125 for test in tests: 128 for test in tests:
126 # We're only running one test at a time, so this TestRunResults object 129 # We're only running one test at a time, so this TestRunResults object
127 # will hold only one result. 130 # will hold only one result.
128 suite, test_name = test.split('.') 131 suite, test_name = test.split('.')
129 java_results = self._RunJavaTest(fname, suite, test_name) 132 java_result = self.__RunJavaTest(package_name, suite, test_name)
130 assert len(java_results.GetAll()) == 1 133 assert len(java_result.GetAll()) == 1
131 if not java_results.DidRunPass(): 134 if not java_result.DidRunPass():
132 result = java_results.GetNotPass().pop() 135 result = java_result.GetNotPass().pop()
133 log = result.GetLog() 136 log = result.GetLog()
134 test_type = result.GetType() 137 test_type = result.GetType()
135 break 138 break
136 duration_ms = int(time.time()) * 1000 - start_ms 139 duration_ms = int(time.time()) * 1000 - start_ms
137 140
138 python_results = base_test_result.TestRunResults() 141 overall_result = base_test_result.TestRunResults()
139 python_results.AddResult( 142 overall_result.AddResult(
140 test_result.InstrumentationTestResult( 143 test_result.InstrumentationTestResult(
141 self.qualified_name, test_type, start_ms, duration_ms, log=log)) 144 self.tagged_name, test_type, start_ms, duration_ms, log=log))
142 return python_results 145 return overall_result
143 146
144 def _ComposeFullTestName(self, fname, suite, test): 147 def __str__(self):
145 package_name = self._GetPackageName(fname) 148 return self.tagged_name
146 return package_name + '.' + suite + '#' + test
147 149
148 def _GetPackageName(self, fname): 150 def __repr__(self):
149 """Extracts the package name from the test file path.""" 151 return self.tagged_name
150 dirname = os.path.dirname(fname)
151 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):]
152 return package.replace(os.sep, '.')
OLDNEW
« no previous file with comments | « build/android/pylib/host_driven/setup.py ('k') | build/android/pylib/host_driven/test_info_collection.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698