Skip to content
Permalink
Browse files
Merge pull request #76 from abayer/jenkins-27395-mk2
[JENKINS-27395] Add a junitResults step
  • Loading branch information
abayer committed Oct 17, 2017
2 parents 187cb92 + c6f5827 commit 5ae9ec10480d92075f03944462d8a90c8755ed86
Showing with 2,212 additions and 114 deletions.
  1. +1 −0 Jenkinsfile
  2. +84 −4 pom.xml
  3. +58 −5 src/main/java/hudson/tasks/junit/CaseResult.java
  4. +27 −8 src/main/java/hudson/tasks/junit/JUnitParser.java
  5. +32 −15 src/main/java/hudson/tasks/junit/JUnitResultArchiver.java
  6. +15 −0 src/main/java/hudson/tasks/junit/JUnitTask.java
  7. +171 −33 src/main/java/hudson/tasks/junit/SuiteResult.java
  8. +187 −27 src/main/java/hudson/tasks/junit/TestResult.java
  9. +1 −1 src/main/java/hudson/tasks/junit/TestResultAction.java
  10. +46 −0 src/main/java/hudson/tasks/junit/TestResultSummary.java
  11. +156 −0 src/main/java/hudson/tasks/junit/pipeline/JUnitResultsStep.java
  12. +80 −0 src/main/java/hudson/tasks/junit/pipeline/JUnitResultsStepExecution.java
  13. +102 −0 src/main/java/hudson/tasks/test/PipelineBlockWithTests.java
  14. +83 −0 src/main/java/hudson/tasks/test/TabulatedResult.java
  15. +16 −4 src/main/java/hudson/tasks/test/TestResultParser.java
  16. +30 −0 src/main/resources/hudson/tasks/junit/pipeline/JUnitResultsStep/config.jelly
  17. +2 −1 src/test/java/hudson/tasks/junit/JUnitParserTest.java
  18. +5 −0 src/test/java/hudson/tasks/junit/JUnitResultArchiverTest.java
  19. +1 −1 src/test/java/hudson/tasks/junit/SuiteResult2Test.java
  20. +3 −3 src/test/java/hudson/tasks/junit/SuiteResultTest.java
  21. +12 −12 src/test/java/hudson/tasks/junit/TestResultTest.java
  22. +397 −0 src/test/java/hudson/tasks/junit/pipeline/JUnitResultsStepTest.java
  23. +11 −0 src/test/resources/hudson/tasks/junit/pipeline/junit-report-testTrends-first-1.xml
  24. +301 −0 src/test/resources/hudson/tasks/junit/pipeline/junit-report-testTrends-first-2.xml
  25. +301 −0 src/test/resources/hudson/tasks/junit/pipeline/junit-report-testTrends-first-3.xml
  26. +30 −0 src/test/resources/hudson/tasks/junit/pipeline/junit-report-testTrends-second-1.xml
  27. +30 −0 src/test/resources/hudson/tasks/junit/pipeline/junit-report-testTrends-second-2.xml
  28. +30 −0 src/test/resources/hudson/tasks/junit/pipeline/junit-report-testTrends-second-3.xml
@@ -0,0 +1 @@
buildPlugin(jenkinsVersions: [null, '2.60.1'], platforms: ['linux']) // Tests need to be refactored to run on Windows
88 pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>2.33</version>
<version>2.36</version>
<relativePath />
</parent>
<artifactId>junit</artifactId>
@@ -13,8 +13,11 @@
<description>Allows JUnit-format test results to be published.</description>
<url>http://wiki.jenkins-ci.org/display/JENKINS/JUnit+Plugin</url>
<properties>
<jenkins.version>1.580.1</jenkins.version>
<java.level>6</java.level>
<jenkins.version>2.7.3</jenkins.version>
<java.level>7</java.level>
<no-test-jar>false</no-test-jar>
<workflow-cps.version>2.37</workflow-cps.version>
<workflow-support.version>2.14</workflow-support.version>
</properties>
<licenses>
<license>
@@ -44,7 +47,34 @@
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.2</version>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-step-api</artifactId>
<version>2.12</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>variant</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>2.22</version>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.30</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
@@ -64,5 +94,55 @@
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>${workflow-cps.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.11.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>${workflow-cps.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<version>2.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>${workflow-support.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>${workflow-support.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>pipeline-stage-step</artifactId>
<version>2.2</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.13</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -25,7 +25,9 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.util.TextFile;
import org.apache.commons.collections.iterators.ReverseListIterator;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.jvnet.localizer.Localizable;

import hudson.model.Run;
@@ -34,11 +36,15 @@
import org.dom4j.Element;
import org.kohsuke.stapler.export.Exported;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.logging.Logger;

import static java.util.Collections.emptyList;
@@ -256,10 +262,25 @@ private static String getSkippedMessage(Element testCase) {
return message;
}

public String getDisplayName() {
public String getTransformedTestName() {
return TestNameTransformer.getTransformedName(testName);
}

public String getDisplayName() {
// Only prepend the enclosing flow node names if there are any and the run this is in has multiple blocks directly containing
// test results.
if (!getEnclosingFlowNodeNames().isEmpty()) {
Run<?, ?> r = getRun();
if (r != null) {
TestResultAction action = r.getAction(TestResultAction.class);
if (action != null && action.getResult().hasMultipleBlocksForRun(r.getExternalizableId())) {
return StringUtils.join(new ReverseListIterator(getEnclosingFlowNodeNames()), " / ") + " / " + getTransformedTestName();
}
}
}
return getTransformedTestName();
}

/**
* Gets the name of the test, which is returned from {@code TestCase.getName()}
*
@@ -294,7 +315,7 @@ public float getDuration() {
if (safeName != null) {
return safeName;
}
StringBuilder buf = new StringBuilder(testName);
StringBuilder buf = new StringBuilder(getDisplayName());
for( int i=0; i<buf.length(); i++ ) {
char ch = buf.charAt(i);
if(!Character.isJavaIdentifierPart(ch))
@@ -446,7 +467,7 @@ public CaseResult getPreviousResult() {
if (parent == null) return null;
SuiteResult pr = parent.getPreviousResult();
if(pr==null) return null;
return pr.getCase(getName());
return pr.getCase(getDisplayName());
}

/**
@@ -553,15 +574,47 @@ public String getSkippedMessage() {
public SuiteResult getSuiteResult() {
return parent;
}


@CheckForNull
public String getFlowNodeId() {
if (parent != null) {
return parent.getNodeId();
}
return null;
}

@Nonnull
public List<String> getEnclosingFlowNodeIds() {
List<String> enclosing = new ArrayList<>();
if (parent != null) {
enclosing.addAll(parent.getEnclosingBlocks());
}
return enclosing;
}

@Nonnull
public List<String> getEnclosingFlowNodeNames() {
List<String> enclosing = new ArrayList<>();
if (parent != null) {
enclosing.addAll(parent.getEnclosingBlockNames());
}
return enclosing;
}

@Override
public Run<?,?> getRun() {
SuiteResult sr = getSuiteResult();
if (sr==null) {
LOGGER.warning("In getOwner(), getSuiteResult is null"); return null; }
hudson.tasks.junit.TestResult tr = sr.getParent();
if (tr==null) {
LOGGER.warning("In getOwner(), suiteResult.getParent() is null."); return null; }
if (sr.getRunId() != null) {
return Run.fromExternalizableId(sr.getRunId());
} else {
LOGGER.warning("In getOwner(), suiteResult.getParent() is null and suiteResult.getRunId() is null.");
return null;
}
}
return tr.getRun();
}

@@ -32,11 +32,15 @@

import java.io.IOException;
import java.io.File;
import java.util.List;

import jenkins.MasterToSlaveFileCallable;

import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.DirectoryScanner;

import javax.annotation.CheckForNull;

/**
* Parse some JUnit xml files and generate a TestResult containing all the
* results parsed.
@@ -88,20 +92,27 @@ public String getTestResultLocationMessage() {
return (TestResult) super.parse(testResultLocations, build, launcher, listener);
}

@Deprecated
@Override
public TestResult parseResult(String testResultLocations, Run<?,?> build, FilePath workspace,
Launcher launcher, TaskListener listener)
throws InterruptedException, IOException {
return parseResult(testResultLocations, build, null, null, workspace, launcher, listener);
}

@Override
public TestResult parseResult(String testResultLocations,
Run<?,?> build, FilePath workspace, Launcher launcher,
TaskListener listener)
throws InterruptedException, IOException
{
public TestResult parseResult(String testResultLocations, Run<?,?> build, @CheckForNull String nodeId,
List<String> enclosingBlocks, FilePath workspace, Launcher launcher,
TaskListener listener) throws InterruptedException, IOException {
final long buildTime = build.getTimestamp().getTimeInMillis();
final long timeOnMaster = System.currentTimeMillis();

// [BUG 3123310] TODO - Test Result Refactor: review and fix TestDataPublisher/TestAction subsystem]
// also get code that deals with testDataPublishers from JUnitResultArchiver.perform

return workspace.act(new ParseResultCallable(testResultLocations, buildTime,
timeOnMaster, keepLongStdio, allowEmptyResults));
timeOnMaster, keepLongStdio, allowEmptyResults,
build.getExternalizableId(), nodeId, enclosingBlocks));
}

private static final class ParseResultCallable extends MasterToSlaveFileCallable<TestResult> {
@@ -110,14 +121,21 @@ public TestResult parseResult(String testResultLocations,
private final long nowMaster;
private final boolean keepLongStdio;
private final boolean allowEmptyResults;
private final String runId;
private final String nodeId;
private final List<String> enclosingBlocks;

private ParseResultCallable(String testResults, long buildTime, long nowMaster,
boolean keepLongStdio, boolean allowEmptyResults) {
boolean keepLongStdio, boolean allowEmptyResults, String runId, @CheckForNull String nodeId,
List<String> enclosingBlocks) {
this.buildTime = buildTime;
this.testResults = testResults;
this.nowMaster = nowMaster;
this.keepLongStdio = keepLongStdio;
this.allowEmptyResults = allowEmptyResults;
this.runId = runId;
this.nodeId = nodeId;
this.enclosingBlocks = enclosingBlocks;
}

public TestResult invoke(File ws, VirtualChannel channel) throws IOException {
@@ -129,7 +147,8 @@ public TestResult invoke(File ws, VirtualChannel channel) throws IOException {

String[] files = ds.getIncludedFiles();
if (files.length > 0) {
result = new TestResult(buildTime + (nowSlave - nowMaster), ds, keepLongStdio);
result = new TestResult(buildTime + (nowSlave - nowMaster), ds, keepLongStdio, runId, nodeId,
enclosingBlocks);
result.tally();
} else {
if (this.allowEmptyResults) {

0 comments on commit 5ae9ec1

Please sign in to comment.