Skip to content

Commit

Permalink
TestFailures: Support showing partial results for jobs that succeed i…
Browse files Browse the repository at this point in the history
…n a view

Exclude jobs for which api calls fail as opposed to the entire view.
  • Loading branch information
damienbiggs committed Jun 4, 2021
1 parent 4182619 commit 540edbe
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 29 deletions.
19 changes: 17 additions & 2 deletions config/src/main/java/com/vmware/jenkins/domain/Job.java
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,20 @@ public boolean addTestResultsToMasterList() {
log.info("Adding presumed pass result for test {} in build {}", result.classAndTestName(), build.buildNumber);
result.addTestResult(new TestResult(result, build, PRESUMED_PASS));
}));

return presumedPassResultsAdded.get();
}

public boolean addPassResultsForSavedTestResults(JobBuild stableBuild) {
AtomicBoolean passResultsAdded = new AtomicBoolean(false);
testResults.stream().filter(result -> !result.containsBuildNumbers(stableBuild.buildNumber)).forEach(result -> {
passResultsAdded.set(true);
log.info("Adding pass result for test {} in build {}", result.classAndTestName(), stableBuild.buildNumber);
result.addTestResult(new TestResult(result, stableBuild, PASS));
});
return passResultsAdded.get();
}

public void saveFetchedBuildsInfo() {
if (dbUtils == null || (CollectionUtils.isEmpty(fetchedResults))) {
return;
Expand All @@ -228,8 +239,8 @@ public void saveFetchedBuildsInfo() {
savedBuilds = dbUtils.query(JobBuild.class, "SELECT * from JOB_BUILD WHERE JOB_ID = ? ORDER BY BUILD_NUMBER DESC", id);
}

public void saveTestResultsToDb(boolean presumedPassedResultsAdded) {
if (dbUtils == null || (CollectionUtils.isEmpty(fetchedResults) && !presumedPassedResultsAdded)) {
public void saveTestResultsToDb(boolean passResultsAdded) {
if (dbUtils == null || (CollectionUtils.isEmpty(fetchedResults) && !passResultsAdded)) {
return;
}

Expand Down Expand Up @@ -277,6 +288,10 @@ public boolean hasSavedBuild(int buildNumber) {
return savedBuilds != null && savedBuilds.stream().anyMatch(build -> build.buildNumber == buildNumber);
}

public boolean hasSavedBuilds() {
return CollectionUtils.isNotEmpty(savedBuilds);
}

public void removeOldBuilds(int maxJenkinsBuildsToCheck) {
if (dbUtils == null) {
return;
Expand Down
4 changes: 0 additions & 4 deletions config/src/main/java/com/vmware/jenkins/domain/JobView.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ public List<Job> usableJobs(int maxJenkinsBuildsToCheck) {
log.info("Skipping {} as there are no recent completed builds", job.name);
return false;
}
if (job.lastBuildWasSuccessful()) {
log.info("Skipping {} as most recent build {} was successful", job.name, job.lastStableBuild.buildNumber);
return false;
}
if (job.lastUnstableBuild == null) {
log.info("Skipping {} as there are no recent unstable builds", job.name);
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,17 +151,27 @@ private void saveResultsPageForView(HomePage.View view, boolean includeViewsLink
view.failingTestsCount = failingTestMethods.values().stream().mapToInt(List::size).sum();
log.info("{} failing tests found for view {}", view.failingTestsCount, view.name);

final StringBuilder jobFragments = new StringBuilder("");
final AtomicInteger counter = new AtomicInteger();
failingTestMethods.keySet().stream().sorted(comparing(jobDetails -> jobDetails.name)).forEach(key -> {
List<TestResult> failingTests = failingTestMethods.get(key);
String jobFragment = createJobFragment(counter.getAndIncrement(), key, failingTests);
if (jobFragments.length() > 0) {
jobFragments.append("\n");
}
jobFragments.append(jobFragment);
});
String jobsResultsHtml = failingTestMethods.keySet().stream().sorted(comparing(jobDetails -> jobDetails.name)).map(job -> {
List<TestResult> failingTests = failingTestMethods.get(job);
return createJobFragment(counter.getAndIncrement(), job, failingTests);
}).collect(Collectors.joining("\n"));

String resultsPage = createTestResultsHtmlPage(view, includeViewsLink, failingTestMethods, jobsResultsHtml);

File destinationFile = new File(fileSystemConfig.destinationFile);
if (destinationFile.exists() && destinationFile.isDirectory()) {
File failurePageFile = new File(fileSystemConfig.destinationFile + File.separator + view.htmlFileName());
log.info("Saving test results to {}", failurePageFile);
IOUtils.write(failurePageFile, resultsPage);
} else {
log.info("Saving test results to {}", destinationFile);
IOUtils.write(destinationFile, resultsPage);
}
viewPadder.infoTitle();
}

private String createTestResultsHtmlPage(HomePage.View view, boolean includeViewsLink, Map<Job, List<TestResult>> failingTestMethods, String jobsTestResultsHtml) {
String resultsPage;
String footer = "Generated at " + generationDate;
if (includeViewsLink) {
Expand All @@ -170,25 +180,15 @@ private void saveResultsPageForView(HomePage.View view, boolean includeViewsLink
if (!failingTestMethods.isEmpty()) {
String failuresPage = new ClasspathResource("/testFailuresTemplate/testFailuresWebPage.html", this.getClass()).getText();
resultsPage = failuresPage.replace("#viewName", view.viewNameWithFailureCount());
resultsPage = resultsPage.replace("#body", jobFragments.toString());
resultsPage = resultsPage.replace("#body", jobsTestResultsHtml);
resultsPage = resultsPage.replace("#footer", footer);
log.trace("Test Failures for view {}:\n{}", view.name, resultsPage);
} else {
String allPassedPage = new ClasspathResource("/testFailuresTemplate/noTestFailures.html", this.getClass()).getText();
resultsPage = allPassedPage.replace("#viewName", view.name);
resultsPage = resultsPage.replace("#footer", footer);
}

File destinationFile = new File(fileSystemConfig.destinationFile);
if (destinationFile.exists() && destinationFile.isDirectory()) {
File failurePageFile = new File(fileSystemConfig.destinationFile + File.separator + view.htmlFileName());
log.info("Saving test results to {}", failurePageFile);
IOUtils.write(failurePageFile, resultsPage);
} else {
log.info("Saving test results to {}", destinationFile);
IOUtils.write(destinationFile, resultsPage);
}
viewPadder.infoTitle();
return resultsPage;
}

private Map<Job, List<TestResult>> findAllRealFailingTests(JobView jobView) {
Expand Down Expand Up @@ -222,8 +222,9 @@ private Map<Job, List<TestResult>> findAllRealFailingTests(JobView jobView) {

usableJobs.stream().filter(job -> !failedJobs.contains(job)).forEach(job -> {
job.saveFetchedBuildsInfo();
boolean presumedPassedResultsAdded = job.addTestResultsToMasterList();
job.saveTestResultsToDb(presumedPassedResultsAdded);
boolean passResultsAdded = addPassResultsIfNeeded(job);
boolean presumedPassResultsAdded = job.addTestResultsToMasterList();
job.saveTestResultsToDb(passResultsAdded || presumedPassResultsAdded);
job.removeOldBuilds(jenkinsConfig.maxJenkinsBuildsToCheck);

List<TestResult> failingTests = job.createFailingTestsList(jenkinsConfig.maxJenkinsBuildsToCheck);
Expand All @@ -238,8 +239,21 @@ private Map<Job, List<TestResult>> findAllRealFailingTests(JobView jobView) {
return allFailingTests;
}

private boolean addPassResultsIfNeeded(Job job) {
boolean passResultsAdded = false;
if (dbUtils != null && job.hasSavedBuilds() && job.lastBuildWasSuccessful() && !job.hasSavedBuild(job.lastStableBuild.buildNumber)) {
JobBuild stableBuild = jenkinsExecutor.execute(jenkins -> jenkins.getJobBuildDetails(job.name, job.lastStableBuild.buildNumber));
dbUtils.insert(stableBuild);
passResultsAdded = job.addPassResultsForSavedTestResults(stableBuild);
}
return passResultsAdded;
}

private void fetchLatestTestResults(Job job, int lastFetchAmount) {
job.fetchedResults = Collections.emptyList();
if (job.lastBuildWasSuccessful()) {
log.info("No need to fetch latest results for job {} as last build was successful", job);
}
int latestUsableBuildNumber = job.latestUsableBuildNumber();
if (lastFetchAmount >= jenkinsConfig.maxJenkinsBuildsToCheck && job.hasSavedBuild(latestUsableBuildNumber)) {
log.info("Saved builds for {} already include latest build {}", job.name, latestUsableBuildNumber);
Expand Down
8 changes: 8 additions & 0 deletions utils/src/main/java/com/vmware/util/db/DbUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ public <T> List<T> query(Connection connection, Class<T> recordClass, String que

}

public <T> void insert(T record) {
try (Connection connection = createConnection()) {
insert(connection, record);
} catch (SQLException se) {
throw new RuntimeException(se);
}
}

public <T> void insert(Connection connection, T record) {
insertIfNeeded(connection, record, null);
}
Expand Down

0 comments on commit 540edbe

Please sign in to comment.