You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by gs...@apache.org on 2009/01/27 22:18:23 UTC
svn commit: r738248 - in
/ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit: AntUnit.java
AntUnitScriptRunner.java
Author: gscokart
Date: Tue Jan 27 21:18:22 2009
New Revision: 738248
URL: http://svn.apache.org/viewvc?rev=738248&view=rev
Log:
Finally extract AntUnitScriptRunner (I have also added assertion validating the proper sequence of method invocation)
Added:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java (with props)
Modified:
ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnit.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=738248&r1=738247&r2=738248&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 Jan 27 21:18:22 2009
@@ -24,10 +24,8 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.Vector;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildException;
@@ -224,227 +222,6 @@
}
}
- /** Manage the project reference in order to minimize the number of project creation
- * while allowing every test to run in isolation.
- */
- private static class AntUnitScriptRunner {
-
- /** ant script currently under testing */
- private File scriptFile;
-
- /** The project currently used. */
- private Project project = null;
-
- /** Indicates if a target has already be executed using this project.
- * Value is undefined when project is null.
- */
- private boolean projectIsDirty;
-
- /**
- * The environment that creates the project and receive execution notification.
- */
- private final AntUnitExecutionPlatform env;
-
-
- public AntUnitScriptRunner(AntUnitExecutionPlatform env) {
- if (env==null) {
- throw new AssertionError();
- }
- this.env = env;
- }
-
- /** Set the ant script to use. */
- public void activate(File f) {
- scriptFile = f;
- project = null;
- }
-
- /** Declare that the current ant script doesn't need to be used anymore. */
- 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("scriptFile==null");
- }
- if (project == null) {
- project = env.createProjectForFile(scriptFile);
- projectIsDirty = false;
- }
- return project;
- }
-
- /**
- * 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("scriptFile==null");
- }
- if (project == null || projectIsDirty) {
- project = env.createProjectForFile(scriptFile);
- }
- //we already set isDirty to true in order to make sure we didn't reuse
- //this project next time getRenewed is called.
- projectIsDirty = true;
- return project;
- }
-
- /**
- * name of the magic setUp target.
- */
- private static final String SETUP = "setUp";
-
- /**
- * prefix that identifies test targets.
- */
- private static final String TEST = "test";
-
- /**
- * name of the magic tearDown target.
- */
- private static final String TEARDOWN = "tearDown";
-
- /**
- * name of the magic suiteSetUp target.
- */
- private static final String SUITESETUP = "suiteSetUp";
-
- /**
- * name of the magic suiteTearDown target.
- */
- private static final String SUITETEARDOWN = "suiteTearDown";
-
- private boolean setUp;
- private boolean tearDown;
- private boolean suiteSetUp;
- private boolean suiteTearDown;
-
- public List scanFile() {
- Project newProject = getCurrentProject();
- Map targets = newProject.getTargets();
- setUp = targets.containsKey(SETUP);
- tearDown = targets.containsKey(TEARDOWN);
- suiteSetUp = targets.containsKey(SUITESETUP);
- suiteTearDown = 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);
- }
- }
- return testTargets;
- }
-
- public boolean startSuite() {
- getCurrentProject().fireBuildStarted();
- if (suiteSetUp) {
- try {
- Project newProject = getCleanProject();
- newProject.executeTarget(SUITESETUP);
- } catch (AssertionFailedException e) {
- env.fireStartTest(SUITESETUP);
- env.fireFail(SUITESETUP, e);
- return false;
- } catch (BuildException e) {
- env.fireStartTest(SUITESETUP);
- fireFailOrError(SUITESETUP, e);
- return false;
- }
- }
- return true;
- }
-
- public void runTarget(String name) {
- Project newProject = getCleanProject();
- Vector v = new Vector();
- if (setUp) {
- v.add(SETUP);
- }
- v.add(name);
- // create and register a logcapturer on the newProject
- LogCapturer lc = new LogCapturer(newProject);
- try {
- env.fireStartTest(name);
- newProject.executeTargets(v);
- } catch (AssertionFailedException e) {
- env.fireFail(name, e);
- } catch (BuildException e) {
- fireFailOrError(name, e);
- } 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);
- // clean up
- if (tearDown) {
- try {
- newProject.executeTarget(TEARDOWN);
- } catch (final AssertionFailedException e) {
- env.fireFail(name, e);
- } catch (final BuildException e) {
- fireFailOrError(name, e);
- }
- }
- }
- }
-
- public void endSuite(Throwable caught) {
- if (suiteTearDown) {
- try {
- Project newProject = getCleanProject();
- newProject.executeTarget(SUITETEARDOWN);
- } catch (AssertionFailedException e) {
- env.fireStartTest(SUITETEARDOWN);
- env.fireFail(SUITETEARDOWN, e);
- } catch (BuildException e) {
- env.fireStartTest(SUITETEARDOWN);
- fireFailOrError(SUITETEARDOWN, e);
- }
- }
- getCurrentProject().fireBuildFinished(caught);
- }
-
- /** Report a failure or an exception for the test target name */
- private void fireFailOrError(String name, BuildException e) {
- boolean failed = false;
- // try to see whether the BuildException masks
- // an AssertionFailedException. If so, treat
- // it as failure instead of error.
- Throwable t = e.getCause();
- while (t != null && t instanceof BuildException) {
- if (t instanceof AssertionFailedException) {
- failed = true;
- env.fireFail(name, (AssertionFailedException) t);
- break;
- }
- t = ((BuildException) t).getCause();
- }
-
- if (!failed) {
- env.fireError(name, e);
- }
- }
-
- }
-
/**
* Processes a single build file.
*/
Added: 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=738248&view=auto
==============================================================================
--- ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java (added)
+++ ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java Tue Jan 27 21:18:22 2009
@@ -0,0 +1,326 @@
+package org.apache.ant.antunit;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+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.
+ */
+public class AntUnitScriptRunner {
+
+ /**
+ * name of the magic setUp target.
+ */
+ private static final String SETUP = "setUp";
+
+ /**
+ * prefix that identifies test targets.
+ */
+ private static final String TEST = "test";
+
+ /**
+ * name of the magic tearDown target.
+ */
+ private static final String TEARDOWN = "tearDown";
+
+ /**
+ * name of the magic suiteSetUp target.
+ */
+ private static final String SUITESETUP = "suiteSetUp";
+
+ /**
+ * name of the magic suiteTearDown target.
+ */
+ private static final String SUITETEARDOWN = "suiteTearDown";
+
+ /**
+ * Object used to interact with the environment (for example an ant task or a junit runner)
+ */
+ 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;
+
+ /**
+ * 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
+ */
+ private boolean isSuiteStarted;
+
+ /**
+ * Does that script have a setUp target (defined when scanning the script)
+ */
+ private boolean hasSetUp;
+
+ /**
+ * Does that script have a tearDown target (defined when scanning the script)
+ */
+ private boolean hasTearDown;
+
+ /**
+ * Does that script has a suiteSetUp target.
+ */
+ private boolean hasSuiteSetUp;
+
+ /**
+ * Does that script has a suite tearDown target that should be executed.
+ */
+ private boolean hasSuiteTearDown;
+
+ /**
+ * The project currently used.
+ */
+ private Project project = null;
+
+ /**
+ * Indicates if a target has already be executed using this project.
+ * Value is undefined when project is null.
+ */
+ private boolean projectIsDirty;
+
+
+ /**
+ * Create a new AntScriptRunner on the given environment.
+ * @param env The environment used to create project and where the test progress will be
+ * notified.
+ */
+ public AntUnitScriptRunner(AntUnitExecutionPlatform env) {
+ if (env == null) {
+ throw new AssertionError();
+ }
+ 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();
+ }
+ if (project == null) {
+ project = env.createProjectForFile(scriptFile);
+ projectIsDirty = false;
+ }
+ return project;
+ }
+
+ /**
+ * 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);
+ }
+ //we already set isDirty to true in order to make sure we didn't reuse
+ //this project next time getCleanProject is called.
+ projectIsDirty = true;
+ return project;
+ }
+
+ /**
+ * Provide the list of test targets of the active antunit script.
+ * @pre isActive()
+ * @return List<String> List of test target names
+ */
+ 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;
+ return testTargets;
+ }
+
+ /**
+ * Executes the suiteSetUp target if presents and report any execution error.
+ * 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();
+ }
+ getCurrentProject().fireBuildStarted();
+ if (hasSuiteSetUp) {
+ try {
+ Project newProject = getCleanProject();
+ newProject.executeTarget(SUITESETUP);
+ } catch (AssertionFailedException e) {
+ env.fireStartTest(SUITESETUP);
+ env.fireFail(SUITESETUP, e);
+ return false;
+ } catch (BuildException e) {
+ env.fireStartTest(SUITESETUP);
+ fireFailOrError(SUITESETUP, e);
+ return false;
+ }
+ }
+ isSuiteStarted = true; //set to true only if suiteSetUp executed properly.
+ return true;
+ }
+
+ /**
+ * Run the specific test target, possibly between the setUp and tearDown targets if
+ * it exists. Exception or failures are reported to the execution environment.
+ * @param name name of the test target to execute.
+ */
+ public void runTarget(String name) {
+ if (!isSuiteStarted) {
+ throw new AssertionError();
+ }
+ Project newProject = getCleanProject();
+ Vector v = new Vector();
+ if (hasSetUp) {
+ v.add(SETUP);
+ }
+ v.add(name);
+ // create and register a logcapturer on the newProject
+ LogCapturer lc = new LogCapturer(newProject);
+ try {
+ env.fireStartTest(name);
+ newProject.executeTargets(v);
+ } catch (AssertionFailedException e) {
+ env.fireFail(name, e);
+ } catch (BuildException e) {
+ fireFailOrError(name, e);
+ } 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);
+ // clean up
+ if (hasTearDown) {
+ try {
+ newProject.executeTarget(TEARDOWN);
+ } catch (final AssertionFailedException e) {
+ env.fireFail(name, e);
+ } catch (final BuildException e) {
+ fireFailOrError(name, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public void endSuite(Throwable caught) {
+ if (!isScanned) {
+ throw new AssertionError();
+ }
+ if (hasSuiteTearDown) {
+ try {
+ Project newProject = getCleanProject();
+ newProject.executeTarget(SUITETEARDOWN);
+ } catch (AssertionFailedException e) {
+ env.fireStartTest(SUITETEARDOWN);
+ env.fireFail(SUITETEARDOWN, e);
+ } catch (BuildException e) {
+ env.fireStartTest(SUITETEARDOWN);
+ fireFailOrError(SUITETEARDOWN, e);
+ }
+ }
+ getCurrentProject().fireBuildFinished(caught);
+ isSuiteStarted = false;
+ }
+
+ /** Report a failure or an exception for the test target name */
+ private void fireFailOrError(String name, BuildException e) {
+ boolean failed = false;
+ // try to see whether the BuildException masks
+ // an AssertionFailedException. If so, treat
+ // it as failure instead of error.
+ Throwable t = e.getCause();
+ while (t != null && t instanceof BuildException) {
+ if (t instanceof AssertionFailedException) {
+ failed = true;
+ env.fireFail(name, (AssertionFailedException) t);
+ break;
+ }
+ t = ((BuildException) t).getCause();
+ }
+
+ if (!failed) {
+ env.fireError(name, e);
+ }
+ }
+
+}
\ No newline at end of file
Propchange: ant/antlibs/antunit/trunk/src/main/org/apache/ant/antunit/AntUnitScriptRunner.java
------------------------------------------------------------------------------
svn:eol-style = native