Author: gscokart
Date: Tue Feb 3 21:13:59 2009
New Revision: 740452
URL: http://svn.apache.org/viewvc?rev=740452&view=rev
Log:
Refactoring : - Move active/inactive state managment from AntUnitScriptRunner
to AntUnit - Split AntUnitExecutionPlatform into a ProjectFactory (required to
parse the script) and AntUnitExceutionNotifier (required to run the script) -
Move the invocation of the sequence suiteSetUp, test targets suiteTearDown
from AntUnit to AntUnitScriptRunner
Added:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionNotifier.java
(with props)
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/ProjectFactory.java
(with props)
Removed:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionPlatform.java
Modified:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnit.java
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java
Modified: ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnit.java
URL:
http://svn.apache.org/viewvc/ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnit.java?rev=740452&r1=740451&r2=740452&view=diff
==============================================================================
--- ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnit.java
(original)
+++ ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnit.java Tue
Feb 3 21:13:59 2009
@@ -74,11 +74,7 @@
private Union buildFiles;
- private AntUnitExecutionPlatform myExecutionPlatform = new
AntUnitExecutionPlatform() {
-
- public Project createProjectForFile(File f) {
- return AntUnit.this.createProjectForFile(f);
- }
+ private AntUnitExecutionNotifier notifier = new AntUnitExecutionNotifier()
{
public void fireEndTest(String targetName) {
AntUnit.this.fireEndTest(targetName);
@@ -100,9 +96,10 @@
/**
* The object responsible for the execution of the unit test.
* scriptRunner is invoked to executes the targets and keep the
- * reference to the project.
+ * reference to the project. scriptRunner is defined only when the
+ * antunit script is running.
*/
- private AntUnitScriptRunner scriptRunner = new
AntUnitScriptRunner(myExecutionPlatform);
+ private AntUnitScriptRunner scriptRunner;
/**
* listeners.
@@ -225,27 +222,19 @@
/**
* Processes a single build file.
*/
- private void doFile(File f) {
+ private void doFile(final File f) {
log("Running tests in build file " + f, Project.MSG_DEBUG);
- scriptRunner.activate(f);
- List testTargets = scriptRunner.scanFile();
-
- // start test
- Throwable caught = null;
+ ProjectFactory prjFactory = new ProjectFactory() {
+ public Project createProject() {
+ return createProjectForFile(f);
+ }
+ };
try {
- if (!scriptRunner.startSuite()) {
- return;
- }
- Iterator iter = testTargets.iterator();
- while (iter.hasNext()) {
- String name = (String) iter.next();
- scriptRunner.runTarget(name);
- }
- } catch (Throwable e) {
- caught = e;
+ scriptRunner = new AntUnitScriptRunner(prjFactory);
+ List testTargets = scriptRunner.getTestTartgets();
+ scriptRunner.runSuite(testTargets, notifier);
} finally {
- scriptRunner.endSuite(caught);
- scriptRunner.deactivate();
+ scriptRunner=null;
}
}
@@ -255,7 +244,7 @@
* @param outputToHandle the output to handle.
*/
public void handleOutput(String outputToHandle) {
- if (scriptRunner.isActive()) {
+ if (scriptRunner!=null) {
scriptRunner.getCurrentProject().demuxOutput(outputToHandle,
false);
} else {
super.handleOutput(outputToHandle);
@@ -270,7 +259,7 @@
*/
public int handleInput(byte[] buffer, int offset, int length)
throws IOException {
- if (scriptRunner.isActive()) {
+ if (scriptRunner!=null) {
return scriptRunner.getCurrentProject().demuxInput(buffer, offset,
length);
}
return super.handleInput(buffer, offset, length);
@@ -281,7 +270,7 @@
* @param toFlush the output String to flush.
*/
public void handleFlush(String toFlush) {
- if (scriptRunner.isActive()) {
+ if (scriptRunner!=null) {
scriptRunner.getCurrentProject().demuxFlush(toFlush, false);
} else {
super.handleFlush(toFlush);
@@ -293,7 +282,7 @@
* @param errorOutputToHandle the error output to handle.
*/
public void handleErrorOutput(String errorOutputToHandle) {
- if (scriptRunner.isActive()) {
+ if (scriptRunner!=null) {
scriptRunner.getCurrentProject().demuxOutput(errorOutputToHandle,
true);
} else {
super.handleErrorOutput(errorOutputToHandle);
@@ -305,7 +294,7 @@
* @param errorOutputToFlush the error output to flush.
*/
public void handleErrorFlush(String errorOutputToFlush) {
- if (scriptRunner.isActive()) {
+ if (scriptRunner!=null) {
scriptRunner.getCurrentProject().demuxFlush(errorOutputToFlush,
true);
} else {
super.handleErrorFlush(errorOutputToFlush);
Added:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionNotifier.java
URL:
http://svn.apache.org/viewvc/ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionNotifier.java?rev=740452&view=auto
==============================================================================
---
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionNotifier.java
(added)
+++
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionNotifier.java
Tue Feb 3 21:13:59 2009
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.ant.antunit;
+
+import java.io.File;
+
+import org.apache.tools.ant.Project;
+
+/**
+ * Provides methods that allow the AntUnitScriptRunner to notify the test
progress.
+ * @since 1.2
+ */
+public interface AntUnitExecutionNotifier {
+
+ /**
+ * invokes start on all registered test listeners.
+ * @param targetName the name of the target.
+ */
+ public void fireStartTest(String targetName);
+
+ /**
+ * invokes addFailure on all registered test listeners.
+ * @param targetName the name of the failed target.
+ * @param ae the associated AssertionFailedException.
+ */
+ public void fireFail(String targetName, AssertionFailedException ae);
+
+ /**
+ * invokes addError on all registered test listeners.
+ * @param targetName the name of the failed target.
+ * @param t the associated Throwable.
+ */
+ public void fireError(String targetName, Throwable t);
+
+ /**
+ * invokes endTest on all registered test listeners.
+ * @param targetName the name of the current target.
+ */
+ public void fireEndTest(String targetName);
+
+}
Propchange:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitExecutionNotifier.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java
URL:
http://svn.apache.org/viewvc/ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java?rev=740452&r1=740451&r2=740452&view=diff
==============================================================================
---
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java
(original)
+++
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java
Tue Feb 3 21:13:59 2009
@@ -1,6 +1,5 @@
package org.apache.ant.antunit;
-import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -11,17 +10,13 @@
import org.apache.tools.ant.Project;
/**
- * Run antunit tests. The lifecycle of this object is :
- * <ol>
- * <li> activate(file) : Indicates the runner that the given file should be
used.</li>
- * <li> scanFile() : Provides you the list of targets.</li>
- * <li> startSuite() : Start the suite</li>
- * <li> runTarget(targetName) : Executed one or more time</li>
- * <li> endSuite() : End the suite</li>
- * <li> deactivate() Indicates to the runner that the test is finished and all
- * resources can be freed </li>
- * </ol>
- * Every step is mandatory.
+ * Run antunit tests suites. This AntUnitScriptRunner is responsible for the
+ * management of the ant project and the correct invocation the target (taking
+ * into account properly the [case]setUp and [case]tearDown targets).
+ * The user can however provide the order of the test targets and or can filter
+ * the list of test targets to execute.
+ * The user must also provide its ProjectFactory and an
AntUnitExecutionNotifier.
+ * @since 1.2
*/
public class AntUnitScriptRunner {
@@ -51,24 +46,11 @@
private static final String SUITETEARDOWN = "suiteTearDown";
/**
- * Object used to interact with the environment (for example an ant task
or a junit runner)
+ * Object used to create projects in order to support test isolation.
*/
- private final AntUnitExecutionPlatform env;
-
- /**
- * Ant script file currently under testing. The file is set at
activation, and used
- * during all execution every time we want have to create a new
project.</br>
- * It is only defined when the project isActive()
- */
- private File scriptFile;
+ private final ProjectFactory prjFactory;
/**
- * Indicates if the active project is already scanned and if the value the
fields
- * hasSuiteSetUp, hasSetUp, hasTearDown, hasSuiteTearDown are defined.
- */
- private boolean isScanned;
-
- /**
* Indicates if the startSuite method has been invoked. Use to fail fast
if the
* the caller forget to call the startSuite method
*/
@@ -77,22 +59,27 @@
/**
* Does that script have a setUp target (defined when scanning the script)
*/
- private boolean hasSetUp;
+ private final boolean hasSetUp;
/**
* Does that script have a tearDown target (defined when scanning the
script)
*/
- private boolean hasTearDown;
+ private final boolean hasTearDown;
/**
* Does that script has a suiteSetUp target.
*/
- private boolean hasSuiteSetUp;
+ private final boolean hasSuiteSetUp;
/**
* Does that script has a suite tearDown target that should be executed.
*/
- private boolean hasSuiteTearDown;
+ private final boolean hasSuiteTearDown;
+
+ /**
+ * List of target names
+ */
+ private final List testTargets;
/**
* The project currently used.
@@ -108,54 +95,35 @@
/**
* Create a new AntScriptRunner on the given environment.
- * @param env The environment used to create project and where the test
progress will be
- * notified.
+ * @param prjFactory A factory for the ant project that will contains the
antunit test to execute.
+ * The factory might be invoked multiple time in order to provide test
isolation.
*/
- public AntUnitScriptRunner(AntUnitExecutionPlatform env) {
- if (env == null) {
- throw new AssertionError();
+ public AntUnitScriptRunner(ProjectFactory prjFactory) {
+ this.prjFactory = prjFactory;
+ Project newProject = getCurrentProject();
+ Map targets = newProject.getTargets();
+ hasSetUp = targets.containsKey(SETUP);
+ hasTearDown = targets.containsKey(TEARDOWN);
+ hasSuiteSetUp = targets.containsKey(SUITESETUP);
+ hasSuiteTearDown = targets.containsKey(SUITETEARDOWN);
+ testTargets = new LinkedList();
+ Iterator it = targets.keySet().iterator();
+ while (it.hasNext()) {
+ String name = (String) it.next();
+ if (name.startsWith(TEST) && !name.equals(TEST)) {
+ testTargets.add(name);
+ }
}
- this.env = env;
- }
-
- /**
- * Set the ant script to use.
- * @post isActive()
- */
- public void activate(File f) {
- scriptFile = f;
- project = null;
- isScanned = false;
- isSuiteStarted = false;
- }
-
- /**
- * Declare that the current ant script doesn't need to be used anymore.
- * @post !isActive()
- */
- public void deactivate() {
- scriptFile = null;
- project = null;
- }
-
- /**
- * Indicates if there is a project currently under test.
- */
- public boolean isActive() {
- return scriptFile != null;
}
/**
* Get the project currently in use. The caller is not allowed to invoke
a target or
* do anything that would break the isolation of the test targets.
- * @pre isActif()
*/
- public Project getCurrentProject() {
- if (!isActive()) {
- throw new AssertionError();
- }
+ public final Project getCurrentProject() {
+ //Method is final because it is called from the constructor
if (project == null) {
- project = env.createProjectForFile(scriptFile);
+ project = prjFactory.createProject();
projectIsDirty = false;
}
return project;
@@ -163,14 +131,10 @@
/**
* Get a project that has not yet been used in order to execute a target
on it.
- * @pre isActive()
*/
private Project getCleanProject() {
- if (!isActive()) {
- throw new AssertionError();
- }
if (project == null || projectIsDirty) {
- project = env.createProjectForFile(scriptFile);
+ project = prjFactory.createProject();
}
//we already set isDirty to true in order to make sure we didn't reuse
//this project next time getCleanProject is called.
@@ -179,60 +143,34 @@
}
/**
- * Provides the list of test targets of the active antunit script.
- * @pre isActive()
- * @return List<String> List of test target names
+ * @return List<String> List of test targets of the script file
*/
- public List scanFile() {
- if (!isActive()) {
- throw new AssertionError();
- }
- Project newProject = getCurrentProject();
- Map targets = newProject.getTargets();
- hasSetUp = targets.containsKey(SETUP);
- hasTearDown = targets.containsKey(TEARDOWN);
- hasSuiteSetUp = targets.containsKey(SUITESETUP);
- hasSuiteTearDown = targets.containsKey(SUITETEARDOWN);
- List testTargets = new LinkedList();
- Iterator it = targets.keySet().iterator();
- while (it.hasNext()) {
- String name = (String) it.next();
- if (name.startsWith(TEST) && !name.equals(TEST)) {
- testTargets.add(name);
- }
- }
- isScanned = true;
+ public List getTestTartgets() {
return testTargets;
}
/**
* Provides the name of the active script.
- * @pre isAvtive()
*/
public String getName() {
- if (!isActive()) {
- throw new AssertionError();
- }
return getCurrentProject().getName();
}
/**
* Executes the suiteSetUp target if presents and report any execution
error.
+ * A failure is reported to the notifier and by returning false.
* Note that if the method return false, you are not allowed to run
targets.
* @return false in case of execution failure. true in case of success.
*/
- public boolean startSuite() {
- if (!isScanned) {
- throw new AssertionError();
- }
+ private boolean startSuite(AntUnitExecutionNotifier notifier) {
getCurrentProject().fireBuildStarted();
if (hasSuiteSetUp) {
try {
Project newProject = getCleanProject();
newProject.executeTarget(SUITESETUP);
} catch (BuildException e) {
- env.fireStartTest(SUITESETUP);
- fireFailOrError(SUITESETUP, e);
+ notifier.fireStartTest(SUITESETUP);
+ fireFailOrError(SUITESETUP, e, notifier);
return false;
}
}
@@ -242,10 +180,12 @@
/**
* Run the specific test target, possibly between the setUp and tearDown
targets if
- * it exists. Exception or failures are reported to the execution
environment.
+ * it exists. Exception or failures are reported to the notifier.
* @param name name of the test target to execute.
+ * @param notifier will receive execution notifications.
+ * @pre startSuite has been invoked successfully
*/
- public void runTarget(String name) {
+ private void runTarget(String name, AntUnitExecutionNotifier notifier) {
if (!isSuiteStarted) {
throw new AssertionError();
}
@@ -258,23 +198,23 @@
// create and register a logcapturer on the newProject
LogCapturer lc = new LogCapturer(newProject);
try {
- env.fireStartTest(name);
+ notifier.fireStartTest(name);
newProject.executeTargets(v);
} catch (BuildException e) {
- fireFailOrError(name, e);
+ fireFailOrError(name, e, notifier);
} finally {
// fire endTest here instead of the endTarget
// event, otherwise an error would be
// registered after the endTest event -
// endTarget is called before this method's catch block
// is reached.
- env.fireEndTest(name);
+ notifier.fireEndTest(name);
// clean up
if (hasTearDown) {
try {
newProject.executeTarget(TEARDOWN);
} catch (final BuildException e) {
- fireFailOrError(name, e);
+ fireFailOrError(name, e, notifier);
}
}
}
@@ -282,20 +222,18 @@
/**
* Executes the suiteTearDown target if presents and report any execution
error.
- * @param caught Any internal exception triggered (and catched) by the
caller indicating that
- * the this runner could not be invoked as expected.
+ * @param caught Any internal exception triggered (and caught) by the
caller indicating that
+ * the execution could not be invoked as expected.
+ * @param notifier will receive execution notifications.
*/
- public void endSuite(Throwable caught) {
- if (!isScanned) {
- throw new AssertionError();
- }
+ private void endSuite(Throwable caught, AntUnitExecutionNotifier notifier)
{
if (hasSuiteTearDown) {
try {
Project newProject = getCleanProject();
newProject.executeTarget(SUITETEARDOWN);
} catch (BuildException e) {
- env.fireStartTest(SUITETEARDOWN);
- fireFailOrError(SUITETEARDOWN, e);
+ notifier.fireStartTest(SUITETEARDOWN);
+ fireFailOrError(SUITETEARDOWN, e, notifier);
}
}
getCurrentProject().fireBuildFinished(caught);
@@ -307,20 +245,45 @@
* or is caused by an AssertionFailedException. If so, fire a failure for
* given targetName. Otherwise fire an error.
*/
- private void fireFailOrError(String targetName, BuildException e) {
+ private void fireFailOrError(String targetName, BuildException e,
+ AntUnitExecutionNotifier notifier) {
boolean failed = false;
Throwable t = e;
while (t != null && t instanceof BuildException) {
if (t instanceof AssertionFailedException) {
failed = true;
- env.fireFail(targetName, (AssertionFailedException) t);
+ notifier.fireFail(targetName, (AssertionFailedException) t);
break;
}
t = ((BuildException) t).getCause();
}
if (!failed) {
- env.fireError(targetName, e);
+ notifier.fireError(targetName, e);
+ }
+ }
+
+
+ /**
+ * Executes the suite.
+ * @param suiteTargets An ordered list of test targets. It must be a
sublist of getTestTargets
+ * @param notifier
+ */
+ public void runSuite(List suiteTargets, AntUnitExecutionNotifier notifier)
{
+ Throwable caught = null;
+ try {
+ if (!startSuite(notifier)) {
+ return;
+ }
+ Iterator iter = suiteTargets.iterator();
+ while (iter.hasNext()) {
+ String name = (String) iter.next();
+ runTarget(name, notifier);
+ }
+ } catch (Throwable e) {
+ caught = e;
+ } finally {
+ endSuite(caught, notifier);
}
}
Added:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/ProjectFactory.java
URL:
http://svn.apache.org/viewvc/ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/ProjectFactory.java?rev=740452&view=auto
==============================================================================
---
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/ProjectFactory.java
(added)
+++
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/ProjectFactory.java
Tue Feb 3 21:13:59 2009
@@ -0,0 +1,20 @@
+package org.apache.ant.antunit;
+
+import org.apache.tools.ant.Project;
+
+/**
+ * Provides project instances for AntUnit execution.<br/>
+ * The aproach to creates a project depends on the context. When invoked from
an
+ * ant project, some elements might be intialized from the parent project.
When
+ * executed in a junit runner, a brand new project must be initialized.<br/>
+ * The AntScriptRunner will usually creates multiple project in order to
provide test isolation.
+ * @since 1.2
+ */
+public interface ProjectFactory {
+
+ /**
+ * Creates a new project instance and configures it according to the
execution context.
+ */
+ public Project createProject();
+
+}
Propchange:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/ProjectFactory.java
------------------------------------------------------------------------------
svn:eol-style = native