Skip to content

Commit

Permalink
Merge pull request #76 from abayer/jenkins-27395-mk2
Browse files Browse the repository at this point in the history
[JENKINS-27395] Add a junitResults step
  • Loading branch information
abayer committed Oct 17, 2017
2 parents 187cb92 + c6f5827 commit 5ae9ec1
Show file tree
Hide file tree
Showing 28 changed files with 2,212 additions and 114 deletions.
1 change: 1 addition & 0 deletions Jenkinsfile
@@ -0,0 +1 @@
buildPlugin(jenkinsVersions: [null, '2.60.1'], platforms: ['linux']) // Tests need to be refactored to run on Windows
88 changes: 84 additions & 4 deletions pom.xml
Expand Up @@ -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>
Expand All @@ -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>
Expand Down Expand Up @@ -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>
Expand All @@ -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>
63 changes: 58 additions & 5 deletions src/main/java/hudson/tasks/junit/CaseResult.java
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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()}
*
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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());
}

/**
Expand Down Expand Up @@ -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();
}

Expand Down
35 changes: 27 additions & 8 deletions src/main/java/hudson/tasks/junit/JUnitParser.java
Expand Up @@ -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.
Expand Down Expand Up @@ -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> {
Expand All @@ -110,14 +121,21 @@ private static final class ParseResultCallable extends MasterToSlaveFileCallable
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 {
Expand All @@ -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) {
Expand Down

0 comments on commit 5ae9ec1

Please sign in to comment.