diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..acc287b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+target/
+.settings/
+.classpath
+.project
+logs/
+*.log
+velocity.log*
+.tomcatplugin
+*.dump
+classes/
+*.class
+*jacoco.exec
+*~
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..7b3e4a9
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,197 @@
+
+ 4.0.0
+ com.technophobia.substeps
+ substeps-runner
+ maven-plugin
+ 0.0.1
+
+ SubSteps Maven Runner
+
+
+ Technophobia Ltd
+ www.technophobia.com/
+
+
+
+
+ LGPL 3.0 license
+ http://www.opensource.org/licenses/lgpl-3.0.html
+ manual
+
+
+
+
+
+
+ ianmoore
+ Ian Moore
+ Technophobia
+
+ architect
+ developer
+
+
+
+
+ rorygibson
+ Rory Gibson
+ Technophobia
+
+ developer
+
+
+
+
+ davemoss
+ Dave Moss
+ Technophobia
+
+ developer
+
+
+
+
+ stuartforbes
+ Stu Forbes
+ Technophobia
+
+ developer
+
+
+
+
+
+
+ UTF-8
+ 1.3.RC2
+ 10.0
+ 1.9.0-rc1
+ 0.0.1
+ 2.2.1
+
+ internalsnapshots
+ internalreleases
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 1.5
+ true
+ ${project.build.sourceEncoding}
+
+
+
+
+ org.codehaus.plexus
+ plexus-component-metadata
+ 1.5.5
+
+
+
+
+ generate-metadata
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven
+ maven-artifact
+ ${maven.version}
+
+
+ org.apache.maven
+ maven-plugin-api
+ ${maven.version}
+
+
+ org.apache.maven
+ maven-project
+ ${maven.version}
+
+
+ org.apache.maven
+ maven-model
+ ${maven.version}
+
+
+ org.apache.maven
+ maven-core
+ 2.0.9
+
+
+
+ org.apache.maven.shared
+ maven-plugin-testing-harness
+ 1.0-beta-1
+ test
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.6.4
+
+
+
+ org.hamcrest
+ hamcrest-core
+ ${hamcrest.version}
+ test
+
+
+
+ org.hamcrest
+ hamcrest-library
+ ${hamcrest.version}
+ test
+
+
+
+
+ junit
+ junit
+ 4.10
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+ org.mockito
+ mockito-all
+ ${mockito.version}
+
+
+
+ com.technophobia.substeps
+ substeps-core
+ ${substeps.version}
+
+
+
+
+
+
+ scm:git:git://github.com/technophobia/substeps-runner.git
+
+
+
+
+
diff --git a/src/main/java/com/technophobia/substeps/mojo/runner/IncludeProjectDependenciesComponentConfigurator.java b/src/main/java/com/technophobia/substeps/mojo/runner/IncludeProjectDependenciesComponentConfigurator.java
new file mode 100644
index 0000000..d9914c2
--- /dev/null
+++ b/src/main/java/com/technophobia/substeps/mojo/runner/IncludeProjectDependenciesComponentConfigurator.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright Technophobia Ltd 2012
+ *
+ * This file is part of Substeps Maven Runner.
+ *
+ * Substeps Maven Runner is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Substeps Maven Runner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Substeps. If not, see .
+ */
+package com.technophobia.substeps.mojo.runner;
+
+// from http://maven.40175.n5.nabble.com/Adding-project-dependencies-and-generated-classes-to-classpath-of-my-plugin-td110119.html
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.codehaus.classworlds.ClassRealm;
+import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
+import org.codehaus.plexus.component.configurator.ConfigurationListener;
+import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter;
+import org.codehaus.plexus.component.configurator.converters.special.ClassRealmConverter;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A custom ComponentConfigurator which adds the project's runtime classpath
+ * elements to the
+ *
+ * @author Brian Jackson
+ * @since Aug 1, 2008 3:04:17 PM
+ *
+ * @plexus.component
+ * role="org.codehaus.plexus.component.configurator.ComponentConfigurator"
+ * role-hint="include-project-dependencies"
+ * @plexus.requirement role=
+ * "org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup"
+ * role-hint="default"
+ */
+public class IncludeProjectDependenciesComponentConfigurator extends AbstractComponentConfigurator {
+
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(IncludeProjectDependenciesComponentConfigurator.class);
+
+
+ @Override
+ public void configureComponent(final Object component, final PlexusConfiguration configuration,
+ final ExpressionEvaluator expressionEvaluator, final ClassRealm containerRealm,
+ final ConfigurationListener listener) throws ComponentConfigurationException {
+
+ addProjectDependenciesToClassRealm(expressionEvaluator, containerRealm);
+
+ converterLookup.registerConverter(new ClassRealmConverter(containerRealm));
+
+ final ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter();
+
+ converter.processConfiguration(converterLookup, component, containerRealm.getClassLoader(),
+ configuration, expressionEvaluator, listener);
+ }
+
+
+ private void addProjectDependenciesToClassRealm(final ExpressionEvaluator expressionEvaluator,
+ final ClassRealm containerRealm) throws ComponentConfigurationException {
+ List runtimeClasspathElements;
+
+ List testClasspathElements;
+ try {
+ // noinspection unchecked
+ runtimeClasspathElements = (List) expressionEvaluator
+ .evaluate("${project.runtimeClasspathElements}");
+
+ testClasspathElements = (List) expressionEvaluator
+ .evaluate("${project.testClasspathElements}");
+
+ } catch (final ExpressionEvaluationException e) {
+ throw new ComponentConfigurationException(
+ "There was a problem evaluating: ${project.runtimeClasspathElements}", e);
+ }
+
+ runtimeClasspathElements.addAll(testClasspathElements);
+
+ Collections.reverse(runtimeClasspathElements);
+
+ // Add the project dependencies to the ClassRealm
+ final URL[] urls = buildURLs(runtimeClasspathElements);
+ for (final URL url : urls) {
+ containerRealm.addConstituent(url);
+ }
+ }
+
+
+ private URL[] buildURLs(final List runtimeClasspathElements)
+ throws ComponentConfigurationException {
+ // Add the projects classes and dependencies
+ final List urls = new ArrayList(runtimeClasspathElements.size());
+ for (final String element : runtimeClasspathElements) {
+ try {
+ final URL url = new File(element).toURI().toURL();
+ urls.add(url);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Added to project class loader: " + url);
+ }
+ } catch (final MalformedURLException e) {
+ throw new ComponentConfigurationException("Unable to access project dependency: "
+ + element, e);
+ }
+ }
+
+ // Add the plugin's dependencies (so Trove stuff works if Trove isn't on
+ return urls.toArray(new URL[urls.size()]);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/technophobia/substeps/mojo/runner/SubstepsRunnerMojo.java b/src/main/java/com/technophobia/substeps/mojo/runner/SubstepsRunnerMojo.java
new file mode 100644
index 0000000..28a154c
--- /dev/null
+++ b/src/main/java/com/technophobia/substeps/mojo/runner/SubstepsRunnerMojo.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright Technophobia Ltd 2012
+ *
+ * This file is part of Substeps Maven Runner.
+ *
+ * Substeps Maven Runner is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Substeps Maven Runner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Substeps. If not, see .
+ */
+package com.technophobia.substeps.mojo.runner;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.project.MavenProject;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.technophobia.substeps.execution.ExecutionNode;
+import com.technophobia.substeps.report.ExecutionReportBuilder;
+import com.technophobia.substeps.report.ReportData;
+import com.technophobia.substeps.runner.ExecutionConfig;
+import com.technophobia.substeps.runner.ExecutionNodeRunner;
+import com.technophobia.substeps.runner.INotifier;
+import com.technophobia.substeps.runner.TagManager;
+
+/**
+ * Mojo to run a number SubStep features, each contained within any number of
+ * executionConfigs, encapsulating the required config and setup and tear down
+ * details
+ *
+ * @goal run-features
+ * @requiresDependencyResolution test
+ * @phase integration-test
+ *
+ * @configurator include-project-dependencies
+ */
+public class SubstepsRunnerMojo extends AbstractMojo {
+
+ public static void printRed(final String msg) {
+
+ // TODO
+ System.out.println(msg);
+ }
+
+ private final Logger log = LoggerFactory.getLogger(SubstepsRunnerMojo.class);
+
+ /**
+ * Location of the file.
+ *
+ * @parameter expression="${project.build.directory}"
+ * @required
+ */
+ private File outputDirectory;
+
+ /**
+ * @parameter default-value="${project.build.directory}"
+ */
+ private File outputDir;
+
+ /**
+ * @parameter default-value="${project}"
+ * @required
+ * @readonly
+ */
+ private MavenProject project;
+
+ /**
+ * @parameter
+ */
+ private Properties systemProperties;
+
+ /**
+ * @parameter
+ */
+ private final List executionConfigs = null;
+
+ private List failedNodes = null;
+ private List nonFatalFailedNodes = null;
+
+
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ final MojoNotifier notifier = new MojoNotifier();
+ final ReportData data = new ReportData();
+
+ Assert.assertNotNull("executionConfigs cannot be null", executionConfigs);
+ Assert.assertFalse("executionConfigs can't be empty", executionConfigs.isEmpty());
+
+ for (final ExecutionConfig executionConfig : executionConfigs) {
+ final ExecutionNode rootNode = runExecutionConfig(notifier, executionConfig);
+
+ if (executionConfig.getDescription() != null) {
+
+ rootNode.setLine(executionConfig.getDescription());
+ }
+
+ data.addDataFromRootNode(rootNode);
+
+ // notifier.setNonFatalTagManager(null);
+
+ checkRootNodeForFailure(rootNode, executionConfig);
+ }
+
+ final ExecutionReportBuilder reportBuilder = new ExecutionReportBuilder();
+ reportBuilder.buildReport(data, outputDir);
+
+ determineBuildFailure();
+
+ }
+
+
+ /**
+ * @throws MojoFailureException
+ *
+ */
+ private void determineBuildFailure() throws MojoFailureException {
+
+ if (failedNodes != null && !failedNodes.isEmpty()) {
+
+ // fail
+ throw new MojoFailureException("SubStep Execution failed:\n" + getFailureString());
+ }
+
+ if (nonFatalFailedNodes != null && !nonFatalFailedNodes.isEmpty()) {
+
+ System.out.println("NON CRITICAL FAILURES:\n\n" + buildInfoString(nonFatalFailedNodes));
+ }
+
+ }
+
+
+ /**
+ * @return
+ */
+ public String getNonFatalInfo() {
+ return buildInfoString(nonFatalFailedNodes);
+ }
+
+
+ private String buildInfoString(final List nodes) {
+ final StringBuilder buf = new StringBuilder();
+
+ final Set dealtWith = new HashSet();
+
+ if (nodes != null) {
+ for (final ExecutionNode node : nodes) {
+ if (!dealtWith.contains(node)) {
+ final List hierarchy = new ArrayList();
+
+ hierarchy.add(node);
+
+ // go up the tree as far as we can go
+ ExecutionNode parent = node.getParent();
+ while (parent != null && nodes.contains(parent)) {
+ hierarchy.add(parent);
+ parent = parent.getParent();
+ }
+
+ Collections.reverse(hierarchy);
+
+ for (final ExecutionNode node2 : hierarchy) {
+ buf.append(node2.getDebugStringForThisNode());
+ dealtWith.add(node2);
+ }
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+
+ /**
+ * @return
+ */
+ public String getFailureString() {
+ return "NON CRITICAL FAILURES:\n\n" + buildInfoString(nonFatalFailedNodes)
+ + "\n\nCRITICAL FAILURES:\n\n" + buildInfoString(failedNodes);
+ }
+
+
+ /**
+ * @param rootNode
+ * @param executionConfig
+ */
+ private void checkRootNodeForFailure(final ExecutionNode rootNode,
+ final ExecutionConfig executionConfig) {
+
+ TagManager nonFatalTagManager = null;
+ if (executionConfig.getNonFatalTags() != null) {
+ nonFatalTagManager = new TagManager(executionConfig.getNonFatalTags());
+ }
+
+ // any of these failures should be tagged correctly so we can assess for
+ // criticality
+ final List failures = rootNode.getFailedChildNodes();
+
+ if (failures != null) {
+
+ for (final ExecutionNode fail : failures) {
+
+ boolean handled = false;
+ if (nonFatalTagManager != null) {
+
+ printRed("non fatal tag mgr");
+
+ final Set tags = fail.getTagsFromHierarchy();
+
+ final StringBuilder buf = new StringBuilder();
+
+ if (tags != null) {
+ for (final String s : tags) {
+ buf.append(s).append(" ");
+ }
+ }
+ printRed("node has tags: " + buf.toString());
+
+ final Set acceptedTags = nonFatalTagManager.getAcceptedTags();
+
+ final StringBuilder buf2 = new StringBuilder();
+ for (final String s : acceptedTags) {
+ buf2.append(s).append(" ");
+ }
+
+ printRed("acceptedTags: " + buf2.toString());
+
+ if (nonFatalTagManager.acceptTaggedScenario(tags)) {
+ // this node is allowed to fail, add to the list of
+ // warnings
+
+ if (nonFatalFailedNodes == null) {
+ nonFatalFailedNodes = new ArrayList();
+ }
+ nonFatalFailedNodes.add(fail);
+ handled = true;
+ printRed("failure permissable");
+ }
+ }
+
+ if (!handled) {
+
+ printRed("** failure not permissable");
+
+ if (failedNodes == null) {
+ failedNodes = new ArrayList();
+ }
+
+ failedNodes.add(fail);
+ }
+
+ }
+ }
+
+ }
+
+
+ /**
+ * @param notifier
+ * @return
+ */
+ private ExecutionNode runExecutionConfig(final INotifier notifier,
+ final ExecutionConfig theConfig) {
+
+ final ExecutionNodeRunner runner = new ExecutionNodeRunner();
+
+ final ExecutionNode rootNode = runner.prepareExecutionConfig(theConfig, notifier);
+
+ runner.run();
+
+ return rootNode;
+ }
+
+ private static class MojoNotifier implements INotifier {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * uk.co.itmoore.bddrunner.runner.INotifier#notifyTestFailed(org.junit
+ * .runner.Description, java.lang.Throwable)
+ */
+ public void notifyTestFailed(final Description arg0, final Throwable arg1) {
+
+ System.out.println("notifyTestFailed desc");
+
+ }
+
+
+ public void notifyTestFinished(final Description arg0) {
+ // System.out.println("notifyTestFinished desc");
+ }
+
+
+ public void notifyTestIgnored(final Description arg0) {
+ // System.out.println("notifyTestIgnored desc");
+ }
+
+
+ public void notifyTestStarted(final Description arg0) {
+ // System.out.println("notifyTestStarted desc");
+ }
+
+
+ public void notifyTestFinished(final ExecutionNode node) {
+ // System.out.println("notifyTestFinished ");
+ }
+
+
+ public void notifyTestFailed(final ExecutionNode node, final Throwable throwable) {
+ // printRed("notifyTestFailed : " +
+ // node.getDebugStringForThisNode());
+
+ }
+
+
+ public void notifyTestStarted(final ExecutionNode arg0) {
+
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see uk.co.itmoore.bddrunner.runner.INotifier#pleaseStop()
+ */
+ public void pleaseStop() {
+
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * uk.co.itmoore.bddrunner.runner.INotifier#setJunitRunNotifier(org.
+ * junit.runner.notification.RunNotifier)
+ */
+ public void setJunitRunNotifier(final RunNotifier arg0) {
+
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * uk.co.itmoore.bddrunner.runner.INotifier#addListener(uk.co.itmoore
+ * .bddrunner.runner.INotifier)
+ */
+ public void addListener(final INotifier arg0) {
+
+ }
+
+ }
+
+}
diff --git a/src/main/resources/COPYING.LESSER b/src/main/resources/COPYING.LESSER
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/src/main/resources/COPYING.LESSER
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/src/test/java/com/technophobia/substeps/mojo/runner/MojoTest.java b/src/test/java/com/technophobia/substeps/mojo/runner/MojoTest.java
new file mode 100644
index 0000000..4ddaac2
--- /dev/null
+++ b/src/test/java/com/technophobia/substeps/mojo/runner/MojoTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright Technophobia Ltd 2012
+ *
+ * This file is part of Substeps Maven Runner.
+ *
+ * Substeps Maven Runner is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Substeps Maven Runner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Substeps. If not, see .
+ */
+package com.technophobia.substeps.mojo.runner;
+
+import java.io.File;
+
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import org.junit.Ignore;
+
+/**
+ * @author ian
+ *
+ */
+@Ignore
+public class MojoTest extends AbstractMojoTestCase {
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+
+ // required for mojo lookups to work
+ super.setUp();
+ }
+
+
+ /**
+ * @throws Exception
+ */
+ public void testMojoGoal() throws Exception {
+ final File testPom = new File(getBasedir(),
+ "src/test/resources/basic-test-plugin-config.xml");
+
+ final SubstepsRunnerMojo mojo = (SubstepsRunnerMojo) lookupMojo("integration-test", testPom);
+
+ assertNotNull(mojo);
+ }
+}
diff --git a/src/test/java/com/technophobia/substeps/mojo/runner/SubstepsRunnerMojoTest.java b/src/test/java/com/technophobia/substeps/mojo/runner/SubstepsRunnerMojoTest.java
new file mode 100644
index 0000000..bf136ed
--- /dev/null
+++ b/src/test/java/com/technophobia/substeps/mojo/runner/SubstepsRunnerMojoTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright Technophobia Ltd 2012
+ *
+ * This file is part of Substeps Maven Runner.
+ *
+ * Substeps Maven Runner is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Substeps Maven Runner is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Substeps. If not, see .
+ */
+package com.technophobia.substeps.mojo.runner;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.List;
+
+import junit.framework.Assert;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.technophobia.substeps.execution.ExecutionNode;
+import com.technophobia.substeps.runner.ExecutionConfig;
+
+/**
+ *
+ *
+ *
+ * @author imoore
+ *
+ */
+public class SubstepsRunnerMojoTest {
+
+ @Ignore("incomplete test")
+ @Test
+ public void testCriticalNonCriticalFailures() throws SecurityException, NoSuchMethodException,
+ IllegalArgumentException, IllegalAccessException, InvocationTargetException,
+ NoSuchFieldException {
+
+ final SubstepsRunnerMojo mojo = new SubstepsRunnerMojo();
+
+ final Method method = mojo.getClass().getMethod("checkRootNodeForFailure",
+ ExecutionNode.class, ExecutionConfig.class);
+
+ final Field failedNodesField = mojo.getClass().getField("failedNodes");
+ final Field nonFatalFailedNodesField = mojo.getClass().getField("nonFatalFailedNodes");
+
+ failedNodesField.setAccessible(true);
+ nonFatalFailedNodesField.setAccessible(true);
+
+ Assert.assertNotNull(method);
+ method.setAccessible(true);
+
+ final ExecutionConfig execConfig = new ExecutionConfig();
+
+ final ExecutionNode rootNode = new ExecutionNode();
+
+ method.invoke(mojo, rootNode, execConfig);
+
+ final List failedNodes = (List) failedNodesField.get(mojo);
+ final List nonFatalFailedNodes = (List) nonFatalFailedNodesField
+ .get(mojo);
+
+ }
+
+}
diff --git a/src/test/resources/basic-test-plugin-config.xml b/src/test/resources/basic-test-plugin-config.xml
new file mode 100644
index 0000000..e06f4b5
--- /dev/null
+++ b/src/test/resources/basic-test-plugin-config.xml
@@ -0,0 +1,44 @@
+
+ 4.0.0
+ test.group.id
+ test.artifact
+ jar
+ 0.0.1-SNAPSHOT
+
+
+
+
+
+
+
+
+ com.technophobia.substeps
+ substeps-runner
+ 0.0.1
+
+
+
+ SubSteps Test
+ test
+
+ run-features
+
+
+
+
+
+
+ -Denvironment=jenkins -DverboseDescriptions=true
+
+ **/OriginalCucumberTests.java
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file