1 #!/usr/bin/python2.4 2 # 3 # 4 # Copyright 2008, The Android Open Source Project 5 # 6 # Licensed under the Apache License, Version 2.0 (the "License"); 7 # you may not use this file except in compliance with the License. 8 # You may obtain a copy of the License at 9 # 10 # http://www.apache.org/licenses/LICENSE-2.0 11 # 12 # Unless required by applicable law or agreed to in writing, software 13 # distributed under the License is distributed on an "AS IS" BASIS, 14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 # See the License for the specific language governing permissions and 16 # limitations under the License. 17 18 """TestSuite definition for Android instrumentation tests.""" 19 20 # python imports 21 import os 22 23 # local imports 24 import coverage 25 import errors 26 import logger 27 import test_suite 28 29 30 class InstrumentationTestSuite(test_suite.AbstractTestSuite): 31 """Represents a java instrumentation test suite definition run on device.""" 32 33 DEFAULT_RUNNER = "android.test.InstrumentationTestRunner" 34 35 # build path to Emma target Makefile 36 _EMMA_BUILD_PATH = os.path.join("external", "emma") 37 38 def __init__(self): 39 test_suite.AbstractTestSuite.__init__(self) 40 self._package_name = None 41 self._runner_name = self.DEFAULT_RUNNER 42 self._class_name = None 43 self._target_name = None 44 self._java_package = None 45 46 def GetPackageName(self): 47 return self._package_name 48 49 def SetPackageName(self, package_name): 50 self._package_name = package_name 51 return self 52 53 def GetRunnerName(self): 54 return self._runner_name 55 56 def SetRunnerName(self, runner_name): 57 self._runner_name = runner_name 58 return self 59 60 def GetClassName(self): 61 return self._class_name 62 63 def SetClassName(self, class_name): 64 self._class_name = class_name 65 return self 66 67 def GetJavaPackageFilter(self): 68 return self._java_package 69 70 def SetJavaPackageFilter(self, java_package_name): 71 """Configure the suite to only run tests in given java package.""" 72 self._java_package = java_package_name 73 return self 74 75 def GetTargetName(self): 76 """Retrieve module that this test is targeting. 77 78 Used for generating code coverage metrics. 79 Returns: 80 the module target name 81 """ 82 return self._target_name 83 84 def SetTargetName(self, target_name): 85 self._target_name = target_name 86 return self 87 88 def GetBuildDependencies(self, options): 89 if options.coverage: 90 return [self._EMMA_BUILD_PATH] 91 return [] 92 93 def Run(self, options, adb): 94 """Run the provided test suite. 95 96 Builds up an adb instrument command using provided input arguments. 97 98 Args: 99 options: command line options to provide to test run 100 adb: adb_interface to device under test 101 102 Raises: 103 errors.AbortError: if fatal error occurs 104 """ 105 106 test_class = self.GetClassName() 107 if options.test_class is not None: 108 test_class = options.test_class.lstrip() 109 if test_class.startswith("."): 110 test_class = self.GetPackageName() + test_class 111 if options.test_method is not None: 112 test_class = "%s#%s" % (test_class, options.test_method) 113 114 test_package = self.GetJavaPackageFilter() 115 if options.test_package: 116 test_package = options.test_package 117 118 if test_class and test_package: 119 logger.Log('Error: both class and java package options are specified') 120 121 instrumentation_args = {} 122 if test_class is not None: 123 instrumentation_args["class"] = test_class 124 if test_package: 125 instrumentation_args["package"] = test_package 126 if options.test_size: 127 instrumentation_args["size"] = options.test_size 128 if options.wait_for_debugger: 129 instrumentation_args["debug"] = "true" 130 if options.suite_assign_mode: 131 instrumentation_args["suiteAssignment"] = "true" 132 if options.coverage: 133 instrumentation_args["coverage"] = "true" 134 if options.test_annotation: 135 instrumentation_args["annotation"] = options.test_annotation 136 if options.test_not_annotation: 137 instrumentation_args["notAnnotation"] = options.test_not_annotation 138 if options.preview: 139 adb_cmd = adb.PreviewInstrumentationCommand( 140 package_name=self.GetPackageName(), 141 runner_name=self.GetRunnerName(), 142 raw_mode=options.raw_mode, 143 instrumentation_args=instrumentation_args) 144 logger.Log(adb_cmd) 145 elif options.coverage: 146 coverage_gen = coverage.CoverageGenerator(adb) 147 if not coverage_gen.TestDeviceCoverageSupport(): 148 raise errors.AbortError 149 adb.WaitForInstrumentation(self.GetPackageName(), 150 self.GetRunnerName()) 151 # need to parse test output to determine path to coverage file 152 logger.Log("Running in coverage mode, suppressing test output") 153 try: 154 (test_results, status_map) = adb.StartInstrumentationForPackage( 155 package_name=self.GetPackageName(), 156 runner_name=self.GetRunnerName(), 157 timeout_time=60*60, 158 instrumentation_args=instrumentation_args) 159 except errors.InstrumentationError, errors.DeviceUnresponsiveError: 160 return 161 self._PrintTestResults(test_results) 162 device_coverage_path = status_map.get("coverageFilePath", None) 163 if device_coverage_path is None: 164 logger.Log("Error: could not find coverage data on device") 165 return 166 167 coverage_file = coverage_gen.ExtractReport( 168 self, device_coverage_path, test_qualifier=options.test_size) 169 if coverage_file is not None: 170 logger.Log("Coverage report generated at %s" % coverage_file) 171 else: 172 adb.WaitForInstrumentation(self.GetPackageName(), 173 self.GetRunnerName()) 174 adb.StartInstrumentationNoResults( 175 package_name=self.GetPackageName(), 176 runner_name=self.GetRunnerName(), 177 raw_mode=options.raw_mode, 178 instrumentation_args=instrumentation_args) 179 180 def _PrintTestResults(self, test_results): 181 """Prints a summary of test result data to stdout. 182 183 Args: 184 test_results: a list of am_instrument_parser.TestResult 185 """ 186 total_count = 0 187 error_count = 0 188 fail_count = 0 189 for test_result in test_results: 190 if test_result.GetStatusCode() == -1: # error 191 logger.Log("Error in %s: %s" % (test_result.GetTestName(), 192 test_result.GetFailureReason())) 193 error_count+=1 194 elif test_result.GetStatusCode() == -2: # failure 195 logger.Log("Failure in %s: %s" % (test_result.GetTestName(), 196 test_result.GetFailureReason())) 197 fail_count+=1 198 total_count+=1 199 logger.Log("Tests run: %d, Failures: %d, Errors: %d" % 200 (total_count, fail_count, error_count)) 201