Add Apps.AppListSearchQueryLength UMA histogram.
[chromium-blink-merge.git] / build / android / pylib / host_driven / test_info_collection.py
blobc65d417df7253d4b7071a9afbbf1dbd6fe3f38e1
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
3 # found in the LICENSE file.
5 """Module containing information about the host-driven tests."""
7 import logging
8 import os
9 import sys
11 from pylib.host_driven import tests_annotations
13 from pylib import constants
15 sys.path.insert(0,
16 os.path.join(constants.DIR_SOURCE_ROOT,
17 'build', 'util', 'lib', 'common'))
19 import unittest_util # pylint: disable=F0401
21 class TestInfo(object):
22 """An object containing and representing a test function, plus metadata."""
24 def __init__(self, runnable, set_up=None, tear_down=None):
25 # The actual test function/method.
26 self.runnable = runnable
27 # Qualified name of test function/method (e.g. FooModule.testBar).
28 self.qualified_name = self._GetQualifiedName(runnable)
29 # setUp and teardown functions, if any.
30 self.set_up = set_up
31 self.tear_down = tear_down
33 @staticmethod
34 def _GetQualifiedName(runnable):
35 """Helper method to infer a runnable's name and module name.
37 Many filters and lists presuppose a format of module_name.testMethodName.
38 To make this easy on everyone, we use some reflection magic to infer this
39 name automatically.
41 Args:
42 runnable: the test method to get the qualified name for
44 Returns:
45 qualified name for this runnable, incl. module name and method name.
46 """
47 runnable_name = runnable.__name__
48 # See also tests_annotations.
49 module_name = os.path.splitext(
50 os.path.basename(runnable.__globals__['__file__']))[0]
51 return '.'.join([module_name, runnable_name])
53 def __str__(self):
54 return self.qualified_name
57 class TestInfoCollection(object):
58 """A collection of TestInfo objects which facilitates filtering."""
60 def __init__(self):
61 """Initialize a new TestInfoCollection."""
62 # Master list of all valid tests.
63 self.all_tests = []
65 def AddTests(self, test_infos):
66 """Adds a set of tests to this collection.
68 The user may then retrieve them, optionally according to criteria, via
69 GetAvailableTests().
71 Args:
72 test_infos: a list of TestInfos representing test functions/methods.
73 """
74 self.all_tests = test_infos
76 def GetAvailableTests(self, annotations, exclude_annotations, name_filter):
77 """Get a collection of TestInfos which match the supplied criteria.
79 Args:
80 annotations: List of annotations. Each test in the returned list is
81 annotated with atleast one of these annotations.
82 exclude_annotations: List of annotations. The tests in the returned
83 list are not annotated with any of these annotations.
84 name_filter: name filter which tests must match, if any
86 Returns:
87 List of available tests.
88 """
89 available_tests = self.all_tests
91 # Filter out tests which match neither the requested annotation, nor the
92 # requested name filter, if any.
93 available_tests = [t for t in available_tests if
94 self._AnnotationIncludesTest(t, annotations)]
95 if annotations and len(annotations) == 1 and annotations[0] == 'SmallTest':
96 tests_without_annotation = [
97 t for t in self.all_tests if
98 not tests_annotations.AnnotatedFunctions.GetTestAnnotations(
99 t.qualified_name)]
100 test_names = [t.qualified_name for t in tests_without_annotation]
101 logging.warning('The following tests do not contain any annotation. '
102 'Assuming "SmallTest":\n%s',
103 '\n'.join(test_names))
104 available_tests += tests_without_annotation
105 if exclude_annotations:
106 excluded_tests = [t for t in available_tests if
107 self._AnnotationIncludesTest(t, exclude_annotations)]
108 available_tests = list(set(available_tests) - set(excluded_tests))
110 if name_filter:
111 available_test_names = unittest_util.FilterTestNames(
112 [t.qualified_name for t in available_tests], name_filter)
113 available_tests = [
114 t for t in available_tests if
115 t.qualified_name in available_test_names]
116 return available_tests
118 @staticmethod
119 def _AnnotationIncludesTest(test_info, annotation_filter_list):
120 """Checks whether a given test represented by test_info matches annotation.
122 Args:
123 test_info: TestInfo object representing the test
124 annotation_filter_list: list of annotation filters to match (e.g. Smoke)
126 Returns:
127 True if no annotation was supplied or the test matches; false otherwise.
129 if not annotation_filter_list:
130 return True
131 for annotation_filter in annotation_filter_list:
132 filters = annotation_filter.split('=')
133 if len(filters) == 2:
134 key = filters[0]
135 value_list = filters[1].split(',')
136 for value in value_list:
137 if tests_annotations.AnnotatedFunctions.IsAnnotated(
138 key + ':' + value, test_info.qualified_name):
139 return True
140 elif tests_annotations.AnnotatedFunctions.IsAnnotated(
141 annotation_filter, test_info.qualified_name):
142 return True
143 return False