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