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

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: Fixes naming scheme to match unittest naming, adds exception handling to host-driven test_runner 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) 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 test cases which intend
8 tests. It is similar to the Python unitttest module in that the user's tests 8 to run instrumentation tests. It provides a constructor which accepts
9 inherit from this case and add their tests in that case. 9 the relevant options and stores them in object variables.
10
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 """ 10 """
21 11
22 import logging
23 import os 12 import os
24 import time 13 import time
25 14
26 from pylib import android_commands
27 from pylib.base import base_test_result 15 from pylib.base import base_test_result
28 from pylib.instrumentation import test_package 16 from pylib.instrumentation import test_package
29 from pylib.instrumentation import test_result 17 from pylib.instrumentation import test_result
30 from pylib.instrumentation import test_runner 18 from pylib.instrumentation import test_runner
31 19
20 import test_case
32 21
33 # aka the parent of com.google.android 22 # aka the parent of com.google.android
34 BASE_ROOT = 'src' + os.sep 23 BASE_ROOT = 'src' + os.sep
35 24
36 25
37 class PythonTestBase(object): 26 class InstrumentationHostDrivenTestCase(test_case.HostDrivenTestCase):
38 """Base class for Python-driven tests.""" 27 """Base class for host-driven instrumentation tests.
39 28
40 def __init__(self, test_name): 29 Args:
41 # test_name must match one of the test methods defined on a subclass which 30 test_name: The name of the method to run as the test.
42 # inherits from this class. 31 test_apk_path: Path to the test apk file.
43 # It's stored so we can do the attr lookup on demand, allowing this class 32 test_apk_jar_path: Path to the accompanying jar file.
44 # to be pickled, a requirement for the multiprocessing module. 33 other args: All passed through to the instrumentation test runner. See the
45 self.test_name = test_name 34 test runner docs for details.
46 class_name = self.__class__.__name__ 35 """
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 super(InstrumentationHostDrivenTestCase, self).__init__(test_name)
53 self.adb = android_commands.AndroidCommands(self.device_id) 41 self.test_apk_path = test_apk_path
54 self.ports_to_forward = [] 42 self.test_apk_jar_path = test_apk_jar_path
55 43 self.test_data = test_data
56 def TearDown(self): 44 self.install_apk = install_apk
57 pass 45 self.save_perf_json = save_perf_json
58 46 self.screenshot_failures = screenshot_failures
59 def GetOutDir(self): 47 self.wait_for_debugger = wait_for_debugger
60 return os.path.join(os.environ['CHROME_SRC'], 'out', 48 self.tool = tool
61 self.options.build_type) 49 self.disable_assertions = disable_assertions
62
63 def Run(self):
64 logging.warning('Running Python-driven test: %s', self.test_name)
65 return getattr(self, self.test_name)()
66 50
67 def _RunJavaTest(self, fname, suite, test): 51 def _RunJavaTest(self, fname, suite, test):
68 """Runs a single Java test with a Java TestRunner. 52 """Runs a single Java test with a Java TestRunner.
69 53
70 Args: 54 Args:
71 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py) 55 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py)
72 suite: name of the Java test suite (e.g. FooTest) 56 suite: name of the Java test suite (e.g. FooTest)
73 test: name of the test method to run (e.g. testFooBar) 57 test: name of the test method to run (e.g. testFooBar)
74 58
75 Returns: 59 Returns:
76 TestRunResults object with a single test result. 60 TestRunResults object with a single test result.
77 """ 61 """
78 test = self._ComposeFullTestName(fname, suite, test) 62 test = self._ComposeFullTestName(fname, suite, test)
79 test_pkg = test_package.TestPackage( 63 test_pkg = test_package.TestPackage(
80 self.options.test_apk_path, self.options.test_apk_jar_path) 64 self.test_apk_path, self.test_apk_jar_path)
81 java_test_runner = test_runner.TestRunner(self.options.build_type, 65 java_test_runner = test_runner.TestRunner(self.build_type,
82 self.options.test_data, 66 self.test_data,
83 self.options.install_apk, 67 self.install_apk,
84 self.options.save_perf_json, 68 self.save_perf_json,
85 self.options.screenshot_failures, 69 self.screenshot_failures,
86 self.options.tool, 70 self.tool,
87 self.options.wait_for_debugger, 71 self.wait_for_debugger,
88 self.options.disable_assertions, 72 self.disable_assertions,
89 self.options.push_deps, 73 self.push_deps,
90 self.options.cleanup_test_files, 74 self.cleanup_test_files,
91 self.device_id, 75 self.device_id,
92 self.shard_index, test_pkg, 76 self.shard_index, test_pkg, [])
93 self.ports_to_forward)
94 try: 77 try:
95 java_test_runner.SetUp() 78 java_test_runner.SetUp()
96 return java_test_runner.RunTest(test)[0] 79 return java_test_runner.RunTest(test)[0]
97 finally: 80 finally:
98 java_test_runner.TearDown() 81 java_test_runner.TearDown()
99 82
100 def _RunJavaTests(self, fname, tests): 83 def _RunJavaTests(self, fname, tests):
101 """Calls a list of tests and stops at the first test failure. 84 """Calls a list of tests and stops at the first test failure.
102 85
103 This method iterates until either it encounters a non-passing test or it 86 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. 87 exhausts the list of tests. Then it returns the appropriate overall result.
105 88
106 Args: 89 Args:
107 fname: filename for the Python test 90 fname: filename for the host-driven test
108 tests: a list of Java test names which will be run 91 tests: a list of Java test names which will be run
109 92
110 Returns: 93 Returns:
111 A TestRunResults object containing a result for this Python test. 94 A TestRunResults object containing a result for this host-driven test.
frankf 2013/07/24 23:33:43 This is not accurate. A host-driven test can make
gkanwar1 2013/07/25 00:27:55 Done.
112 """ 95 """
113 test_type = base_test_result.ResultType.PASS 96 test_type = base_test_result.ResultType.PASS
114 log = '' 97 log = ''
115 98
116 start_ms = int(time.time()) * 1000 99 start_ms = int(time.time()) * 1000
117 for test in tests: 100 for test in tests:
118 # We're only running one test at a time, so this TestRunResults object 101 # We're only running one test at a time, so this TestRunResults object
119 # will hold only one result. 102 # will hold only one result.
120 suite, test_name = test.split('.') 103 suite, test_name = test.split('.')
121 java_results = self._RunJavaTest(fname, suite, test_name) 104 java_results = self._RunJavaTest(fname, suite, test_name)
frankf 2013/07/24 23:33:43 this should be singular
gkanwar1 2013/07/25 00:27:55 Done.
122 assert len(java_results.GetAll()) == 1 105 assert len(java_results.GetAll()) == 1
123 if not java_results.DidRunPass(): 106 if not java_results.DidRunPass():
124 result = java_results.GetNotPass().pop() 107 result = java_results.GetNotPass().pop()
125 log = result.GetLog() 108 log = result.GetLog()
126 test_type = result.GetType() 109 test_type = result.GetType()
127 break 110 break
128 duration_ms = int(time.time()) * 1000 - start_ms 111 duration_ms = int(time.time()) * 1000 - start_ms
129 112
130 python_results = base_test_result.TestRunResults() 113 overall_result = base_test_result.TestRunResults()
131 python_results.AddResult( 114 overall_result.AddResult(
132 test_result.InstrumentationTestResult( 115 test_result.InstrumentationTestResult(
133 self.qualified_name, test_type, start_ms, duration_ms, log=log)) 116 self.qualified_name, test_type, start_ms, duration_ms, log=log))
134 return python_results 117 return overall_result
135 118
136 def _ComposeFullTestName(self, fname, suite, test): 119 def _ComposeFullTestName(self, fname, suite, test):
137 package_name = self._GetPackageName(fname) 120 package_name = self._GetPackageName(fname)
138 return package_name + '.' + suite + '#' + test 121 return package_name + '.' + suite + '#' + test
139 122
140 def _GetPackageName(self, fname): 123 def _GetPackageName(self, fname):
frankf 2013/07/24 23:33:43 If the above two methods are not reused, combine t
gkanwar1 2013/07/25 00:27:55 Done, but with suite -> test_case instead, since c
141 """Extracts the package name from the test file path.""" 124 """Extracts the package name from the test file path."""
142 dirname = os.path.dirname(fname) 125 dirname = os.path.dirname(fname)
143 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):] 126 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):]
144 return package.replace(os.sep, '.') 127 return package.replace(os.sep, '.')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698