All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.linuxstuff.maven.TrinidadMojo Maven / Gradle / Ivy

Go to download

Trinidad is a set of extensions and additional runners for the FitNesse acceptance test management tool.

There is a newer version: 20120309
Show newest version
package org.linuxstuff.maven;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import fitnesse.junit.*;
import fitnesse.responders.run.ResultsListener;

/**
 * Goal which runs a trinidad test execution.
 * 
 * @goal run-tests
 * @phase integration-test
 * @requiresDependencyResolution test
 */
public class TrinidadMojo extends AbstractMojo {
	/**
	 * this is an embedded resource parameter, it is set automatically using maven - ignore it
	 * 
	 * @parameter expression="${project}"
	 */
	private org.apache.maven.project.MavenProject mavenProject;

	/**
	 * The URI for the result repository (output directory if using a file result repository).
	 * 
	 * @parameter expression="${trinidad.output}" default-value="${project.build.directory}/trinidad"
	 * @required
	 */
	private String resultRepositoryUri;

	/**
	 * The URI for the test repository. The format depends on the test repository type. For fitnesse test repositories, this is the path to the main
	 * fitnesse
	 * 
	 * @parameter expression="${trinidad.test.location}"
	 * @required
	 */
	private String testRepositoryUri;

	/**
	 * Set this to true for Maven to break the build if any of the tests have failed. Leave it set to false to just print out a warning
	 * 
	 * @parameter default-value="false"
	 */
	private boolean breakBuildOnFailure;

	/**
	 * Set this to true for Maven to stop running tests after the first failed test/suite. Leave it set to false to run all tests regardless of
	 * failures.
	 * 
	 * @parameter default-value="false"
	 */
	private boolean stopAfterFirstFailure;

	/**
	 * A set of suite names to execute.
	 * 
	 * @parameter
	 */
	private String[] suites = new String[0];

	/**
	 * A set of test names to execute
	 * 
	 * @parameter
	 */
	private String[] tests = new String[0];

	/**
	 * a single test to execute
	 * 
	 * @parameter alias="test" expression="${trinidad.run.test}"
	 */
	private String singleTest = null;

	/**
	 * a single test to execute
	 * 
	 * @parameter alias="suite" expression="${trinidad.run.suite}"
	 */
	private String singleSuite = null;

	/**
	 * Whether or not to skip test run. This aligns with how surefire works.
	 * 
	 * @parameter default-value="false" expression="${maven.test.skip}"
	 */
	private boolean skipTest;

	/**
	 * Optional listener class name for extending test instrumentation and reporting. The class should implement FitNesse ResultListener interface
	 * 
	 * @parameter default-value="" expression="${trinidad.listener}"
	 */
	private String listenerClass;

	void setTestRepositoryUri(String testRepositoryUri) {
		this.testRepositoryUri = testRepositoryUri;
	}

	void setResultRepositoryUri(String resultRepositoryUri) {
		this.resultRepositoryUri = resultRepositoryUri;
	}

	void setSingleSuite(String singleSuite) {
		this.singleSuite = singleSuite;
	}

	void setSingleTest(String singleTest) {
		this.singleTest = singleTest;
	}

	public void execute() throws MojoExecutionException {
		if (this.skipTest) {
			getLog().info("Skipping tests.");
			return;
		}

		processDefaults();
		createOutputDirectory();
		final ClassLoader cl = initProjectTestClassLoader();
		Thread runnerThread = new Thread(new Runnable() {
			public void run() {
				try {
					Object testRunnerInstance = loadTestRunner(cl);
					runIndividualTests(testRunnerInstance);
					runSuites(testRunnerInstance);
				} catch (Exception e) {
					throw new Error(e);
				}
			}
		});
		runnerThread.setContextClassLoader(cl);
		runnerThread.start();
		try {
			runnerThread.join();
		} catch (InterruptedException e) {
			getLog().error(e);
			throw new MojoExecutionException("exception in the mojo runner thread", e);
		}
		if (breakBuildOnFailure && totalWrongOrException > 0)
			throw new MojoExecutionException("Acceptance test run failed. Total " + totalWrongOrException
					+ " failing tests or exceptions. See log for more information.");
	}

	private void createOutputDirectory() {
		File output = new File(this.resultRepositoryUri);
		if (!output.exists())
			output.mkdirs();
	}

	private void runSuites(Object testRunnerInstance) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
			NoSuchFieldException, MojoExecutionException {
		Method runSuite = testRunnerInstance.getClass().getMethod("runSuite", String.class);
		for (String suite : suites) {
			if (stopAfterFirstFailure && totalWrongOrException > 0)
				break;
			getLog().info("running suite=" + suite);
			Object counts = runSuite.invoke(testRunnerInstance, suite);
			int wrongOrException = getWrongPlusExceptions(counts);
			totalWrongOrException += wrongOrException;
		}
	}

	private int totalWrongOrException = 0;

	private void runIndividualTests(Object testRunnerInstance) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
			NoSuchFieldException, MojoExecutionException {
		Method runTest = testRunnerInstance.getClass().getMethod("runTest", String.class);
		for (String test : tests) {
			if (stopAfterFirstFailure && totalWrongOrException > 0)
				break;
			getLog().info("running test=" + test);
			Object counts = runTest.invoke(testRunnerInstance, test);
			int wrongOrException = getWrongPlusExceptions(counts);
			totalWrongOrException += wrongOrException;
		}
	}

	private Object loadTestRunner(ClassLoader cl) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
			NoSuchMethodException, InvocationTargetException {
		Object testRunnerInstance;
		Class c = cl.loadClass(TestHelper.class.getName());
		if (listenerClass != null && !("".equals(listenerClass))) {
			Object listener = cl.loadClass(listenerClass).newInstance();
			getLog().debug("Loaded listener:" + listenerClass);
			testRunnerInstance = c.getConstructor(String.class, String.class, cl.loadClass(ResultsListener.class.getName())).newInstance(
					this.testRepositoryUri, this.resultRepositoryUri, listener);
		} else {
			testRunnerInstance = c.getConstructor(String.class, String.class).newInstance(this.testRepositoryUri, this.resultRepositoryUri);
		}
		getLog().debug("loaded test runner:" + testRunnerInstance);
		return testRunnerInstance;
	}

	private int getWrongPlusExceptions(Object counts) throws IllegalAccessException, NoSuchFieldException {
		int wrong = counts.getClass().getField("wrong").getInt(counts);
		int exceptions = counts.getClass().getField("exceptions").getInt(counts);
		int wrongOrException = wrong + exceptions;
		return wrongOrException;
	}

	private void processDefaults() {
		if (singleTest != null)
			tests = new String[] { singleTest };
		if (singleSuite != null)
			suites = new String[] { singleSuite };
	}

	private ClassLoader initProjectTestClassLoader() throws MojoExecutionException {
		if (mavenProject == null)
			return getClass().getClassLoader();
		try {

			List classpath = mavenProject.getTestClasspathElements();
			getLog().debug("class path=" + classpath);
			URL[] urlArray = new URL[classpath.size()];
			for (int i = 0; i < classpath.size(); i++) {
				urlArray[i] = new File(classpath.get(i)).toURI().toURL();
			}
			return new URLClassLoader(urlArray);
		} catch (Exception e) {
			throw new MojoExecutionException("class loader initialisation failed", e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy