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

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: 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) 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 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 host-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.
frankf 2013/07/24 23:33:43 Use more precise language. A "test" in this contex
gkanwar1 2013/07/25 00:27:55 Done.
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 of 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 device ID which the test will run
14 run against. The runner runs the test method itself, collecting the result, 14 against. The runner runs the test method itself, collecting the result, and
15 and calls TearDown. 15 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 """ 16 """
21 17
22 import logging 18 import logging
23 import os
24 import time
25 19
26 from pylib import android_commands 20 from pylib import android_commands
27 from pylib.base import base_test_result
28 from pylib.instrumentation import test_package
29 from pylib.instrumentation import test_result
30 from pylib.instrumentation import test_runner
31 21
32 22
33 # aka the parent of com.google.android 23 class HostDrivenTestCase(object):
34 BASE_ROOT = 'src' + os.sep 24 """Base class for host-driven tests."""
35
36
37 class PythonTestBase(object):
38 """Base class for Python-driven tests."""
39 25
40 def __init__(self, test_name): 26 def __init__(self, test_name):
41 # test_name must match one of the test methods defined on a subclass which 27 # test_name must match one of the test methods defined on a subclass which
42 # inherits from this class. 28 # inherits from this class.
43 # It's stored so we can do the attr lookup on demand, allowing this class
44 # to be pickled, a requirement for the multiprocessing module.
45 self.test_name = test_name 29 self.test_name = test_name
46 class_name = self.__class__.__name__ 30 class_name = self.__class__.__name__
47 self.qualified_name = class_name + '.' + self.test_name 31 self.qualified_name = class_name + '.' + self.test_name
48 32
49 def SetUp(self, options): 33 def SetUp(self, device, shard_index, build_type, push_deps,
50 self.options = options 34 cleanup_test_files):
51 self.shard_index = self.options.shard_index 35 self.device_id = device
52 self.device_id = self.options.device_id 36 self.shard_index = shard_index
37 self.build_type = build_type
53 self.adb = android_commands.AndroidCommands(self.device_id) 38 self.adb = android_commands.AndroidCommands(self.device_id)
54 self.ports_to_forward = [] 39 self.push_deps = push_deps
40 self.cleanup_test_files = cleanup_test_files
55 41
56 def TearDown(self): 42 def TearDown(self):
57 pass 43 pass
58 44
59 def GetOutDir(self): 45 def GetOutDir(self):
60 return os.path.join(os.environ['CHROME_SRC'], 'out', 46 return os.path.join(os.environ['CHROME_SRC'], 'out',
61 self.options.build_type) 47 self.build_type)
62 48
63 def Run(self): 49 def Run(self):
64 logging.warning('Running Python-driven test: %s', self.test_name) 50 logging.info('Running host-driven test: %s', self.test_name)
65 return getattr(self, self.test_name)() 51 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
70 Args:
71 fname: filename for the test (e.g. foo/bar/baz/tests/FooTest.py)
72 suite: name of the Java test suite (e.g. FooTest)
73 test: name of the test method to run (e.g. testFooBar)
74
75 Returns:
76 TestRunResults object with a single test result.
77 """
78 test = self._ComposeFullTestName(fname, suite, test)
79 test_pkg = test_package.TestPackage(
80 self.options.test_apk_path, self.options.test_apk_jar_path)
81 java_test_runner = test_runner.TestRunner(self.options.build_type,
82 self.options.test_data,
83 self.options.install_apk,
84 self.options.save_perf_json,
85 self.options.screenshot_failures,
86 self.options.tool,
87 self.options.wait_for_debugger,
88 self.options.disable_assertions,
89 self.options.push_deps,
90 self.options.cleanup_test_files,
91 self.device_id,
92 self.shard_index, test_pkg,
93 self.ports_to_forward)
94 try:
95 java_test_runner.SetUp()
96 return java_test_runner.RunTest(test)[0]
97 finally:
98 java_test_runner.TearDown()
99
100 def _RunJavaTests(self, fname, tests):
101 """Calls a list of tests and stops at the first test failure.
102
103 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.
105
106 Args:
107 fname: filename for the Python test
108 tests: a list of Java test names which will be run
109
110 Returns:
111 A TestRunResults object containing a result for this Python test.
112 """
113 test_type = base_test_result.ResultType.PASS
114 log = ''
115
116 start_ms = int(time.time()) * 1000
117 for test in tests:
118 # We're only running one test at a time, so this TestRunResults object
119 # will hold only one result.
120 suite, test_name = test.split('.')
121 java_results = self._RunJavaTest(fname, suite, test_name)
122 assert len(java_results.GetAll()) == 1
123 if not java_results.DidRunPass():
124 result = java_results.GetNotPass().pop()
125 log = result.GetLog()
126 test_type = result.GetType()
127 break
128 duration_ms = int(time.time()) * 1000 - start_ms
129
130 python_results = base_test_result.TestRunResults()
131 python_results.AddResult(
132 test_result.InstrumentationTestResult(
133 self.qualified_name, test_type, start_ms, duration_ms, log=log))
134 return python_results
135
136 def _ComposeFullTestName(self, fname, suite, test):
137 package_name = self._GetPackageName(fname)
138 return package_name + '.' + suite + '#' + test
139
140 def _GetPackageName(self, fname):
141 """Extracts the package name from the test file path."""
142 dirname = os.path.dirname(fname)
143 package = dirname[dirname.rfind(BASE_ROOT) + len(BASE_ROOT):]
144 return package.replace(os.sep, '.')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698