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

Side by Side Diff: build/android/pylib/host_driven/instrumentation_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: Removes uiautomator host-driven interface 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) 2013 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 instrumentation tests.
6 6
7 This test case is intended to serve as the base class for any Python-driven 7 This test case serves as the base class for any host-driven instrumentation
8 tests. It is similar to the Python unitttest module in that the user's tests 8 tests. Each test method in the derived class can call _RunJavaTests to run
9 inherit from this case and add their tests in that case. 9 instrumentation tests on the corresponding device via an instrumentation test
10 10 runner.
11 When a PythonTestBase object is instantiated, its purpose is to run only one of
12 its tests. The test runner gives it the name of the test the instance will
13 run. The test runner calls SetUp with the Android device ID which the test will
14 run against. The runner runs the test method itself, collecting the result,
15 and calls TearDown.
16
17 Tests can basically do whatever they want in the test methods, such as call
18 Java tests using _RunJavaTests. Those methods have the advantage of massaging
19 the Java test results into Python test results.
20 """ 11 """
21 12
22 import logging
23 import os 13 import os
24 import time 14 import time
25 15
26 from pylib import android_commands
27 from pylib.base import base_test_result 16 from pylib.base import base_test_result
28 from pylib.instrumentation import test_package 17 from pylib.instrumentation import test_package
29 from pylib.instrumentation import test_result 18 from pylib.instrumentation import test_result
30 from pylib.instrumentation import test_runner 19 from pylib.instrumentation import test_runner
31 20
21 import test_case
32 22
33 # aka the parent of com.google.android 23 # aka the parent of com.google.android
34 BASE_ROOT = 'src' + os.sep 24 BASE_ROOT = 'src' + os.sep
35 25
36 26
37 class PythonTestBase(object): 27 class InstrumentationHostDrivenTestCase(test_case.HostDrivenTestCase):
bulach 2013/07/29 09:30:58 I'm still a bit concerned about making mixing up "
38 """Base class for Python-driven tests.""" 28 """Base class for host-driven instrumentation test cases.
39 29
40 def __init__(self, test_name): 30 Raises:
41 # test_name must match one of the test methods defined on a subclass which 31 WaitForResponseTimedOutError: If timeout occurred while waiting for
42 # inherits from this class. 32 response to adb instrument command.
43 # It's stored so we can do the attr lookup on demand, allowing this class 33 DeviceUnresponsiveError: If device system process is not responding.
44 # to be pickled, a requirement for the multiprocessing module. 34 InstrumentationError: If instrumentation failed to run.
45 self.test_name = test_name 35 """
46 class_name = self.__class__.__name__
47 self.qualified_name = class_name + '.' + self.test_name
48 36
49 def SetUp(self, options): 37 def __init__(self, test_name, test_apk_path, test_apk_jar_path,
50 self.options = options 38 test_data, install_apk, save_perf_json, screenshot_failures,
51 self.shard_index = self.options.shard_index 39 tool, wait_for_debugger, disable_assertions):
52 self.device_id = self.options.device_id 40 """Create an InstrumentationHostDrivenTestCase object.
53 self.adb = android_commands.AndroidCommands(self.device_id)
54 self.ports_to_forward = []
55
56 def TearDown(self):
57 pass
58
59 def GetOutDir(self):
60 return os.path.join(os.environ['CHROME_SRC'], 'out',
61 self.options.build_type)
62
63 def Run(self):
64 logging.warning('Running Python-driven test: %s', self.test_name)
65 return getattr(self, self.test_name)()
66
67 def _RunJavaTest(self, fname, suite, test):
68 """Runs a single Java test with a Java TestRunner.
69 41
70 Args: 42 Args:
71 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py) 43 test_name: The name of the method to run as the test.
72 suite: name of the Java test suite (e.g. FooTest) 44 test_apk_path: Path to the test apk file.
73 test: name of the test method to run (e.g. testFooBar) 45 test_apk_jar_path: Path to the accompanying jar file.
46 other args: All passed to the instrumentation test runner constructor in
47 _RunJavaTest. See the test runner docs for details.
48 """
49
50 super(InstrumentationHostDrivenTestCase, self).__init__(test_name)
51 self.test_apk_path = test_apk_path
52 self.test_apk_jar_path = test_apk_jar_path
53 self.test_data = test_data
54 self.install_apk = install_apk
55 self.save_perf_json = save_perf_json
56 self.screenshot_failures = screenshot_failures
57 self.wait_for_debugger = wait_for_debugger
58 self.tool = tool
59 self.disable_assertions = disable_assertions
60
61 def _RunJavaTest(self, fname, test_case, test_method):
62 """Runs a single Java test method with a Java TestRunner.
63
64 Args:
65 fname: Filename for the host-driven test case
66 (e.g. foo/bar/baz/tests/FooTest.py)
67 test_case: Name of the Java test case (e.g. FooTest)
68 test_method: Name of the test method to run (e.g. testFooBar)
74 69
75 Returns: 70 Returns:
76 TestRunResults object with a single test result. 71 TestRunResults object with a single test result.
77 """ 72 """
78 test = self._ComposeFullTestName(fname, suite, test) 73 test = self._ComposeFullTestName(fname, test_case, test_method)
79 test_pkg = test_package.TestPackage( 74 test_pkg = test_package.TestPackage(
80 self.options.test_apk_path, self.options.test_apk_jar_path) 75 self.test_apk_path, self.test_apk_jar_path)
81 java_test_runner = test_runner.TestRunner(self.options.build_type, 76 java_test_runner = test_runner.TestRunner(self.build_type,
82 self.options.test_data, 77 self.test_data,
83 self.options.install_apk, 78 self.install_apk,
84 self.options.save_perf_json, 79 self.save_perf_json,
85 self.options.screenshot_failures, 80 self.screenshot_failures,
86 self.options.tool, 81 self.tool,
87 self.options.wait_for_debugger, 82 self.wait_for_debugger,
88 self.options.disable_assertions, 83 self.disable_assertions,
89 self.options.push_deps, 84 self.push_deps,
90 self.options.cleanup_test_files, 85 self.cleanup_test_files,
91 self.device_id, 86 self.device_id,
92 self.shard_index, test_pkg, 87 self.shard_index, test_pkg, [])
93 self.ports_to_forward)
94 try: 88 try:
95 java_test_runner.SetUp() 89 java_test_runner.SetUp()
96 return java_test_runner.RunTest(test)[0] 90 return java_test_runner.RunTest(test)[0]
97 finally: 91 finally:
98 java_test_runner.TearDown() 92 java_test_runner.TearDown()
99 93
100 def _RunJavaTests(self, fname, tests): 94 def _RunJavaTests(self, fname, tests):
101 """Calls a list of tests and stops at the first test failure. 95 """Calls a list of tests and stops at the first test failure.
102 96
103 This method iterates until either it encounters a non-passing test or it 97 This method iterates until either it encounters a non-passing test or it
104 exhausts the list of tests. Then it returns the appropriate Python result. 98 exhausts the list of tests. Then it returns the appropriate overall result.
105 99
106 Args: 100 Args:
107 fname: filename for the Python test 101 fname: Filename for the host-driven test case
108 tests: a list of Java test names which will be run 102 tests: A list of Java test names which will be run
109 103
110 Returns: 104 Returns:
111 A TestRunResults object containing a result for this Python test. 105 A TestRunResults object containing an overall result for this set of Java
106 tests. If any Java tests do not pass, this is a fail overall.
112 """ 107 """
113 test_type = base_test_result.ResultType.PASS 108 test_type = base_test_result.ResultType.PASS
114 log = '' 109 log = ''
115 110
116 start_ms = int(time.time()) * 1000 111 start_ms = int(time.time()) * 1000
117 for test in tests: 112 for test in tests:
118 # We're only running one test at a time, so this TestRunResults object 113 # We're only running one test at a time, so this TestRunResults object
119 # will hold only one result. 114 # will hold only one result.
120 suite, test_name = test.split('.') 115 suite, test_name = test.split('.')
121 java_results = self._RunJavaTest(fname, suite, test_name) 116 java_result = self._RunJavaTest(fname, suite, test_name)
122 assert len(java_results.GetAll()) == 1 117 assert len(java_result.GetAll()) == 1
123 if not java_results.DidRunPass(): 118 if not java_result.DidRunPass():
124 result = java_results.GetNotPass().pop() 119 result = java_result.GetNotPass().pop()
125 log = result.GetLog() 120 log = result.GetLog()
126 test_type = result.GetType() 121 test_type = result.GetType()
127 break 122 break
128 duration_ms = int(time.time()) * 1000 - start_ms 123 duration_ms = int(time.time()) * 1000 - start_ms
129 124
130 python_results = base_test_result.TestRunResults() 125 overall_result = base_test_result.TestRunResults()
131 python_results.AddResult( 126 overall_result.AddResult(
132 test_result.InstrumentationTestResult( 127 test_result.InstrumentationTestResult(
133 self.qualified_name, test_type, start_ms, duration_ms, log=log)) 128 self.tagged_name, test_type, start_ms, duration_ms, log=log))
134 return python_results 129 return overall_result
135 130
136 def _ComposeFullTestName(self, fname, suite, test): 131 def _ComposeFullTestName(self, fname, test_case, test_method):
137 package_name = self._GetPackageName(fname) 132 """Composes a fully-qualified name for the test method.
138 return package_name + '.' + suite + '#' + test
139 133
140 def _GetPackageName(self, fname): 134 Args:
141 """Extracts the package name from the test file path.""" 135 fname: Filename for the host-driven test case
136 test_case: Name of the Java test case (e.g. FooTest)
137 test_method: Name of the test method to run (e.g. testFooBar)
138
139 Returns:
140 The fully qualified name for the test method on the Java test case.
141
142 Example:
143 _ComposeFullTestName('/src/foo/tests/FooTest.py', 'FooTest',
144 'testFooBar') => 'foo.tests.FooTest#testFooBar'
145 """
142 dirname = os.path.dirname(fname) 146 dirname = os.path.dirname(fname)
143 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):] 147 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):]
144 return package.replace(os.sep, '.') 148 package_name = package.replace(os.sep, '.')
149 return package_name + '.' + test_case + '#' + test_method
OLDNEW
« no previous file with comments | « build/android/buildbot/bb_device_steps.py ('k') | build/android/pylib/host_driven/java_unittest_utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698