mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-11-08 01:26:03 +00:00
exposed JUnit test reports to the remote API.
git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@6944 71c3de6d-444a-0410-be80-ed276b4c234a
This commit is contained in:
1 parent
e0779a67ef
commit
9142dadd8a
12 files changed
+134
-12
No files matched your search
@@ -5,10 +5,10 @@ import hudson.maven.MavenBuild;
|
||||
import hudson.maven.MavenModule;
|
||||
import hudson.maven.MavenModuleSet;
|
||||
import hudson.maven.MavenModuleSetBuild;
|
||||
import hudson.model.Action;
|
||||
import hudson.tasks.test.AbstractTestResultAction;
|
||||
import hudson.tasks.test.AggregatedTestResultAction;
|
||||
import hudson.tasks.test.TestResultProjectAction;
|
||||
import hudson.model.Action;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -41,7 +41,7 @@ public class SurefireAggregatedReport extends AggregatedTestResultAction impleme
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MavenBuild resolveChild(Child child) {
|
||||
public MavenBuild resolveChild(Child child) {
|
||||
MavenModuleSet mms = (MavenModuleSet) owner.getProject();
|
||||
MavenModule m = mms.getModule(child.name);
|
||||
if(m!=null)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package hudson.tasks.junit;
|
||||
|
||||
import hudson.Util;
|
||||
import hudson.model.AbstractBuild;
|
||||
import org.dom4j.Element;
|
||||
import org.kohsuke.stapler.export.Exported;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.text.DecimalFormat;
|
||||
@@ -96,6 +96,7 @@ public final class CaseResult extends TestObject implements Comparable<CaseResul
|
||||
* <p>
|
||||
* Note that this may contain any URL-unfriendly character.
|
||||
*/
|
||||
@Exported
|
||||
public String getName() {
|
||||
return testName;
|
||||
}
|
||||
@@ -103,6 +104,7 @@ public final class CaseResult extends TestObject implements Comparable<CaseResul
|
||||
/**
|
||||
* Gets the duration of the test, in seconds
|
||||
*/
|
||||
// TODO: wait for stapler 1.60 to do this : @Exported
|
||||
public float getDuration() {
|
||||
return duration;
|
||||
}
|
||||
@@ -123,6 +125,7 @@ public final class CaseResult extends TestObject implements Comparable<CaseResul
|
||||
/**
|
||||
* Gets the class name of a test class.
|
||||
*/
|
||||
@Exported
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
@@ -160,6 +163,7 @@ public final class CaseResult extends TestObject implements Comparable<CaseResul
|
||||
* Gets the number of consecutive builds (including this)
|
||||
* that this test case has been failing.
|
||||
*/
|
||||
@Exported
|
||||
public int getAge() {
|
||||
if(isPassed())
|
||||
return 0;
|
||||
@@ -177,6 +181,7 @@ public final class CaseResult extends TestObject implements Comparable<CaseResul
|
||||
/**
|
||||
* If there was an error or a failure, this is the stack trace, or otherwise null.
|
||||
*/
|
||||
@Exported
|
||||
public String getErrorStackTrace() {
|
||||
return errorStackTrace;
|
||||
}
|
||||
@@ -233,6 +238,7 @@ public final class CaseResult extends TestObject implements Comparable<CaseResul
|
||||
return this.getFullName().compareTo(that.getFullName());
|
||||
}
|
||||
|
||||
@Exported(name="status") // because stapler notices suffix 's' and remove it
|
||||
public Status getStatus() {
|
||||
CaseResult pr = getPreviousResult();
|
||||
if(pr==null) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package hudson.tasks.junit;
|
||||
import hudson.model.AbstractBuild;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
import org.kohsuke.stapler.StaplerResponse;
|
||||
import org.kohsuke.stapler.export.Exported;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -47,6 +48,7 @@ public final class ClassResult extends TabulatedResult implements Comparable<Cla
|
||||
return "Test Result : "+getName();
|
||||
}
|
||||
|
||||
@Exported
|
||||
public String getName() {
|
||||
int idx = className.lastIndexOf('.');
|
||||
if(idx<0) return className;
|
||||
@@ -62,18 +64,22 @@ public final class ClassResult extends TabulatedResult implements Comparable<Cla
|
||||
}
|
||||
|
||||
|
||||
@Exported(name="child")
|
||||
public List<CaseResult> getChildren() {
|
||||
return cases;
|
||||
}
|
||||
|
||||
// TODO: wait for stapler 1.60 @Exported
|
||||
public float getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Exported
|
||||
public int getPassCount() {
|
||||
return passCount;
|
||||
}
|
||||
|
||||
@Exported
|
||||
public int getFailCount() {
|
||||
return failCount;
|
||||
}
|
||||
|
||||
@@ -3,16 +3,15 @@ package hudson.tasks.junit;
|
||||
import hudson.FilePath.FileCallable;
|
||||
import hudson.Launcher;
|
||||
import hudson.Util;
|
||||
import hudson.maven.MavenModuleSet;
|
||||
import hudson.maven.AbstractMavenProject;
|
||||
import hudson.matrix.MatrixAggregatable;
|
||||
import hudson.matrix.MatrixAggregator;
|
||||
import hudson.matrix.MatrixBuild;
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.Action;
|
||||
import hudson.model.BuildListener;
|
||||
import hudson.model.Descriptor;
|
||||
import hudson.model.Result;
|
||||
import hudson.model.*;
|
||||
import hudson.remoting.VirtualChannel;
|
||||
import hudson.tasks.Publisher;
|
||||
import hudson.tasks.BuildStepDescriptor;
|
||||
import hudson.tasks.test.TestResultAggregator;
|
||||
import hudson.tasks.test.TestResultProjectAction;
|
||||
import hudson.util.FormFieldValidator;
|
||||
@@ -106,7 +105,7 @@ public class JUnitResultArchiver extends Publisher implements Serializable, Matr
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static class DescriptorImpl extends Descriptor<Publisher> {
|
||||
public static class DescriptorImpl extends BuildStepDescriptor<Publisher> {
|
||||
public static final Descriptor<Publisher> DESCRIPTOR = new DescriptorImpl();
|
||||
|
||||
public DescriptorImpl() {
|
||||
@@ -131,5 +130,10 @@ public class JUnitResultArchiver extends Publisher implements Serializable, Matr
|
||||
public Publisher newInstance(StaplerRequest req) {
|
||||
return new JUnitResultArchiver(req.getParameter("junitreport_includes"));
|
||||
}
|
||||
|
||||
public boolean isApplicable(Class<? extends AbstractProject> jobType) {
|
||||
// for Maven we have SurefireArchiver that automatically kicks in.
|
||||
return !AbstractMavenProject.class.isAssignableFrom(jobType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package hudson.tasks.junit;
|
||||
import hudson.model.AbstractBuild;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
import org.kohsuke.stapler.StaplerResponse;
|
||||
import org.kohsuke.stapler.export.Exported;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -34,6 +35,7 @@ public final class PackageResult extends MetaTabulatedResult {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Exported
|
||||
public String getName() {
|
||||
return packageName;
|
||||
}
|
||||
@@ -56,14 +58,17 @@ public final class PackageResult extends MetaTabulatedResult {
|
||||
return "Class";
|
||||
}
|
||||
|
||||
// TODO: wait until stapler 1.60 to do this @Exported
|
||||
public float getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Exported
|
||||
public int getPassCount() {
|
||||
return passCount;
|
||||
}
|
||||
|
||||
@Exported
|
||||
public int getFailCount() {
|
||||
return failCount;
|
||||
}
|
||||
@@ -72,6 +77,7 @@ public final class PackageResult extends MetaTabulatedResult {
|
||||
return classes.get(name);
|
||||
}
|
||||
|
||||
@Exported(name="child")
|
||||
public Collection<ClassResult> getChildren() {
|
||||
return classes.values();
|
||||
}
|
||||
|
||||
@@ -2,15 +2,19 @@ package hudson.tasks.junit;
|
||||
|
||||
import hudson.model.AbstractBuild;
|
||||
import hudson.model.ModelObject;
|
||||
import hudson.model.Api;
|
||||
import hudson.Util;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.kohsuke.stapler.export.ExportedBean;
|
||||
|
||||
/**
|
||||
* Base class for all test result objects.
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
@ExportedBean
|
||||
public abstract class TestObject implements ModelObject, Serializable {
|
||||
public abstract AbstractBuild<?,?> getOwner();
|
||||
|
||||
@@ -35,6 +39,13 @@ public abstract class TestObject implements ModelObject, Serializable {
|
||||
return Util.getTimeSpanString((long)(getDuration()*1000));
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes this object through the remote API.
|
||||
*/
|
||||
public Api getApi() {
|
||||
return new Api(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces URL-unasfe characters.
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
import org.kohsuke.stapler.StaplerResponse;
|
||||
import org.kohsuke.stapler.export.Exported;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -157,26 +158,31 @@ public final class TestResult extends MetaTabulatedResult {
|
||||
return "Package";
|
||||
}
|
||||
|
||||
// TODO once stapler 1.60 is released: @Exported
|
||||
public float getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Exported(visibility=999)
|
||||
@Override
|
||||
public int getPassCount() {
|
||||
return totalTests-getFailCount();
|
||||
}
|
||||
|
||||
@Exported(visibility=999)
|
||||
@Override
|
||||
public int getFailCount() {
|
||||
return failedTests.size();
|
||||
}
|
||||
|
||||
@Exported
|
||||
@Override
|
||||
public List<CaseResult> getFailedTests() {
|
||||
return failedTests;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Exported(name="child")
|
||||
public Collection<PackageResult> getChildren() {
|
||||
return byPackages.values();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import hudson.tasks.test.AbstractTestResultAction;
|
||||
import hudson.util.StringConverter2;
|
||||
import hudson.util.XStream2;
|
||||
import org.kohsuke.stapler.StaplerProxy;
|
||||
import org.kohsuke.stapler.export.Exported;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -83,6 +84,7 @@ public class TestResultAction extends AbstractTestResultAction<TestResultAction>
|
||||
}
|
||||
|
||||
@Override
|
||||
@Exported
|
||||
public int getFailCount() {
|
||||
if(totalCount==null)
|
||||
getResult(); // this will compute the result
|
||||
@@ -90,6 +92,7 @@ public class TestResultAction extends AbstractTestResultAction<TestResultAction>
|
||||
}
|
||||
|
||||
@Override
|
||||
@Exported
|
||||
public int getTotalCount() {
|
||||
if(totalCount==null)
|
||||
getResult(); // this will compute the result
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jfree.data.category.CategoryDataset;
|
||||
import org.jfree.ui.RectangleInsets;
|
||||
import org.kohsuke.stapler.StaplerRequest;
|
||||
import org.kohsuke.stapler.StaplerResponse;
|
||||
import org.kohsuke.stapler.export.ExportedBean;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.IOException;
|
||||
@@ -34,6 +35,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
@ExportedBean
|
||||
public abstract class AbstractTestResultAction<T extends AbstractTestResultAction> implements HealthReportingAction {
|
||||
public final AbstractBuild<?,?> owner;
|
||||
|
||||
@@ -90,6 +92,25 @@ public abstract class AbstractTestResultAction<T extends AbstractTestResultActio
|
||||
return new HealthReport(score, description.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes this object to the remote API.
|
||||
*/
|
||||
public Api getApi() {
|
||||
return new Api(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object that represents the actual test result.
|
||||
* This method is used by the remote API so that the XML/JSON
|
||||
* that we are sending won't contain unnecessary indirection
|
||||
* (that is, {@link AbstractTestResultAction} in between.
|
||||
*
|
||||
* <p>
|
||||
* If such a concept doesn't make sense for a particular subtype,
|
||||
* return <tt>this</tt>.
|
||||
*/
|
||||
public abstract Object getResult();
|
||||
|
||||
/**
|
||||
* Gets the test result of the previous build, if it's recorded, or null.
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,10 @@ package hudson.tasks.test;
|
||||
|
||||
import hudson.maven.MavenBuild;
|
||||
import hudson.model.AbstractBuild;
|
||||
import org.kohsuke.stapler.export.Exported;
|
||||
import org.kohsuke.stapler.export.ExportedBean;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -12,6 +15,7 @@ import java.util.List;
|
||||
*
|
||||
* @author Kohsuke Kawaguchi
|
||||
*/
|
||||
@ExportedBean
|
||||
public abstract class AggregatedTestResultAction extends AbstractTestResultAction {
|
||||
private int failCount,totalCount;
|
||||
|
||||
@@ -53,14 +57,65 @@ public abstract class AggregatedTestResultAction extends AbstractTestResultActio
|
||||
this.children.add(new Child(getChildName(child),child.owner.number));
|
||||
}
|
||||
|
||||
@Exported
|
||||
public int getFailCount() {
|
||||
return failCount;
|
||||
}
|
||||
|
||||
@Exported
|
||||
public int getTotalCount() {
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
public List<ChildReport> getResult() {
|
||||
// I think this is a reasonable default.
|
||||
return getChildReports();
|
||||
}
|
||||
|
||||
/**
|
||||
* Data-binding bean for the remote API.
|
||||
*/
|
||||
@ExportedBean(defaultVisibility=2)
|
||||
public static final class ChildReport {
|
||||
@Exported
|
||||
public final AbstractBuild<?,?> child;
|
||||
@Exported
|
||||
public final Object result;
|
||||
|
||||
public ChildReport(AbstractBuild<?, ?> child, AbstractTestResultAction result) {
|
||||
this.child = child;
|
||||
this.result = result.getResult();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mainly for the remote API. Expose results from children.
|
||||
*/
|
||||
@Exported
|
||||
public List<ChildReport> getChildReports() {
|
||||
return new AbstractList<ChildReport>() {
|
||||
public ChildReport get(int index) {
|
||||
return new ChildReport(
|
||||
resolveChild(children.get(index)),
|
||||
getChildReport(children.get(index)));
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return children.size();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract String getChildName(AbstractTestResultAction tr);
|
||||
protected abstract AbstractBuild<?,?> resolveChild(Child child);
|
||||
public abstract AbstractBuild<?,?> resolveChild(Child child);
|
||||
|
||||
/**
|
||||
* Uses {@link #resolveChild(Child)} and obtain the
|
||||
* {@link AbstractTestResultAction} object for the given child.
|
||||
*/
|
||||
protected AbstractTestResultAction getChildReport(Child child) {
|
||||
AbstractBuild<?,?> b = resolveChild(child);
|
||||
if(b==null) return null;
|
||||
return b.getAction(AbstractTestResultAction.class);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ public class MatrixTestResult extends AggregatedTestResultAction {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractBuild<?,?> resolveChild(Child child) {
|
||||
public AbstractBuild<?,?> resolveChild(Child child) {
|
||||
MatrixBuild b = (MatrixBuild)owner;
|
||||
return b.getRun(Combination.fromString(child.name));
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
<j:set var="p" value="${it.getChildReport(c)}"/>
|
||||
<j:set var="prev" value="${p.previousResult}" />
|
||||
<tr>
|
||||
<td class="pane">${c.name}</td> <!-- TODO: hyperlink -->
|
||||
<td class="pane">
|
||||
<a href="${rootURL}/${it.resolveChild(c).url}testReport/">
|
||||
${c.name}
|
||||
</a>
|
||||
</td>
|
||||
<td class="pane" style="text-align:right">${p.failCount}</td>
|
||||
<td class="pane" style="text-align:right">
|
||||
${h.getDiffString2(p.failCount-prev.failCount)}
|
||||
|
||||
Reference in new issue
Block a user