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

Side by Side Diff: third_party/WebKit/Tools/Scripts/webkitpy/w3c/update_w3c_test_expectations.py

Issue 2136723002: Create test expectations line automatically from failing test results (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add function to write to TestExpectations with unittest Created 4 years, 5 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 # Copyright 2016 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.
4
5 """A script to modify TestExpectations lines based layout test failures in try j obs.
6
7 This script outputs a list of test expectation lines to add to a "TestExpectatio ns" file
8 by retrieving the try job results for the current CL.
9
10 Platform_Results_dict structure:
11 {Test Name(s): { Platform(s): {'actual': ACTUAL_RESULTS, 'expected': EXPECTED_R ESULTS, 'bug': BUG_URL}}}
12 each Test Name and Platform are keys in their respective dictionaries.
13 """
14
15 import logging
16
17 from webkitpy.common.checkout.scm.git import Git
18 from webkitpy.common.host import Host
19 from webkitpy.common.net import buildbot
20 from webkitpy.common.net import rietveld
21 from webkitpy.common.net.web import Web
22 from webkitpy.layout_tests.builder_list import BuilderList
23 from webkitpy.common.config.builders import BUILDERS as Builders_list_dict
qyearsley 2016/07/18 18:31:42 You can keep the name BUILDERS, since that's simpl
dcampb 2016/07/18 20:50:04 I have removed this import as well as builder_list
24
25
26 _log = logging.getLogger(__name__)
27
28
29 TRY_BOTS = ['linux_chromium_rel_ng', 'mac_chromium_rel_ng', 'win_chromium_rel_ng ']
30
31
32 def main():
33 host = Host()
34 port = host.port_factory.get()
35 expectations_file = port.path_to_generic_test_expectations_file()
36 counter = 0
37 builderlist = BuilderList(Builders_list_dict)
qyearsley 2016/07/18 18:31:42 builderlist -> builder_list
38 git = Git('.')
39 web = Web()
40 expectations_line_adder = W3CExpectationsLineAdder(git, web, builderlist)
41 issue_number = expectations_line_adder._git.get_issue_number()
qyearsley 2016/07/18 18:31:42 Here a private attribute of another object is acce
dcampb 2016/07/18 20:50:04 I moved this line and the line 42 into their own f
42 try_bots = expectations_line_adder._builder_list.all_try_builder_names()
43 try_jobs_info = expectations_line_adder.get_try_jobs_information(issue_numbe r, try_bots)
44 line_expectations_dict = {}
45 while counter < len(try_bots):
46 try:
47 builder_name = try_jobs_info[counter][0]
48 build_number = try_jobs_info[counter][1]
49 builder = buildbot.Builder(builder_name, buildbot.BuildBot())
50 build = buildbot.Build(builder, build_number)
51 platform_results_dict = expectations_line_adder.get_failing_results_ dict(builder, build)
52 line_expectations_dict = expectations_line_adder.merge_dicts(line_ex pectations_dict, platform_results_dict)
53 counter += 1
54 except IndexError:
55 print "no tryjob info was collected"
qyearsley 2016/07/18 18:31:42 You could add capitalization and punctuation to th
56 return 1
57 for platform_results_dicts in line_expectations_dict.values():
58 platform_results_dicts = expectations_line_adder.merge_same_valued_keys( platform_results_dicts)
59 line_list = expectations_line_adder.create_line_list(line_expectations_dict)
60 expectations_line_adder.write_to_testexpectations(host, expectations_file, l ine_list)
61
62
63 class W3CExpectationsLineAdder(object):
qyearsley 2016/07/18 18:31:42 Formatting note: Usually there's a blank line befo
64 def __init__(self, git, web, builderlist):
qyearsley 2016/07/18 18:31:42 builderlist -> builder_list
65 self._git = git
66 self._web = web
67 self._builder_list = builderlist
68
69 # This function will return only tryjobs with failing results.
70 # If no failing results, try_job info will not be returned. If one try serve r
71 # has two try jobs, it will return both.
qyearsley 2016/07/18 18:31:42 This comment can go inside a docstring, and update
72 def get_try_jobs_information(self, issue_number, try_bots):
73 info = rietveld.latest_try_jobs(issue_number, try_bots, self._web)
74 return info
qyearsley 2016/07/18 18:31:41 The variable info doesn't provide any extra inform
75
76 def _generate_results_dict(self, platform, result_list):
77 test_dict = {}
78 dash = platform.find("-")
79 if dash != -1:
qyearsley 2016/07/18 18:31:42 To find if a character exists in a string you can
dcampb 2016/07/18 20:50:04 done
80 platform = platform[dash + 1:].capitalize()
81 for result in result_list:
82 test_dict[result.test_name()] = {platform: {'expected': result.expec ted_results(), 'actual': result.actual_results(), 'bug': 'crbug.com/626703'}}
qyearsley 2016/07/18 18:31:42 This line is a bit long; reformatting it may make
dcampb 2016/07/18 20:50:04 done
83 return test_dict
84
85 def get_failing_results_dict(self, builder, build):
86 layout_test_results = builder.fetch_layout_test_results(build.results_ur l())
87 builder_name = layout_test_results.builder_name()
88 platform = self._builder_list.port_name_for_builder_name(builder_name)
89 result_list = layout_test_results.didnt_run_as_expected_results()
90 failing_results_dict = self._generate_results_dict(platform, result_list )
91 return failing_results_dict
92
93 def merge_dicts(self, final, temp, path=None):
94 path = path or []
95 for key in temp:
96 if key in final:
97 if (isinstance(final[key], dict)) and isinstance(temp[key], dict ):
98 self.merge_dicts(final[key], temp[key], path + [str(key)])
99 elif final[key] == temp[key]:
100 pass
101 else:
102 raise Exception('conflict at %s' % '.'.join(path))
103 else:
104 final[key] = temp[key]
105 return final
106
107 def merge_same_valued_keys(self, dictionary):
108 matching_value_keys = set()
109 keys = dictionary.keys()
110 isLastItem = False
111 for index, item in enumerate(keys):
112 if isLastItem:
113 break
114 for i in range(index + 1, len(keys)):
115 next_item = keys[i]
116 if dictionary[item] == dictionary[next_item]:
117 matching_value_keys.update([item, next_item])
118 dictionary[tuple(matching_value_keys)] = dictionary[item]
119 isLastItem = next_item == keys[-1]
120 del dictionary[item]
121 del dictionary[next_item]
122 return dictionary
123
124 def get_expectations(self, results):
125 expectations = []
126 failure_expectations = ['TEXT', 'FAIL', 'IMAGE+TEXT', 'IMAGE']
127 pass_crash_timeout = ['TIMEOUT', 'CRASH', 'PASS']
128 if results['expected'] in pass_crash_timeout and results['actual'] in fa ilure_expectations:
129 expectations.append('Failure')
130 if results['expected'] in failure_expectations and results['actual'] in pass_crash_timeout:
131 expectations.append(results['actual'].capitalize())
132 if results['expected'] in pass_crash_timeout and results['actual'] in pa ss_crash_timeout:
133 expectations.append(results['actual'].capitalize())
134 expectations.append(results['expected'].capitalize())
135 return expectations
136
137 def create_line_list(self, dictionary):
138 line_list = []
139 for key, value in dictionary.iteritems():
140 test_name = key
141 for key2 in value:
142 platform = []
143 bug = []
144 expectations = []
145 if isinstance(key2, tuple):
146 platform = list(key2)
147 else:
148 platform.append(key2)
149 bug.append(value[key2]['bug'])
150 expectations = self.get_expectations(value[key2])
151 line = '%s [ %s ] %s [ %s ]' % (bug[0], ' '.join(platform), test _name, ' '.join(expectations))
152 line_list.append(str(line))
153 return line_list
154
155 def write_to_testexpectations(self, host, path, line_list):
156 file_contents = host.filesystem.read_text_file(path)
157 w3c_comment_line_index = file_contents.find("# Tests added from W3C auto import bot")
158 all_lines = ""
159 for line in line_list:
160 all_lines += str(line) + "\n"
161 all_lines = all_lines[:-1]
162 if w3c_comment_line_index == -1:
163 file_contents += "\n\n# Tests added from W3C auto import bot\n"
164 file_contents += all_lines
165 else:
166 end_of_comment_line = (file_contents[w3c_comment_line_index:].find(' \n')) + w3c_comment_line_index
167 new_data = file_contents[: end_of_comment_line + 1] + all_lines + fi le_contents[end_of_comment_line:]
168 file_contents = new_data
169 host.filesystem.write_text_file(path, file_contents)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698