Running Cactus tests from Ant

Last update : August 25 2002
Doc for : v1.4

About
  • What is Cactus ?
  • News
  • Changes
  • Features/Status
  • Goals
  • Roadmap/Todo
  • Contributors
  • Contributing
  • Cactus Users
  • Tested on ...
  • License


  • Downloads
  • Downloads


  • Documentation
  • How it works ?
  • Getting Started
  • Mock vs Container
  • Javadocs
  • FAQ


  • Howto Guides
  • Classpath Howto
  • Config Howto
  • Migration Howto
  • TestCase Howto
  • Jsp Howto
  • Runner Howto
  • Security Howto
  • Ant Howto
  • HttpUnit Howto
  • Sample Howto
  • EJB Howto
  • IDE Howto
  • Tomcat Howto
  • JUnitEE Howto


  • Support
  • Bug database
  • Mailing list


  • Misc.
  • Why the name ?
  • Logo Challenge
  • Resources
  • Test Coverage
  • Stats


  • Developers
  • CVS
  • Coding Conventions
  • Build results
  • Release Checklist


  • Introduction

    Note You need to have a good understanding of Ant before reading this tutorial. If you don't, I suggest you read the Ant User Manual first.

    This tutorial explains how start Cactus tests from your Ant build script (i.e. build.xml).

    The Ant tasks involved for running a Cactus test are the following :

    • Step 0 : (optional) Deploy configuration files for your container,
    • Step 1 : Package your Cactus tests as a WAR file and deploy it to your servlet engine webapps directory,
    • Step 2 : Start your servlet engine if it is not already started,
    • Step 3 : Run the tests using JUnit,
    • Step 4 : Stop the servlet engine (if need be)

    Cactus provides a custom Ant task (called the runservertests task) that helps perform all these tasks. The rest of this tutorial will explain how to write an Ant build file (build.xml) that performs these tasks and use the Cactus custom Ant task.

    During the remainder of this tutorial we will show examples for Tomcat 4.0. However, the principle can be applied to any other container. Ant Scripts for other containers can be found in the /sample/build directory where you have unpacked the Cactus distribution.


    The 'runservertests' task

    This task will perform several actions, in the following order :

    • Check if a server is already started by constantly trying to call the test URL defined by the testURL attribute (see the example below),
    • If a server is not started, call the Ant target defined by the startTarget attribute (see the example below). This target is supposed to start your container. The runservertests task will then constantly poll the server by calling the test URL until the server answers back,
    • It will then call the Ant target defined by the testTarget attribute (see the example below). This target is supposed to start the unit tests. This is usually implemented by using the Ant junit task,
    • Once the tests are finished (i.e. when the testTarget has finished executing), it will then call the Ant target defined by the stopTarget attribute (see the example below). This target is supposed to stop the container. The runservertests task will then constantly poll the server by calling the test URL until the server stops answering, at which point it will consider the server to be stopped. Note that the stopTarget will only get called if the server was not already started when the runservertests task began executing. This is to allow keeping running servers for intensive debugging phases.

    The runservertests task is generic in the sense that you are free to implement the startTarget, testTarget and stopTarget as you wish and they will get called at the right time.

    Example :

    <!--
       ========================================================================
         Run Tomcat 4.0 tests
       ========================================================================
    -->
    <target name="test.tomcat.40" depends="prepare.test.tomcat.40"
        if="tomcat.home.40" description="Run tests on Tomcat 4.0">
    
        <!-- Start the servlet engine, wait for it to be started, run the
             unit tests, stop the servlet engine, wait for it to be stopped.
             The servlet engine is stopped if the tests fail for any reason -->
    
        <runservertests
            testURL="http://localhost:${test.port}/test/ServletRedirector?Cactus_Service=RUN_TEST"
            startTarget="start.tomcat.40"
            stopTarget="stop.tomcat.40"
            testTarget="test"/>
    
    </target>
    

    Before you can execute the runservertests task, you need to define it for Ant as it is not a standard Ant task. A good place to do this is in an init target.

    Example :

    <!--
       ======================================================================
         Initialize the build. Must be called by all targets
       ======================================================================
    -->
    <target name="init">
        [...]
        <taskdef name="runservertests" classname="org.apache.cactus.ant.RunServerTestsTask">
            <classpath>
                <pathelement location="${cactus.ant.jar}"/>
            </classpath>
        </taskdef>
        [...]
    </target>
    

    where ${cactus.ant.jar} is an Ant property that points to the cactus-ant.jar file found in the lib/ directory where you unpacked the Cactus distribution.

    Note The prepare.test.tomcat.40 target is described in Step 0 below.

    Note The tomcat.home.40 is simply an Ant property that points to the directory where Tomcat 4.0 has been installed. If this property is not defined we don't run the tests.


    Step 0: Deploy container configuration files

    There are 2 possibilities for configuring your application server :

    1. You install it somewhere on your computer (or on another machine) and you deploy your test WAR (see Step 1 below) by copying it to the right subdirectory within it. Your WAR will then be placed alongside with others and your webapp will use the configuration files common to all webapps,
    2. Or, you can create your own set of container configuration files, hosted within your project, that you copy to your own deployment subdirectory (i.e. not shared).

    In the provided Cactus Ant scripts, we have decided to follow approach 2 for the following reasons :

    • We keep the control of our project files as they are deployed within the directory of our project and thus it is easy to perform a clean of all generated files,
    • We do not "pollute" the installed container by dropping files within it and we do not need to modify global configuration files that may prevent other applications we are developing from not running someday (because we would have made an incompatible change),
    • We completely control our needed container configuration.
    • We can guarantee to the user who wants to try the Cactus sample application that it will not deploy anything outside the scope of the Sample directory. Unlike windows applications that you install and that copies tens of DLL to shared directory, overwrite existing files, ... :(

    However, this may not be the best approach for all cases, as :

    • It is more difficult to set up as you need to understand how your container is configured (However, we have already done the job for you for most of the existing containers),
    • You have only a single application to run and test and have dedicated your application server installation for it so you don't care about putting files in there and modifying global configuration,
    • You want to be able to deploy in production several webapps that share the same server and thus must coexist and share common configuration files.

    If you choose solution 1, then you can simply skip this step. The only actions to perform will be, for some containers, to edit their configuration files to tell them about your webapp (some will automatically pick you test WAR if you drop it in the correct directory).

    Example :

    <!--
       ========================================================================
         Prepare directories and variables for running the tests
       ========================================================================
    -->
    <target name="prepare.test.tomcat.40"
        depends="check.test.tomcat.40,testwar" if="tomcat.home.40">
    
        <echo message="tomcat.home.40 = ${tomcat.home.40}"/>
    
        <property name="target.tomcat40.dir"
            value="${target.test.dir}/tomcat40"/>
        <property name="conf.tomcat40.dir" value="${conf.test.dir}/tomcat40"/>
    
        <!-- Create work and conf directories and copy configuration files -->
        <mkdir dir="${target.tomcat40.dir}/conf"/>
        <mkdir dir="${target.tomcat40.dir}/work"/>
        <mkdir dir="${target.tomcat40.dir}/webapps"/>
    
        <!-- Delete some config file so that they will be copied every time -->
        <delete file="${target.tomcat40.dir}/conf/server.xml"/>
    
        <!-- Remove the auto deployed webapp so that it is redeployed every
             time -->
        <delete dir="${target.tomcat40.dir}/webapps/test"/>
    
        <copy todir="${target.tomcat40.dir}/conf" filtering="on">
            <fileset dir="${conf.tomcat40.dir}"/>
        </copy>
    
        <!-- Copy the Tomcat web.xml -->
        <copy file="${tomcat.home.40}/conf/web.xml"
            todir="${target.tomcat40.dir}/conf"/>
    
        <!-- Copy the war file -->
        <copy file="${target.test.dir}/test.war"
            tofile="${target.tomcat40.dir}/webapps/test.war"/>
    
    </target>
    

    Note The ${target.test.dir} Ant property needs to be defined prior to calling this target and needs to be set to the location where the tests will be deployed. It should be set to any subdirectory of your output directory. This property will also be used later on in step 1 to copy the test WAR file.

    Note The ${conf.test.dir} Ant property also needs to be defined prior to calling this target and represent the location of server configuration files (in the current example of Tomcat 4.0, these are the global web.xml and server.xml).


    Step 1: create and deploy test WAR file

    Creating a WAR file is the preferred way of deploying Cactus tests to your servlet engine. Check the Getting Started guide and the example below for details on what files to include in the WAR.

    Example :

    <!--
       ========================================================================
         Create a Cactus test war file for the sample application.
       ========================================================================
    -->
    <target name="testwar" depends="compile">
    
        <!-- Create the war file -->
        <war warfile="${target.test.dir}/test.war"
             webxml="${conf.test.dir}/web.xml">
    
            <classes dir="${target.classes.sample.dir}"/>
            <classes dir="${target.classes.unit.dir}"/>
    
            <!-- log_server.properties need to be in the server classpath -->
            <classes dir="${conf.test.dir}">
                <include name="log_server.properties"/>
                <include name="cactus.properties"/>
            </classes>
    
            <lib dir="${target.lib.dir}"/>
            <fileset dir="${web.dir}"/>
       </war>
    
    </target>
    

    where :

    • ${conf.test.dir} : directory containing configuration files for the test,
    • ${target.classes.*.dir} : directory where the java classes have been compiled. These are the classes under test + the test classes,
    • ${target.lib.dir} : directory containing the needed jars (junit.jar, cactus.jar, ...).
    • ${web.dir} : directory containing the web files to include in the test webapp (JSPs, HTML, ...).

    Note The compile target is used to compile all java classes into the ${target.classes.*.dir} directory.


    Step 2: Start the container

    Example :

    <!--
       ========================================================================
         Start Tomcat 4.0
       ========================================================================
    -->
    <target name="start.tomcat.40">
    
        <java classname="org.apache.catalina.startup.Bootstrap" fork="yes">
            <jvmarg value="-Dcatalina.home=${tomcat.home.40}"/>
            <jvmarg value="-Dcatalina.base=${target.tomcat40.dir}"/>
            <arg value="start"/>
            <classpath>
              <fileset dir="${tomcat.home.40}">
                  <include name="bin/bootstrap.jar"/>
              </fileset>
            </classpath>
        </java>
    
    </target>
    

    Step 3: Run the unit tests

    We start the unit test by calling a JUnit test runner (we use the text runner in this example). Example :

    <!--
       ========================================================================
         Run the client JUnit test cases.
       ========================================================================
    -->
    <target name="test">
    
        <junit printsummary="yes" haltonfailure="yes" haltonerror="yes"
            fork="yes">
    
            <classpath>
                <!-- Cactus.propertie and log_client.properties need to be in
                     the classpath -->
                <pathelement location="${target.conf.dir}"/>
                <pathelement location="${target.classes.sample.dir}"/>
                <pathelement location="${target.classes.unit.dir}"/>
                <path refid="project.class.path"/>
            </classpath>
    
            <formatter type="plain" usefile="false"/>
            <test name="org.apache.cactus.unit.TestAll"/>
            <test name="org.apache.cactus.sample.TestAll"/>
    
        </junit>
    
    </target>
    

    Note The list of jars to include in your classpath is explained and detailed in the Classpath Howto guide.


    Step 4: Stop the container

    Example :

    <!--
       ========================================================================
         Stop Tomcat 4.0
       ========================================================================
    -->
    <target name="stop.tomcat.40">
    
        <java classname="org.apache.catalina.startup.Bootstrap" fork="yes">
            <jvmarg value="-Dcatalina.home=${tomcat.home.40}"/>
            <jvmarg value="-Dcatalina.base=${target.tomcat40.dir}"/>
            <arg value="stop"/>
            <classpath>
              <fileset dir="${tomcat.home.40}">
                  <include name="bin/bootstrap.jar"/>
              </fileset>
            </classpath>
        </java>
    
    </target>
    



    Copyright © 2000-2002 The Apache Software Foundation. All Rights Reserved.