package hudson.plugins.testng.util; import java.util.List; import hudson.model.Run; import hudson.plugins.testng.TestNGTestResultBuildAction; import hudson.plugins.testng.results.ClassResult; import hudson.plugins.testng.results.MethodResult; import hudson.plugins.testng.results.TestNGResult; /** * Utility methods around displaying results (esp history of results) * * @author nullin */ public class TestResultHistoryUtil { private TestResultHistoryUtil() {} /** * Gets the latest build before this one and returns it's test result. * * We'd rather make this list when needed otherwise if we cache these values * in the memory we will run out of memory * * @return previous build test results if the build exists and has a * {@link hudson.plugins.testng.TestNGTestResultBuildAction}, * otherwise returns an empty {@link hudson.plugins.testng.results.TestNGResult} * object. <b>Never returns {@code null}.</b> */ public static TestNGResult getPreviousBuildTestResults(Run<?, ?> owner) { // Doesn't make sense to return a build that is still running. // We can compare results with a previous build that completed Run<?, ?> previousBuild = owner.getPreviousCompletedBuild(); if (previousBuild != null && previousBuild.getAction(TestNGTestResultBuildAction.class) != null) { return previousBuild.getAction(TestNGTestResultBuildAction.class).getResult(); } else { return new TestNGResult(); } } /** * Summarizes the delta in tests and also displays a list of failed/skipped * tests and configuration methods. * * The list is returned as an HTML unordered list. * * @param action TestNG build action * @return summarized */ //TODO: move into Groovy/Jelly public static String toSummary(TestNGTestResultBuildAction action) { int prevFailedTestCount; int prevSkippedTestCount; int prevFailedConfigurationCount; int prevSkippedConfigurationCount; int prevTotalTestCount; Run<?,?> run = action.run; TestNGResult previousResult = TestResultHistoryUtil.getPreviousBuildTestResults(run); prevFailedTestCount = previousResult.getFailCount(); prevSkippedTestCount = previousResult.getSkipCount(); prevFailedConfigurationCount = previousResult.getFailedConfigCount(); prevSkippedConfigurationCount = previousResult.getSkippedConfigCount(); prevTotalTestCount = previousResult.getTotalCount(); TestNGResult tr = action.getResult(); return "<ul>" + diff(prevTotalTestCount, tr.getTotalCount(), "Total Tests") + diff(prevFailedTestCount, tr.getFailCount(), "Failed Tests") + printTestsUrls(tr.getFailedTests()) + diff(prevSkippedTestCount, tr.getSkipCount(), "Skipped Tests") + printTestsUrls(tr.getSkippedTests()) + diff(prevFailedConfigurationCount, tr.getFailedConfigCount(), "Failed Configurations") + printTestsUrls(tr.getFailedConfigs()) + diff(prevSkippedConfigurationCount, tr.getSkippedConfigCount(), "Skipped Configurations") + printTestsUrls(tr.getSkippedConfigs()) + "</ul>"; } private static String diff(long prev, long curr, String name) { if (prev == curr) { return "<li>" + name + ": " + curr + " (±0)</li>"; } else if (prev < curr) { return "<li>" + name + ": " + curr + " (+" + (curr - prev) + ")</li>"; } else { // if (a < b) return "<li>" + name + ": " + curr + " (-" + (prev - curr) + ")</li>"; } } /* <OL start="10"> <LI><a href="url">test_full_name</a></LI> </OL> */ private static String printTestsUrls(List<MethodResult> methodResults) { StringBuilder htmlStr = new StringBuilder(); htmlStr.append("<OL>"); if (methodResults != null && methodResults.size() > 0) { for (MethodResult methodResult : methodResults) { htmlStr.append("<LI>"); if (methodResult.getParent() instanceof ClassResult) { htmlStr.append("<a href=\"").append(methodResult.getUpUrl()); htmlStr.append("\">"); htmlStr.append(((ClassResult)methodResult.getParent()).getCanonicalName()); htmlStr.append(".").append(methodResult.getName()).append("</a>"); } else { htmlStr.append(methodResult.getName()); } htmlStr.append("</LI>"); } } htmlStr.append("</OL>"); return htmlStr.substring(0); } }