Tools/ChangeLog

 12015-01-21 Jake Nielsen <jacob_nielsen@apple.com>
 2
 3 webkitpy needs a results.html file to render the results.json file for
 4 human eyes.
 5 https://bugs.webkit.org/show_bug.cgi?id=138161
 6
 7 Reviewed by NOBODY (OOPS!).
 8
 9 * Scripts/resources/results-stylesheet.css: Added.
 10 Style sheet for results.html
 11 (body):
 12 (body > *):
 13 (h1):
 14 (pre):
 15 (.expand-button):
 16 (.expand-button-text):
 17 (.hidden):
 18 (.actual-results):
 19 * Scripts/resources/results.html: Added.
 20 * Scripts/webkitpy/port/base.py:
 21 Adds the script_resources_directory function to allow runtests to copy
 22 results.html and results-stylesheet.css into the appropriate
 23 directory.
 24 (Port.script_resources_directory):
 25 * Scripts/webkitpy/tool/steps/runtests.py:
 26 Copies files as per comment above.
 27 (RunTests.run):
 28
1292015-01-21 Alexey Proskuryakov <ap@apple.com>
230
331 https://build.webkit.org/dashboard/metrics.html fails because of ios-ews

Tools/Scripts/resources/results-stylesheet.css

 1body {
 2 margin: 0;
 3 font-family: Helvetica, sans-serif;
 4 font-size: 11pt;
 5}
 6
 7body > * {
 8 margin-left: 4px;
 9 margin-top: 4px;
 10}
 11
 12h1 {
 13 font-size: 14pt;
 14 margin-top: 1.5em;
 15}
 16
 17pre {
 18 font-family: "Courier New";
 19 border: 1px solid;
 20 background-color: #E3E3E3;
 21 padding: 6px;
 22}
 23
 24.expand-button {
 25 background-color: white;
 26 width: 11px;
 27 height: 12px;
 28 border: 1px solid gray;
 29 display: inline-block;
 30 margin: 0 3px 0 0;
 31 position: relative;
 32 cursor: default;
 33 -webkit-user-select: none;
 34}
 35
 36.expand-button-text {
 37 position: absolute;
 38 top: -0.3em;
 39 left: 1px;
 40 pointer-events: none;
 41}
 42
 43.hidden {
 44 display: none;
 45}
 46
 47.actual-results {
 48 display: inline-block;
 49 border: 1px solid gray;
 50 margin: 4px;
 51}

Tools/Scripts/resources/results.html

 1<!DOCTYPE html>
 2<html>
 3<head>
 4 <meta charset="utf-8">
 5 <link rel="stylesheet" href="results-stylesheet.css">
 6</head>
 7<body>
 8<template class="test-results-listing">
 9 <h1>Tests that failed (1):</h1>
 10 <table>
 11 <template class="test-results-table-section">
 12 <tr>
 13 <td><span class="expand-button" onclick="toggleActualResults(this)"><span class="expand-button-text">+</span></span><a href="#">webkitpy.common.editdistance_unittest.EditDistanceTest.test_edit_distance</a></td>
 14 </tr>
 15 <tr class="hidden">
 16 <td colspan="1"><pre class="actual-results">AssertionError: 2 != 6</pre></td>
 17 </tr>
 18 </template>
 19 </table>
 20</template>
 21<template class="passing-test-listing">
 22 <h1>Tests that passed (1):</h1>
 23 <table>
 24 <template class="passing-test-table-section">
 25 <tr>
 26 <td><a href="#">webkitpy.common.editdistance_unittest.EditDistanceTest.test_edit_distance</a></td>
 27 </tr>
 28 </template>
 29 </table>
 30</template>
 31
 32<script>
 33
 34var fileRequest = new XMLHttpRequest();
 35fileRequest.open('GET', "results.json", false);
 36fileRequest.responseType = 'json';
 37fileRequest.send();
 38
 39var g_jsonp = fileRequest.response
 40
 41</script>
 42
 43<script>
 44var TRAC_WEBKITPY_URL_PREFIX = "https://trac.webkit.org/browser/trunk/Tools/Scripts/";
 45var PYTHON_UNIT_TEST_SUFFIX = "_unittest";
 46var DisclosureState = {
 47 OPEN: "–",
 48 CLOSED: "+"
 49};
 50
 51function matchesSelector(node, selector)
 52{
 53 if (node.matches)
 54 return node.matches(selector);
 55 if (node.webkitMatchesSelector)
 56 return node.webkitMatchesSelector(selector);
 57 if (node.mozMatchesSelector)
 58 return node.mozMatchesSelector(selector);
 59}
 60
 61function parentOfType(node, selector)
 62{
 63 while (node = node.parentNode) {
 64 if (matchesSelector(node, selector))
 65 return node;
 66 }
 67 return null;
 68}
 69
 70function setActualResultsVisible(resultSection, visible)
 71{
 72 var functionToCall;
 73 var newDisclosureState;
 74 if (visible) {
 75 newDisclosureState = DisclosureState.OPEN;
 76 functionToCall = "remove";
 77 } else {
 78 newDisclosureState = DisclosureState.CLOSED;
 79 functionToCall = "add";
 80 }
 81 var expandButtonText = resultSection.querySelector(".expand-button-text");
 82 expandButtonText.textContent = newDisclosureState;
 83 resultSection.nextElementSibling.classList[functionToCall]("hidden");
 84}
 85
 86function toggleActualResults(element)
 87{
 88 setActualResultsVisible(parentOfType(element, "tr"), element.querySelector(".expand-button-text").textContent === DisclosureState.CLOSED);
 89}
 90
 91function tracURLForPythonUnitTestName(unitTestName)
 92{
 93 var modulePath = unitTestName.substr(0, unitTestName.lastIndexOf(PYTHON_UNIT_TEST_SUFFIX + ".") + PYTHON_UNIT_TEST_SUFFIX.length);
 94 return TRAC_WEBKITPY_URL_PREFIX + modulePath.replace(/\./g, "/") + ".py";
 95}
 96
 97function passToResultFormat(passingTest)
 98{
 99 return {
 100 name: passingTest,
 101 result: ["pass"],
 102 }
 103}
 104
 105var TestCategories = [
 106{
 107 name: "Tests that failed",
 108 tests: g_jsonp.failures,
 109},
 110{
 111 name: "Tests that had error output",
 112 tests: g_jsonp.errors,
 113}
 114];
 115
 116var listingContainer = document.createElement("div");
 117var listingTemplate = document.querySelector(".test-results-listing").content;
 118var tableSectionTemplate = listingTemplate.querySelector(".test-results-table-section").content;
 119
 120for (var i = 0; i < TestCategories.length; ++i) {
 121 var testCategory = TestCategories[i];
 122 var tests = testCategory.tests;
 123 var numberOfTests = tests.length;
 124
 125 var listing = listingTemplate.cloneNode(true /* Deep copy */);
 126 listing.querySelector("h1").textContent = testCategory.name + " (" + numberOfTests + "):";
 127 var table = listing.querySelector("table");
 128 for (var j = 0; j < numberOfTests; ++j) {
 129 var test = tests[j];
 130 var tableSection = tableSectionTemplate.cloneNode(true /* Deep copy */);
 131 var a = tableSection.querySelector("a");
 132 a.href = tracURLForPythonUnitTestName(test.name);
 133 a.textContent = test.name;
 134
 135 setActualResultsVisible(tableSection.querySelector("tr"), false);
 136
 137 // FIXME: Consider creating hyperlinks to trac.webkit.org corresponding to each file referenced in the backtrace.
 138 tableSection.querySelector(".actual-results").textContent = test.result;
 139 table.appendChild(tableSection);
 140 }
 141 listingContainer.appendChild(listing);
 142}
 143
 144var passingListingTemplate = document.querySelector(".passing-test-listing").content;
 145var passingTableSectionTemplate = passingListingTemplate.querySelector(".passing-test-table-section").content;
 146
 147var passingTests = g_jsonp.passes;
 148var numberOfPassingTests = passingTests.length;
 149
 150var listing = passingListingTemplate.cloneNode(true /* Deep copy */);
 151listing.querySelector("h1").textContent = "Tests that passed (" + numberOfPassingTests + "):";
 152var table = listing.querySelector("table");
 153for (var j = 0; j < numberOfPassingTests; ++j) {
 154 var testName = passingTests[j];
 155 var tableSection = passingTableSectionTemplate.cloneNode(true /* Deep copy */);
 156 var a = tableSection.querySelector("a");
 157 a.href = tracURLForPythonUnitTestName(testName);
 158 a.textContent = testName;
 159
 160 table.appendChild(tableSection);
 161}
 162listingContainer.appendChild(listing);
 163
 164document.body.appendChild(listingContainer);
 165</script>
 166</body>
 167</html>

Tools/Scripts/webkitpy/port/base.py

@@class Port(object):
781781 def python_unittest_results_directory(self):
782782 return self._build_path('python-unittest-results')
783783
 784 def script_resources_directory(self):
 785 return self.path_from_webkit_base("Tools", "Scripts", "resources")
 786
784787 def default_results_directory(self):
785788 """Absolute path to the default place to store the test results."""
786789 # Results are store relative to the built products to make it easy

Tools/Scripts/webkitpy/tool/steps/runtests.py

@@class RunTests(AbstractStep):
5858 _log.info("Running Python unit tests")
5959 if self._options.non_interactive:
6060 filesystem = self._tool.filesystem
61  python_unittest_results_directory = self._tool.port_factory.get().python_unittest_results_directory()
 61 port = self._tool.port_factory.get()
 62 python_unittest_results_directory = port.python_unittest_results_directory()
6263 filesystem.maybe_make_directory(python_unittest_results_directory)
6364
6465 python_unittests_command.append('--json')
6566 output = self._tool.executive.run_command(python_unittests_command, cwd=self._tool.scm().checkout_root, error_handler=Executive.ignore_error, return_stderr=False)
6667 filesystem.write_text_file(filesystem.join(python_unittest_results_directory, "results.json"), output)
 68 resources_path = port.script_resources_directory()
 69 filesystem.copyfile(filesystem.join(resources_path, "results.html"), filesystem.join(python_unittest_results_directory, "results.html"))
 70 filesystem.copyfile(filesystem.join(resources_path, "results-stylesheet.css"), filesystem.join(python_unittest_results_directory, "results-stylesheet.css"))
6771 else:
6872 self._tool.executive.run_and_throw_if_fail(python_unittests_command, cwd=self._tool.scm().checkout_root)
6973