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

Side by Side Diff: tools/android/find_annotated_tests.py

Issue 1851143002: Find annotated tests by exposing API in instrumentation_test_instance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Change after mikecase's comments Created 4 years, 6 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
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2016 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Finds all the annotated tests from proguard dump"""
7
8 import argparse
9 import datetime
10 import json
11 import linecache
12 import logging
13 import os
14 import pprint
15 import re
16 import sys
17 import time
18
19 _SRC_DIR = os.path.abspath(os.path.join(
20 os.path.dirname(__file__), '..', '..'))
21
22 sys.path.append(os.path.join(_SRC_DIR, 'build', 'android'))
23 from pylib import constants
24 from pylib.instrumentation import instrumentation_test_instance
25
26 sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil'))
jbudorick 2016/06/11 00:24:02 nit: devil should precede pylib in the import list
the real yoland 2016/06/11 01:35:43 Done
27 from devil.utils import cmd_helper
28
29 _GIT_TIME_FORMAT = '%Y-%m-%dT%H:%M:%S'
jbudorick 2016/06/11 00:24:03 nit: alphabetize these constants within each subgr
the real yoland 2016/06/11 01:35:43 Done
30 _EXPORT_TIME_FORMAT = '%Y%m%dT%H%M%S'
31
32 _GIT_LOG_TIME_PATTERN = re.compile(r'\d+')
33 _GIT_LOG_MESSAGE_PATTERN = r'Cr-Commit-Position: refs/heads/master@{#(\d+)}'
34
35 _CRBUG_ID_PATTERN = re.compile(r'crbug(?:.com)?/(\d+)')
36
37 _TEST_MASTER_KEY = 'tests'
jbudorick 2016/06/11 00:24:03 Are all of these only used once? If so, why are th
the real yoland 2016/06/11 01:35:43 I was using them here so if any renaming is decide
38 _REPORT_MASTER_KEY = 'metadata'
39 _REVISION_KEY = 'revision'
40 _COMMIT_POS_KEY = 'commit_pos'
41 _ANNOTATIONS_KEY = 'annotations'
42 _TEST_NAME_KEY = 'test_name'
43 _TEST_APK_KEY = 'test_apk_name'
44 _CRBUG_KEY = 'bug_id'
45 _CLASS_PATH_KEY = 'class_path'
46 _CLASS_NAME_KEY = 'class_name'
47 _TOTAL_TEST_COUNT_KEY = 'total_test_count'
48 _UTC_SCRIPT_RUNTIME= 'script_runtime'
49 _UTC_REVISIONTIME_KEY = 'revision_time'
50 _PLATFORM_KEY = 'platform'
51 _PLATFORM_VALUE = 'android'
52
53
54 def _GetBugId(message):
55 """Validate bug message format and get bug id"""
56 result = re.search(_CRBUG_ID_PATTERN, message)
57 if result:
58 return int(result.group(1))
59 else:
60 return None
61
62
63 def _GetAnnotations(test_annotations):
64 """Store annotations in the existing anntation_dict and return bug id"""
jbudorick 2016/06/11 00:24:03 nit: anntation_dict -> annotation_dict
the real yoland 2016/06/11 01:35:43 ...O_o how Done
65 bug_id = None
66 annotations_dict = {}
jbudorick 2016/06/11 00:24:03 What's the point of annotations_dict? It's the sam
the real yoland 2016/06/11 01:35:43 My bad, inherited problem from previous CLs Done
67 for annotation, content in test_annotations.iteritems():
68 if content is not None and content.get('message') is not None:
jbudorick 2016/06/11 00:24:03 nit: collapse these two lines down to just bug_id
the real yoland 2016/06/11 01:35:43 Done
69 bug_id = _GetBugId(content.get('message'))
jbudorick 2016/06/11 00:24:03 So this gets any annotation with a crbug message?
the real yoland 2016/06/11 01:35:43 Yes, it parses any annotation with message to matc
70 annotations_dict.update({annotation: content})
71 return bug_id, annotations_dict
72
73
74 def _GetTests(test_apks, apk_output_dir):
75 """Return a list of all annotated tests and total test count"""
76 result = []
77 total_test_count = 0
78 for test_apk in test_apks:
79 logging.info('Current test apk: %s', test_apk)
80 test_jar = os.path.join(
81 apk_output_dir, constants.SDK_BUILD_TEST_JAVALIB_DIR,
82 '%s.jar' % test_apk)
83 all_tests = instrumentation_test_instance.GetAllTests(test_jar=test_jar)
84 for test_class in all_tests:
85 class_path = test_class['class']
86 class_name = test_class['class'].split('.')[-1]
87
88 class_bug_id, class_annotation = _GetAnnotations(
89 test_class['annotations'])
90 for test_method in test_class['methods']:
91 total_test_count += 1
92 # getting annotation of each test case
93 test_bug_id, test_annotations = _GetAnnotations(
94 test_method['annotations'])
95 test_bug_id = test_bug_id if test_bug_id else class_bug_id
96 test_annotations.update(class_annotation)
97 # getting test method name of each test
98 test_name = test_method['method']
99 test_dict = {
100 _CRBUG_KEY: test_bug_id,
101 _ANNOTATIONS_KEY: test_annotations,
102 _TEST_NAME_KEY: test_name,
103 _TEST_APK_KEY: test_apk,
104 _CLASS_NAME_KEY: class_name,
105 _CLASS_PATH_KEY: class_path
106 }
107 result.append(test_dict)
108 logging.info('Total count of tests in all test apks: %d', total_test_count)
109 return result, total_test_count
110
111
112 def _GetReportMeta(utc_script_runtime_string, total_test_count):
113 """Returns a dictionary of the report's metadata"""
114 revision = cmd_helper.GetCmdOutput(['git', 'rev-parse', 'HEAD']).strip()
115 raw_string = cmd_helper.GetCmdOutput(
116 ['git', 'log', '--pretty=format:%at', '--max-count=1', 'HEAD'])
117 time_string_search = re.search(_GIT_LOG_TIME_PATTERN, raw_string)
118 if time_string_search is None:
119 raise Exception('Timestamp format incorrect, expected all digits, got %s'
120 % raw_string)
121
122 raw_string = cmd_helper.GetCmdOutput(
123 ['git', 'log', '--pretty=format:%b', '--max-count=1', 'HEAD'])
124 commit_pos_search = re.search(_GIT_LOG_MESSAGE_PATTERN, raw_string)
125 if commit_pos_search is None:
126 raise Exception('Cr-Commit-Position is not found, potentially running with '
127 'uncommited HEAD')
128 commit_pos = int(commit_pos_search.group(1))
129
130 utc_revision_time = datetime.datetime.utcfromtimestamp(
131 int(time_string_search.group(0)))
132 utc_revision_time = utc_revision_time.strftime(_EXPORT_TIME_FORMAT)
133 logging.info(
134 'revision is %s, revision time is %s', revision, utc_revision_time)
135
136 return {
137 _REVISION_KEY: revision,
138 _COMMIT_POS_KEY: commit_pos,
139 _UTC_SCRIPT_RUNTIME: utc_script_runtime_string,
140 _UTC_REVISIONTIME_KEY: utc_revision_time,
141 _PLATFORM_KEY: _PLATFORM_VALUE,
142 _TOTAL_TEST_COUNT_KEY: total_test_count
143 }
144
145
146 def _GetReport(test_apks, script_runtime_string, apk_output_dir):
147 """Generate the dictionary of report data
148
149 Args:
150 test_apks: a list of apks for search for tests
151 script_runtime_string: the time when the script is run at
152 format: '%Y%m%dT%H%M%S'
153 """
154
155 test_data, total_test_count = _GetTests(test_apks, apk_output_dir)
156 report_meta = _GetReportMeta(script_runtime_string, total_test_count)
157 report_data = {
158 _REPORT_MASTER_KEY: report_meta,
159 _TEST_MASTER_KEY: test_data}
jbudorick 2016/06/11 00:24:02 nit: drop } onto its own line
the real yoland 2016/06/11 01:35:43 Done
160 return report_data
161
162
163 def main():
164 parser = argparse.ArgumentParser()
165 parser.add_argument('-t', '--test-apks', nargs='+', dest='test_apks',
166 required=True,
167 help='List all test apks file name that the script uses '
168 'to fetch tracked tests from')
169 parser.add_argument('--json-output-dir', required=True,
170 help='JSON file output directory')
171 parser.add_argument('--apk-output-dir', required=True,
172 help='The output directory of test apks')
173 parser.add_argument('-v', '--verbose', action='store_true', default=False,
174 help='INFO verbosity')
175
176 arguments = parser.parse_args(sys.argv[1:])
177 logging.basicConfig(
178 level=logging.INFO if arguments.verbose else logging.WARNING)
179
180 script_runtime = datetime.datetime.utcnow()
181 script_runtime_string = script_runtime.strftime(_EXPORT_TIME_FORMAT)
182 logging.info('Build time is %s', script_runtime_string)
183 apk_output_dir = os.path.abspath(os.path.join(
184 constants.DIR_SOURCE_ROOT, arguments.apk_output_dir))
jbudorick 2016/06/11 00:24:03 nit: indent two spaces
the real yoland 2016/06/11 01:35:43 Done
185 report_data = _GetReport(
186 arguments.test_apks, script_runtime_string, apk_output_dir)
187
188 temp_output_dir = arguments.json_output_dir
189 json_output_path = os.path.join(
190 temp_output_dir, '%s-android-chrome.json' % script_runtime_string)
191 with open(json_output_path, 'w') as f:
192 json.dump(report_data, f, sort_keys=True, separators=(',',': '))
193 logging.info('Saved json output file to %s', json_output_path)
194
195 if __name__ == '__main__':
196 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698