// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesseMain.ant;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.LogStreamHandler;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
/**
* Task to run fit tests. This task runs fitnesse tests and publishes the results.
* <pre>
* Usage:
* <taskdef name="execute-fitnesse-tests"
* classname="fitnesse.ant.ExecuteFitnesseTestsTask"
* classpathref="classpath" />
* OR
* <taskdef classpathref="classpath"
* resource="tasks.properties" />
*
* <execute-fitnesse-tests
* suitepage="FitNesse.SuiteAcceptanceTests"
* fitnesseport="8082"
* resultsdir="${results.dir}"
* resultshtmlpage="fit-results.html"
* classpathref="classpath" />
* </pre>
*/
public class ExecuteFitnesseTestsTask extends Task {
private String fitnesseHost = "localhost";
private int fitnessePort;
private String suitePage;
private String suiteFilter;
private String resultsDir = ".";
private String resultsHTMLPage;
private String resultsXMLPage;
private boolean debug = true;
private boolean verbose = true;
private boolean failOnError = true;
private String testRunnerClass = "fitnesse.runner.TestRunner";
private Path classpath;
private String resultProperty;
@Override
public void execute() throws BuildException {
try {
int exitCode = executeRunnerClassAsForked();
if (exitCode != 0) {
log("Finished executing FitNesse tests: " + exitCode + " failures/exceptions");
if (failOnError) {
throw new BuildException(exitCode + " FitNesse test failures/exceptions");
} else {
getProject().setNewProperty(resultProperty, String.valueOf(exitCode));
}
} else {
log("Fitnesse Tests executed successfully");
}
}
catch (Exception e) {
if (failOnError) {
throw new BuildException(
"Got an unexpected error trying to run the fitnesse tests : " + e.getMessage(), e);
} else {
e.printStackTrace();
}
}
}
private int executeRunnerClassAsForked() throws BuildException {
CommandlineJava cmd = initializeJavaCommand();
Execute execute = new Execute(new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN));
String[] commandLine = cmd.getCommandline();
log("Executing: " + StringUtils.join(Arrays.asList(commandLine), " "));
execute.setCommandline(commandLine);
execute.setNewenvironment(false);
execute.setAntRun(getProject());
log(cmd.describeCommand(), Project.MSG_VERBOSE);
int retVal;
try {
retVal = execute.execute();
}
catch (IOException e) {
throw new BuildException("Process fork failed.", e, getLocation());
}
return retVal;
}
private CommandlineJava initializeJavaCommand() {
CommandlineJava cmd = new CommandlineJava();
cmd.setClassname(testRunnerClass);
appendDebugArgument(cmd);
appendVerboseArgument(cmd);
appendHtmlResultPage(cmd);
appendXmlResultPage(cmd);
appendSuiteFilter(cmd);
cmd.createArgument().setValue(fitnesseHost);
cmd.createArgument().setValue(String.valueOf(fitnessePort));
cmd.createArgument().setValue(suitePage);
cmd.createClasspath(getProject()).createPath().append(classpath);
return cmd;
}
private void appendDebugArgument(CommandlineJava cmd) {
if (debug)
cmd.createArgument().setValue("-debug");
}
private void appendVerboseArgument(CommandlineJava cmd) {
if (verbose)
cmd.createArgument().setValue("-v");
}
private void appendHtmlResultPage(CommandlineJava cmd) {
if (resultsHTMLPage != null) {
String resultsHTMLPagePath = new File(resultsDir, resultsHTMLPage).getAbsolutePath();
cmd.createArgument().setValue("-html");
cmd.createArgument().setValue(resultsHTMLPagePath);
}
}
private void appendXmlResultPage(CommandlineJava cmd) {
if (resultsXMLPage != null) {
String resultsHTMLPagePath = new File(resultsDir, resultsXMLPage).getAbsolutePath();
cmd.createArgument().setValue("-xml");
cmd.createArgument().setValue(resultsHTMLPagePath);
}
}
private void appendSuiteFilter(CommandlineJava cmd) {
if (suiteFilter != null) {
cmd.createArgument().setValue("-suiteFilter");
cmd.createArgument().setValue(suiteFilter);
}
}
/**
* Set host address on which Fitnesse is running. Defaults to 'localhost'.
*
* @param fitnesseHost host address on which Fitnesse is running
*/
public void setFitnesseHost(String fitnesseHost) {
this.fitnesseHost = fitnesseHost;
}
/**
* Set Classpath of the TestRunner class. <b>MUST SET</b>
*
* @param classpath Classpath of the TestRunner class
*/
public void setClasspath(Path classpath) {
this.classpath = classpath;
}
/**
* Set name of the filter to be passed to TestRunner to specify a subset of tests to run.
*
* @param suiteFilter name of the filter to be passed to TestRunner for filtering
*/
public void setSuiteFilter(String suiteFilter) {
this.suiteFilter = suiteFilter;
}
/**
* Set debug mode. Defaults to 'true'.
*
* @param debug enable or disable debug mode
*/
public void setDebug(boolean debug) {
this.debug = debug;
}
/**
* Enable or disable to fail the build if any Fitnesse tests fail. Defaults to 'true'.
*
* @param failOnError Enable or disable to fail the build if any Fitnesse tests fail
*/
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}
/**
* Set port on which fitnesse would run. <b>MUST SET.</b>.
*
* @param fitnessePort port on which fitnesse would run
*/
public void setFitnessePort(int fitnessePort) {
this.fitnessePort = fitnessePort;
}
/**
* Set name of the property which will store the test results. Only valid if failOnError attribute is set to false.
*
* @param resultProperty name of the property which will store the test results
*/
public void setResultProperty(String resultProperty) {
this.resultProperty = resultProperty;
}
/**
* Set the path to the folder that will contain the fitnesse results page after execution. Only valid if resultsHTMLPage or
* resultsXMLPage attributes are set. Defaults to current directory.
*
* @param resultsDir path to the folder that will contain the fitnesse results page after execution.
*/
public void setResultsDir(String resultsDir) {
this.resultsDir = resultsDir;
}
/**
* Set the filename for storing the results in HTML format
*
* If set, stores the fitnesse results in HTML format under the resultsdir folder with the given name. The file name
* must have a '.html' extension.
*
* @param resultsHTMLPage set the filename for storing the results in HTML format
*/
public void setResultsHTMLPage(String resultsHTMLPage) {
this.resultsHTMLPage = resultsHTMLPage;
}
/**
* Set the filename for storing the results in XML format
*
* If set, stores the fitnesse results in XML format under the resultsdir folder with the given name. The file name
* must have a '.xml' extension.
*
* @param resultsXMLPage set the filename for storing the results in XML format
*/
public void setResultsXMLPage(String resultsXMLPage) {
this.resultsXMLPage = resultsXMLPage;
}
/**
* Set the fully qualifies class name of the fitnesse testrunner class. Defaults to 'fitnesse.runner.TestRunner'.
*
* @param runnerClass Fully qualifies class name of the fitnesse testrunner class
*/
public void setTestRunnerClass(String runnerClass) {
testRunnerClass = runnerClass;
}
/**
* Set the partial URL of the wiki page which is declared as a Suite. Ex: FrontPage.SmokeTest,
* FitNesse.SuiteAcceptanceTests, or FitNesse.AcceptanceTestsSuite. <b>MUST SET.</b>
*
* @param suitePage partial URL of the wiki page which is declared as a Suite
*/
public void setSuitePage(String suitePage) {
this.suitePage = suitePage;
}
/**
* Set verbose mode. Defaults to 'true'.
*
* @param verbose verbose mode
*/
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
public Path createClasspath() {
if (classpath == null) {
classpath = new Path(getProject());
}
return classpath.createPath();
}
public void setClasspathRef(Reference r) {
createClasspath().setRefid(r);
}
}