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/python_test_base.py

Issue 12544033: [Android] Rewrite base test result classes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 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 | Annotate | Revision Log
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 Android Python-driven tests.
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 Python-driven
8 tests. It is similar to the Python unitttest module in that the user's tests 8 tests. It is similar to the Python unitttest module in that the user's tests
9 inherit from this case and add their tests in that case. 9 inherit from this case and add their tests in that case.
10 10
11 When a PythonTestBase object is instantiated, its purpose is to run only one of 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 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 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, 14 run against. The runner runs the test method itself, collecting the result,
15 and calls TearDown. 15 and calls TearDown.
16 16
17 Tests can basically do whatever they want in the test methods, such as call 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 18 Java tests using _RunJavaTests. Those methods have the advantage of massaging
19 the Java test results into Python test results. 19 the Java test results into Python test results.
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.test_result import SingleTestResult, TestResults 27 from pylib.base import base_test_result
28 from pylib.instrumentation import test_package 28 from pylib.instrumentation import test_package
29 from pylib.instrumentation import test_result
29 from pylib.instrumentation import test_runner 30 from pylib.instrumentation import test_runner
30 31
31 32
32 # aka the parent of com.google.android 33 # aka the parent of com.google.android
33 BASE_ROOT = 'src' + os.sep 34 BASE_ROOT = 'src' + os.sep
34 35
35 36
36 class PythonTestBase(object): 37 class PythonTestBase(object):
37 """Base class for Python-driven tests.""" 38 """Base class for Python-driven tests."""
38 39
(...skipping 26 matching lines...) Expand all
65 66
66 def _RunJavaTest(self, fname, suite, test): 67 def _RunJavaTest(self, fname, suite, test):
67 """Runs a single Java test with a Java TestRunner. 68 """Runs a single Java test with a Java TestRunner.
68 69
69 Args: 70 Args:
70 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py) 71 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py)
71 suite: name of the Java test suite (e.g. FooTest) 72 suite: name of the Java test suite (e.g. FooTest)
72 test: name of the test method to run (e.g. testFooBar) 73 test: name of the test method to run (e.g. testFooBar)
73 74
74 Returns: 75 Returns:
75 TestResults object with a single test result. 76 TestRunResults object with a single test result.
76 """ 77 """
77 test = self._ComposeFullTestName(fname, suite, test) 78 test = self._ComposeFullTestName(fname, suite, test)
78 test_pkg = test_package.TestPackage( 79 test_pkg = test_package.TestPackage(
79 self.options.test_apk_path, self.options.test_apk_jar_path) 80 self.options.test_apk_path, self.options.test_apk_jar_path)
80 java_test_runner = test_runner.TestRunner(self.options, self.device_id, 81 java_test_runner = test_runner.TestRunner(self.options, self.device_id,
81 self.shard_index, False, 82 self.shard_index, False,
82 test_pkg, 83 test_pkg,
83 self.ports_to_forward) 84 self.ports_to_forward)
84 try: 85 try:
85 java_test_runner.SetUp() 86 java_test_runner.SetUp()
86 return java_test_runner.RunTest(test)[0] 87 return java_test_runner.RunTest(test)[0]
87 finally: 88 finally:
88 java_test_runner.TearDown() 89 java_test_runner.TearDown()
89 90
90 def _RunJavaTests(self, fname, tests): 91 def _RunJavaTests(self, fname, tests):
91 """Calls a list of tests and stops at the first test failure. 92 """Calls a list of tests and stops at the first test failure.
92 93
93 This method iterates until either it encounters a non-passing test or it 94 This method iterates until either it encounters a non-passing test or it
94 exhausts the list of tests. Then it returns the appropriate Python result. 95 exhausts the list of tests. Then it returns the appropriate Python result.
95 96
96 Args: 97 Args:
97 fname: filename for the Python test 98 fname: filename for the Python test
98 tests: a list of Java test names which will be run 99 tests: a list of Java test names which will be run
99 100
100 Returns: 101 Returns:
101 A TestResults object containing a result for this Python test. 102 A TestRunResults object containing a result for this Python test.
102 """ 103 """
104 test_type = base_test_result.ResultType.PASS
105 log = ''
106
103 start_ms = int(time.time()) * 1000 107 start_ms = int(time.time()) * 1000
104
105 result = None
106 for test in tests: 108 for test in tests:
107 # We're only running one test at a time, so this TestResults object will 109 # We're only running one test at a time, so this TestRunResults object
108 # hold only one result. 110 # will hold only one result.
109 suite, test_name = test.split('.') 111 suite, test_name = test.split('.')
110 result = self._RunJavaTest(fname, suite, test_name) 112 java_results = self._RunJavaTest(fname, suite, test_name)
111 # A non-empty list means the test did not pass. 113 assert len(java_results.GetAll()) == 1
112 if result.GetAllBroken(): 114 if not java_results.DidRunPass():
115 result = java_results.GetNotPass().pop()
116 log = result.GetLog()
117 test_type = result.GetType()
113 break 118 break
114
115 duration_ms = int(time.time()) * 1000 - start_ms 119 duration_ms = int(time.time()) * 1000 - start_ms
116 120
117 # Do something with result. 121 python_results = base_test_result.TestRunResults()
118 return self._ProcessResults(result, start_ms, duration_ms) 122 python_results.AddResult(
119 123 test_result.InstrumentationTestResult(
120 def _ProcessResults(self, result, start_ms, duration_ms): 124 self.qualified_name, test_type, start_ms, duration_ms, log=log))
121 """Translates a Java test result into a Python result for this test. 125 return python_results
122
123 The TestRunner class that we use under the covers will return a test result
124 for that specific Java test. However, to make reporting clearer, we have
125 this method to abstract that detail and instead report that as a failure of
126 this particular test case while still including the Java stack trace.
127
128 Args:
129 result: TestResults with a single Java test result
130 start_ms: the time the test started
131 duration_ms: the length of the test
132
133 Returns:
134 A TestResults object containing a result for this Python test.
135 """
136 test_results = TestResults()
137
138 # If our test is in broken, then it crashed/failed.
139 broken = result.GetAllBroken()
140 if broken:
141 # Since we have run only one test, take the first and only item.
142 single_result = broken[0]
143
144 log = single_result.log
145 if not log:
146 log = 'No logging information.'
147
148 python_result = SingleTestResult(self.qualified_name, start_ms,
149 duration_ms,
150 log)
151
152 # Figure out where the test belonged. There's probably a cleaner way of
153 # doing this.
154 if single_result in result.crashed:
155 test_results.crashed = [python_result]
156 elif single_result in result.failed:
157 test_results.failed = [python_result]
158 elif single_result in result.unknown:
159 test_results.unknown = [python_result]
160
161 else:
162 python_result = SingleTestResult(self.qualified_name, start_ms,
163 duration_ms)
164 test_results.ok = [python_result]
165
166 return test_results
167 126
168 def _ComposeFullTestName(self, fname, suite, test): 127 def _ComposeFullTestName(self, fname, suite, test):
169 package_name = self._GetPackageName(fname) 128 package_name = self._GetPackageName(fname)
170 return package_name + '.' + suite + '#' + test 129 return package_name + '.' + suite + '#' + test
171 130
172 def _GetPackageName(self, fname): 131 def _GetPackageName(self, fname):
173 """Extracts the package name from the test file path.""" 132 """Extracts the package name from the test file path."""
174 dirname = os.path.dirname(fname) 133 dirname = os.path.dirname(fname)
175 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):] 134 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):]
176 return package.replace(os.sep, '.') 135 return package.replace(os.sep, '.')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698