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:
kohsuke committed 2008-02-02 20:17:57 +00:00
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));
}