You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dp...@apache.org on 2018/11/10 17:08:00 UTC

[ignite-teamcity-bot] branch master updated: IGNITE-10181 [Tc Bot] Add fail-rate handling for test's page - Fixes #63.

This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git


The following commit(s) were added to refs/heads/master by this push:
     new a52f7cd  IGNITE-10181 [Tc Bot] Add fail-rate handling for test's page - Fixes #63.
a52f7cd is described below

commit a52f7cd6e5fc3248e4c291eb9974ed9b4a70656d
Author: ololo3000 <pm...@gmail.com>
AuthorDate: Sat Nov 10 20:07:51 2018 +0300

    IGNITE-10181 [Tc Bot] Add fail-rate handling for test's page - Fixes #63.
    
    Signed-off-by: Dmitriy Pavlov <dp...@apache.org>
---
 .../ignite/ci/web/model/hist/BuildsHistory.java    | 47 ++++++-----
 .../src/main/webapp/comparison.html                | 95 +++++++++++++---------
 .../src/main/webapp/css/style-1.5.css              | 62 +++++++++++++-
 3 files changed, 140 insertions(+), 64 deletions(-)

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 e85d34c..17abef0 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 @@ public class BuildsHistory {
     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 @@ public class BuildsHistory {
     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 class BuildsHistory {
         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 @@ public class BuildsHistory {
         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 @@ public class BuildsHistory {
                 return buildsStatistic;
             }, teamcity.getExecutor());
 
-            buildStaticsFutures.add(buildFuture);
+            buildStaticsFutures.add(buildFut);
         }
 
         buildStaticsFutures.forEach(new Consumer <Future<BuildStatisticsSummary>>() {
@@ -192,7 +192,7 @@ public class BuildsHistory {
         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 @@ public class BuildsHistory {
                     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 4a5c37c..9d97977 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;">' +
-                ' &gt&gt</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;"> &gt&gt</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 7729192..13d83ed 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 {