summaryrefslogtreecommitdiffstats
path: root/testrunner/test_defs/instrumentation_test.py
blob: c932a0be380facd59876b1014194afd07da6655e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#!/usr/bin/python2.4
#
#
# Copyright 2008, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""TestSuite definition for Android instrumentation tests."""

# python imports
import os

# local imports
import coverage
import errors
import logger
import test_suite


class InstrumentationTestSuite(test_suite.AbstractTestSuite):
  """Represents a java instrumentation test suite definition run on device."""

  DEFAULT_RUNNER = "android.test.InstrumentationTestRunner"

    # build path to Emma target Makefile
  _EMMA_BUILD_PATH = os.path.join("external", "emma")

  def __init__(self):
    test_suite.AbstractTestSuite.__init__(self)
    self._package_name = None
    self._runner_name = self.DEFAULT_RUNNER
    self._class_name = None
    self._target_name = None
    self._java_package = None

  def GetPackageName(self):
    return self._package_name

  def SetPackageName(self, package_name):
    self._package_name = package_name
    return self

  def GetRunnerName(self):
    return self._runner_name

  def SetRunnerName(self, runner_name):
    self._runner_name = runner_name
    return self

  def GetClassName(self):
    return self._class_name

  def SetClassName(self, class_name):
    self._class_name = class_name
    return self

  def GetJavaPackageFilter(self):
    return self._java_package

  def SetJavaPackageFilter(self, java_package_name):
    """Configure the suite to only run tests in given java package."""
    self._java_package = java_package_name
    return self

  def GetTargetName(self):
    """Retrieve module that this test is targeting.

    Used for generating code coverage metrics.
    Returns:
      the module target name
    """
    return self._target_name

  def SetTargetName(self, target_name):
    self._target_name = target_name
    return self

  def GetBuildDependencies(self, options):
    if options.coverage:
      return [self._EMMA_BUILD_PATH]
    return []

  def Run(self, options, adb):
    """Run the provided test suite.

    Builds up an adb instrument command using provided input arguments.

    Args:
      options: command line options to provide to test run
      adb: adb_interface to device under test

    Raises:
      errors.AbortError: if fatal error occurs
    """

    test_class = self.GetClassName()
    if options.test_class is not None:
      test_class = options.test_class.lstrip()
      if test_class.startswith("."):
        test_class = self.GetPackageName() + test_class
    if options.test_method is not None:
      test_class = "%s#%s" % (test_class, options.test_method)

    test_package = self.GetJavaPackageFilter()
    if options.test_package:
      test_package = options.test_package

    if test_class and test_package:
      logger.Log('Error: both class and java package options are specified')

    instrumentation_args = {}
    if test_class is not None:
      instrumentation_args["class"] = test_class
    if test_package:
      instrumentation_args["package"] = test_package
    if options.test_size:
      instrumentation_args["size"] = options.test_size
    if options.wait_for_debugger:
      instrumentation_args["debug"] = "true"
    if options.suite_assign_mode:
      instrumentation_args["suiteAssignment"] = "true"
    if options.coverage:
      instrumentation_args["coverage"] = "true"
    if options.preview:
      adb_cmd = adb.PreviewInstrumentationCommand(
          package_name=self.GetPackageName(),
          runner_name=self.GetRunnerName(),
          raw_mode=options.raw_mode,
          instrumentation_args=instrumentation_args)
      logger.Log(adb_cmd)
    elif options.coverage:
      coverage_gen = coverage.CoverageGenerator(adb)
      if not coverage_gen.TestDeviceCoverageSupport():
        raise errors.AbortError
      adb.WaitForInstrumentation(self.GetPackageName(),
                                 self.GetRunnerName())
      # need to parse test output to determine path to coverage file
      logger.Log("Running in coverage mode, suppressing test output")
      try:
        (test_results, status_map) = adb.StartInstrumentationForPackage(
            package_name=self.GetPackageName(),
            runner_name=self.GetRunnerName(),
            timeout_time=60*60,
            instrumentation_args=instrumentation_args)
      except errors.InstrumentationError, errors.DeviceUnresponsiveError:
        return
      self._PrintTestResults(test_results)
      device_coverage_path = status_map.get("coverageFilePath", None)
      if device_coverage_path is None:
        logger.Log("Error: could not find coverage data on device")
        return

      coverage_file = coverage_gen.ExtractReport(
          self, device_coverage_path, test_qualifier=options.test_size)
      if coverage_file is not None:
        logger.Log("Coverage report generated at %s" % coverage_file)
    else:
      adb.WaitForInstrumentation(self.GetPackageName(),
                                 self.GetRunnerName())
      adb.StartInstrumentationNoResults(
          package_name=self.GetPackageName(),
          runner_name=self.GetRunnerName(),
          raw_mode=options.raw_mode,
          instrumentation_args=instrumentation_args)

  def _PrintTestResults(self, test_results):
    """Prints a summary of test result data to stdout.

    Args:
      test_results: a list of am_instrument_parser.TestResult
    """
    total_count = 0
    error_count = 0
    fail_count = 0
    for test_result in test_results:
      if test_result.GetStatusCode() == -1:  # error
        logger.Log("Error in %s: %s" % (test_result.GetTestName(),
                                        test_result.GetFailureReason()))
        error_count+=1
      elif test_result.GetStatusCode() == -2:  # failure
        logger.Log("Failure in %s: %s" % (test_result.GetTestName(),
                                          test_result.GetFailureReason()))
        fail_count+=1
      total_count+=1
    logger.Log("Tests run: %d, Failures: %d, Errors: %d" %
               (total_count, fail_count, error_count))