1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/trunk/build/android/pylib/test_info_collection.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,137 @@ 1.4 +# Copyright (c) 2012 The Chromium Authors. All rights reserved. 1.5 +# Use of this source code is governed by a BSD-style license that can be 1.6 +# found in the LICENSE file. 1.7 + 1.8 +"""Module containing information about the python-driven tests.""" 1.9 + 1.10 +import logging 1.11 +import os 1.12 + 1.13 +import tests_annotations 1.14 + 1.15 + 1.16 +class TestInfo(object): 1.17 + """An object containing and representing a test function, plus metadata.""" 1.18 + 1.19 + def __init__(self, runnable, set_up=None, tear_down=None): 1.20 + # The actual test function/method. 1.21 + self.runnable = runnable 1.22 + # Qualified name of test function/method (e.g. FooModule.testBar). 1.23 + self.qualified_name = self._GetQualifiedName(runnable) 1.24 + # setUp and teardown functions, if any. 1.25 + self.set_up = set_up 1.26 + self.tear_down = tear_down 1.27 + 1.28 + def _GetQualifiedName(self, runnable): 1.29 + """Helper method to infer a runnable's name and module name. 1.30 + 1.31 + Many filters and lists presuppose a format of module_name.testMethodName. 1.32 + To make this easy on everyone, we use some reflection magic to infer this 1.33 + name automatically. 1.34 + 1.35 + Args: 1.36 + runnable: the test method to get the qualified name for 1.37 + 1.38 + Returns: 1.39 + qualified name for this runnable, incl. module name and method name. 1.40 + """ 1.41 + runnable_name = runnable.__name__ 1.42 + # See also tests_annotations. 1.43 + module_name = os.path.splitext( 1.44 + os.path.basename(runnable.__globals__['__file__']))[0] 1.45 + return '.'.join([module_name, runnable_name]) 1.46 + 1.47 + def __str__(self): 1.48 + return self.qualified_name 1.49 + 1.50 + 1.51 +class TestInfoCollection(object): 1.52 + """A collection of TestInfo objects which facilitates filtering.""" 1.53 + 1.54 + def __init__(self): 1.55 + """Initialize a new TestInfoCollection.""" 1.56 + # Master list of all valid tests. 1.57 + self.all_tests = [] 1.58 + 1.59 + def AddTests(self, test_infos): 1.60 + """Adds a set of tests to this collection. 1.61 + 1.62 + The user may then retrieve them, optionally according to criteria, via 1.63 + GetAvailableTests(). 1.64 + 1.65 + Args: 1.66 + test_infos: a list of TestInfos representing test functions/methods. 1.67 + """ 1.68 + self.all_tests = test_infos 1.69 + 1.70 + def GetAvailableTests(self, annotation, name_filter): 1.71 + """Get a collection of TestInfos which match the supplied criteria. 1.72 + 1.73 + Args: 1.74 + annotation: annotation which tests must match, if any 1.75 + name_filter: name filter which tests must match, if any 1.76 + 1.77 + Returns: 1.78 + List of available tests. 1.79 + """ 1.80 + available_tests = self.all_tests 1.81 + 1.82 + # Filter out tests which match neither the requested annotation, nor the 1.83 + # requested name filter, if any. 1.84 + available_tests = [t for t in available_tests if 1.85 + self._AnnotationIncludesTest(t, annotation)] 1.86 + if annotation and len(annotation) == 1 and annotation[0] == 'SmallTest': 1.87 + tests_without_annotation = [ 1.88 + t for t in self.all_tests if 1.89 + not tests_annotations.AnnotatedFunctions.GetTestAnnotations( 1.90 + t.qualified_name)] 1.91 + test_names = [t.qualified_name for t in tests_without_annotation] 1.92 + logging.warning('The following tests do not contain any annotation. ' 1.93 + 'Assuming "SmallTest":\n%s', 1.94 + '\n'.join(test_names)) 1.95 + available_tests += tests_without_annotation 1.96 + available_tests = [t for t in available_tests if 1.97 + self._NameFilterIncludesTest(t, name_filter)] 1.98 + 1.99 + return available_tests 1.100 + 1.101 + def _AnnotationIncludesTest(self, test_info, annotation_filter_list): 1.102 + """Checks whether a given test represented by test_info matches annotation. 1.103 + 1.104 + Args: 1.105 + test_info: TestInfo object representing the test 1.106 + annotation_filter_list: list of annotation filters to match (e.g. Smoke) 1.107 + 1.108 + Returns: 1.109 + True if no annotation was supplied or the test matches; false otherwise. 1.110 + """ 1.111 + if not annotation_filter_list: 1.112 + return True 1.113 + for annotation_filter in annotation_filter_list: 1.114 + filters = annotation_filter.split('=') 1.115 + if len(filters) == 2: 1.116 + key = filters[0] 1.117 + value_list = filters[1].split(',') 1.118 + for value in value_list: 1.119 + if tests_annotations.AnnotatedFunctions.IsAnnotated( 1.120 + key + ':' + value, test_info.qualified_name): 1.121 + return True 1.122 + elif tests_annotations.AnnotatedFunctions.IsAnnotated( 1.123 + annotation_filter, test_info.qualified_name): 1.124 + return True 1.125 + return False 1.126 + 1.127 + def _NameFilterIncludesTest(self, test_info, name_filter): 1.128 + """Checks whether a name filter matches a given test_info's method name. 1.129 + 1.130 + This is a case-sensitive, substring comparison: 'Foo' will match methods 1.131 + Foo.testBar and Bar.testFoo. 'foo' would not match either. 1.132 + 1.133 + Args: 1.134 + test_info: TestInfo object representing the test 1.135 + name_filter: substring to check for in the qualified name of the test 1.136 + 1.137 + Returns: 1.138 + True if no name filter supplied or it matches; False otherwise. 1.139 + """ 1.140 + return not name_filter or name_filter in test_info.qualified_name