asfgit closed pull request #63: IGNITE-10181 [Tc Bot] Add fail-rate handling for test's page
URL: https://github.com/apache/ignite-teamcity-bot/pull/63 This is a PR merged from a forked repository. As GitHub hides the original diff on merge, it is displayed below for the sake of provenance: As this is a foreign pull request (from a fork), the diff is supplied below (as it won't show otherwise due to GitHub magic): diff --git a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java index e85d34cd..17abef06 100644 --- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java +++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/web/model/hist/BuildsHistory.java @@ -73,7 +73,7 @@ private Date untilDateFilter; /** */ - private Map<String, Set<String>> mergedTestsBySuites = new ConcurrentHashMap<>(); + private Map<String, Map<String, Float>> mergedTestsBySuites = new ConcurrentHashMap<>(); /** */ private boolean skipTests; @@ -88,14 +88,14 @@ private static final Logger logger = LoggerFactory.getLogger(BuildsHistory.class); /** */ - public void initialize(ICredentialsProv prov, ServletContext context) { - final IStringCompactor compactor = CtxListener.getInjector(context).getInstance(IStringCompactor.class); + public void initialize(ICredentialsProv prov, ServletContext ctx) { + final IStringCompactor compactor = CtxListener.getInjector(ctx).getInstance(IStringCompactor.class); - ITcHelper tcHelper = CtxListener.getTcHelper(context); + ITcHelper tcHelper = CtxListener.getTcHelper(ctx); ITeamcity teamcity = tcHelper.server(srvId, prov); - ITeamcityIgnitedProvider tcIgnitedProv = CtxListener.getInjector(context) + ITeamcityIgnitedProvider tcIgnitedProv = CtxListener.getInjector(ctx) .getInstance(ITeamcityIgnitedProvider.class); ITeamcityIgnited ignitedTeamcity = tcIgnitedProv.server(srvId, prov); @@ -118,10 +118,10 @@ public void initialize(ICredentialsProv prov, ServletContext context) { if (!skipTests) initFailedTests(teamcity, validBuilds); - ObjectMapper objectMapper = new ObjectMapper(); + ObjectMapper objMapper = new ObjectMapper(); try { - mergedTestsJson = objectMapper.writeValueAsString(mergedTestsBySuites); + mergedTestsJson = objMapper.writeValueAsString(mergedTestsBySuites); } catch (JsonProcessingException e) { throw new RuntimeException(e); } @@ -133,7 +133,7 @@ private void initStatistics(IStringCompactor compactor, ITeamcity teamcity, ITea List<Future<BuildStatisticsSummary>> buildStaticsFutures = new ArrayList<>(); for (int buildId : buildIdsWithConditions.keySet()) { - Future<BuildStatisticsSummary> buildFuture = CompletableFuture.supplyAsync(() -> { + Future<BuildStatisticsSummary> buildFut = CompletableFuture.supplyAsync(() -> { BuildStatisticsSummary buildsStatistic = new BuildStatisticsSummary(buildId); buildsStatistic.isValid = buildIdsWithConditions.get(buildId); buildsStatistic.initialize(compactor, ignited); @@ -141,7 +141,7 @@ private void initStatistics(IStringCompactor compactor, ITeamcity teamcity, ITea return buildsStatistic; }, teamcity.getExecutor()); - buildStaticsFutures.add(buildFuture); + buildStaticsFutures.add(buildFut); } buildStaticsFutures.forEach(new Consumer <Future<BuildStatisticsSummary>>() { @@ -192,7 +192,7 @@ private void initFailedTests(ITeamcity teamcity, List<Integer> buildIds) { List<Future<Void>> buildProcessorFutures = new ArrayList<>(); for (int buildId : buildIds) { - Future<Void> buildFuture = CompletableFuture.supplyAsync(() -> { + Future<Void> buildFut = CompletableFuture.supplyAsync(() -> { Map<Integer, String> configurations = getConfigurations(teamcity, buildId); Build build = teamcity.getBuild(teamcity.getBuildHrefById(buildId)); @@ -206,26 +206,31 @@ private void initFailedTests(ITeamcity teamcity, List<Integer> buildIds) { if(configurationName == null) continue; - Set<String> tests = mergedTestsBySuites.computeIfAbsent(configurationName, - k -> new HashSet<>()); + Map<String, Float> tests = mergedTestsBySuites.computeIfAbsent(configurationName, + k -> new HashMap<>()); - if (!tests.add(testOccurrence.getName())) - continue; + String testName = testOccurrence.getName(); + + if (!tests.containsKey(testName)) { + tests.put(testName, 0F); + + FullQueryParams key = new FullQueryParams(); - FullQueryParams key = new FullQueryParams(); + key.setServerId(srvId); + key.setProjectId(projectId); + key.setTestName(testOccurrence.getName()); + key.setSuiteId(configurationName); - key.setServerId(srvId); - key.setProjectId(projectId); - key.setTestName(testOccurrence.getName()); - key.setSuiteId(configurationName); + teamcity.getTestRef(key); + } - teamcity.getTestRef(key); + tests.put(testName, tests.get(testName) + 1F / buildIds.size()); } return null; }, teamcity.getExecutor()); - buildProcessorFutures.add(buildFuture); + buildProcessorFutures.add(buildFut); } buildProcessorFutures.forEach(v -> { diff --git a/ignite-tc-helper-web/src/main/webapp/comparison.html b/ignite-tc-helper-web/src/main/webapp/comparison.html index 4a5c37c8..9d979771 100644 --- a/ignite-tc-helper-web/src/main/webapp/comparison.html +++ b/ignite-tc-helper-web/src/main/webapp/comparison.html @@ -152,13 +152,15 @@ <td class="total data 2" id="RunsCount2"></td> </tr> </table><br> -<table style="table-layout: fixed" id="testsTable" class="testsTable"> +<table id="testsTable" class="testsTable"> <tbody> <tr> - <th class="failedTestsHeader" width="13%">FAILED TESTS</th> - <th width="3%"><div class="switch-btn tests"></div></th> - <th width="42%"></th> - <th width="42%"></th> + <th class="testsTableTitleHeader">FAILED TESTS</th> + <th class="testsTableBtnHeader"><div class="switch-btn tests"></div></th> + <th class="testsTableDataHeader1"></th> + <th class="testsTableDataHeader2">Fail-rate treshold: + <input id="treshold" class="treshold" type="number" min="0" max="100" value="0" onchange="refreshTests()">% + </th> </tr> </tbody> </table> @@ -175,10 +177,16 @@ <div id="version"></div> <script> + const FAIL_RATE_DIFF_TRESHOLD = 0.1; + let invalidInclude = false, markBuildId = 0, testsTrigger = false; + function refreshTests() { + printTests(generateTestsResultsComparison(mergedTestsResults)); + } + function getDateFewWeeksAgo(numberOfWeeksAgo) { let date = new Date(); @@ -350,7 +358,7 @@ }); } - function mergeSuits(results) { + function mergeSuites(results) { let mergedSuites = new Set(); for (let key of Object.keys(results)) { @@ -364,19 +372,17 @@ function printTests(results) { $(TESTS_TABLE + " tr:not(:first-child)").remove(); - let markedRow = true; - - for (let suite of mergeSuits(results).sort()) { + for (let suite of mergeSuites(results).sort()) { let suiteName = suite.split('_').filter((value, index) => index != 0).join('_'); let testsCntCells = ''; let testsCells = ''; for (let key of Object.keys(results)) { let obj = results[key]; - let testLength = !obj.hasOwnProperty(suite) || obj[suite].length == 0 ? - '' : obj[suite].length; + let testsCnt = !obj.hasOwnProperty(suite) || Object.keys(obj[suite]).length == 0 ? + '' : Object.keys(obj[suite]).length; - testsCntCells = testsCntCells + '<td class="testsCntCell"><p id="' + suite + '">' + testLength + '</p></td>'; + testsCntCells = testsCntCells + '<td class="testsCntCell"><p id="' + suite + '">' + testsCnt + '</p></td>'; testsCells = testsCells + '<td class="testsCell">' + getSuiteTestsHtml(results, suite, key) + '</td>' } @@ -391,57 +397,68 @@ } } - function generateCompareTestsResults(results) { - let compareTestsResults = {}; + function generateTestsResultsComparison(results) { + let testsResultsComparison = {}; for (let key of Object.keys(results)) { - let uniqueObj = {}; + let obj = {}; for (let suite of Object.keys(results[key])) { - let allTests = []; + let otherTests = {}; - for (let key2 of Object.keys(results)) { - if (key == key2) + for (let otherKey of Object.keys(results)) { + if (key == otherKey) continue; - allTests = allTests.concat(results[key2][suite]); + otherTests = Object.assign({}, results[otherKey][suite]); } - let uniqTests = results[key][suite].filter(function(test) { - return allTests.indexOf(test) == -1; - }); + let newFailedTests = {}; - if (uniqTests.length != 0) - uniqueObj[suite] = uniqTests; + for (let testName of Object.keys(results[key][suite])) { + let failRate = results[key][suite][testName]; + let otherFailRate = otherTests[testName]; + + if ((otherFailRate == null || failRate - otherFailRate > FAIL_RATE_DIFF_TRESHOLD) + && failRate > $('#treshold').val()/100) + newFailedTests[testName] = failRate; + } + + if (Object.keys(newFailedTests).length != 0) + obj[suite] = newFailedTests; } - compareTestsResults[key] = uniqueObj; + testsResultsComparison[key] = obj; } - return compareTestsResults; + return testsResultsComparison; } function getSuiteTestsHtml(results, suite, key) { - if (!results[key].hasOwnProperty(suite) || results[key][suite].length === 0) + if (!results[key].hasOwnProperty(suite) || Object.keys(results[key][suite]).length == 0) return ''; - let res = '<body><div id="' + suite + key + '"style="cursor: default; margin-left: 10px;">'; + let res = '<table class="innerTestTable">\n'; - for (let test of results[key][suite].sort()) { - let list = test.toString().split("."); + for (let testName of Object.keys(results[key][suite]).sort()) { + let list = testName.toString().split("."); if (list.length < 2) - list = test.toString().split(":"); + list = testName.toString().split(":"); - let testName = list.pop(); + let testMethodName = list.pop(); let testClass = list.pop(); - - res += '<p align="left" title="' + test + '">' + testClass + '.' + testName + - '<a href="#" onclick="getTestRef(\'' + test + '\'' + ',\'' + suite + '\'); return false;">' + - ' >></a>' + '</p>' + let failRate = results[key][suite][testName]; + + res += '<tr>' + + '<td class="innerTestName"><p title="' + testName + '">' + testClass + '.' + testMethodName + '</p></td>' + + '<td class="innerFailRate"><p title="Test\'s fail-rate for corresponding date period">' + + Number((failRate * 100).toFixed(1)) + '%</p></td>' + + '<td class="innerTcLink"><a href="#" onclick="getTestRef(\'' + + testName + '\',\'' + suite + '\'); return false;"> >></a></td></tr>'; } - res += '</div></body>'; + res += '</table>'; return res; } @@ -571,7 +588,7 @@ printImportantMessage(num, "#ff0000", "Invalid server response. Unable to parse JSON"); } - printTests(generateCompareTestsResults(mergedTestsResults)); + printTests(generateTestsResultsComparison(mergedTestsResults)); }, error: showErrInLoadStatus, timeout: 1800000 @@ -1006,7 +1023,7 @@ updateColumn(2); if (isDefinedAndFilled(mergedTestsResults)) - printTests(generateCompareTestsResults(mergedTestsResults)); + printTests(generateTestsResultsComparison(mergedTestsResults)); } function multiFormat(date) { diff --git a/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css b/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css index 77291923..13d83ed0 100644 --- a/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css +++ b/ignite-tc-helper-web/src/main/webapp/css/style-1.5.css @@ -313,6 +313,8 @@ form li:after } .testsCell { + padding-right: 2%; + padding-left: 2%; cursor: default; word-wrap: break-word; vertical-align: top; @@ -337,20 +339,72 @@ form li:after } .testsTable { + table-layout: fixed; width: 96%; border-collapse: collapse; margin-left: 2%; margin-right: 2%; } -.testsTable tr:nth-child(4n + 2) { - background-color: #fafaff; +.innerTestName { + width: 85%; + padding-right: 2%; + vertical-align: middle; + text-align: left; } -.failedTestsHeader { +.innerFailRate { + width: 10%; vertical-align: middle; + text-align: center; +} + +.innerTcLink { + width: 5%; + vertical-align: middle; + text-align: center; +} + +.testsTableBtnHeader { + width: 3%; + vertical-align: middle; +} + +.testsTableDataHeader1 { + width: 42%; + vertical-align: middle; + text-align: center; +} + +.testsTableDataHeader2 { + width: 42%; + vertical-align: middle; + text-align: right; +} + +.treshold { + width: 8%; +} + +.innerTestTable { + table-layout: fixed; + width: 96%; + border-collapse: collapse; + margin-left: 2%; + margin-right: 2%; +} + +.testsTable tr.testsCntRow:nth-child(4n + 2) { + background-color: #fafaff; +} + +.testsTableTitleHeader { text-align: left; - padding: 5px + width: 13%; + vertical-align: middle; + padding-left: 5px; + padding-bottom: 10px; + padding-top: 10px; } td.details-control { ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [hidden email] With regards, Apache Git Services |
Free forum by Nabble | Edit this page |