|
Last update : September 25 2001
About
What is Cactus ?
Features/Status
Goals
News/Changes
Roadmap/Todo
Contributors
Contributing
License
Feedback
Downloads
Downloads
Documentation
How it works ?
Getting Started
Mock vs Container
API Reference
Howto Guides
Config Howto
TestCase Howto
Ant Howto
HttpUnit Howto
Sample Howto
EJB Howto
IDE Howto
Support
Bug database
Mailing list
FAQ
Misc.
Why the name ?
Resources
Developers
CVS
Coding Conventions
|
Introduction |
 |
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="tests_tomcat"
depends="init,deploy_config,create_test_war" if="tomcat.home">
<!-- We suppose our webapp is named "test" -->
<runservertests testURL="http://localhost:8080/test"
startTarget="start_tomcat"
stopTarget="stop_tomcat"
testTarget="run_tests"/>
</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 the 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}"/>
<pathelement path="${java.class.path}"/>
</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.
 |
The deploy_config target is described in
Step 0 below.
|
 |
The create_test_war target is described in
Step 1 below.
|
 |
The tomcat.home 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 :
-
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,
-
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 :
<!--
======================================================================
Deploy container configuration files
======================================================================
-->
<target name="deploy_config" if="tomcat.home">
<!-- This filter is needed to set the absolute path to the webapps
directory in the Tomcat server.xml configuration file -->
<filter token="out.server.webapp.dir" value="${basedir}/${out.server.dir}/webapps"/>
<!-- Delete the deployed file to ensure that they are reread at every
deployment by Tomcat -->
<delete dir="${out.server.dir}/conf"/>
<delete dir="${out.server.dir}/webapps"/>
<!-- Create work and conf directories and copy configuration files -->
<mkdir dir="${out.server.dir}/conf"/>
<mkdir dir="${out.server.dir}/work"/>
<mkdir dir="${out.server.dir}/webapps"/>
<!-- Copy the Tomcat configuration files to our conf directory -->
<copy file="${conf.server.dir}/web.xml" todir="${out.server.dir}/conf"/>
<copy file="${conf.server.dir}/server.xml"
todir="${out.server.dir}/conf" filtering="on"/>
</target>
|
 |
The ${out.server.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.
|
 |
The ${conf.server.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 test war file that includes the sample application unit
tests and deploy it to the webapps directory
======================================================================
-->
<target name="create_test_war" depends="compile">
<war warfile="${out.server.dir}/webapps/test.war"
webxml="${conf.test.dir}/web.xml">
<classes dir="${out.classes.dir}"/>
<lib dir="${lib.dir}"/>
<fileset dir="${web.dir}"/>
</war>
</target>
|
where :
-
${conf.test.dir} : directory containing configuration
files for the test. Namely web.xml ,
-
${out.classes.dir} : directory where the java classes
have been compiled. These are the classes under test + the test
classes,
-
${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, ...).
 |
The compile target is used to compile all java classes
into the ${out.classes.dir} directory.
|
|
Step 2: Start the container |
Example :
<!--
======================================================================
Start Tomcat 4.0
======================================================================
-->
<target name="start_tomcat">
<java classname="org.apache.catalina.startup.Bootstrap" fork="yes">
<jvmarg value="-Dcatalina.home=${tomcat.home}"/>
<arg value="-config"/>
<arg value="${basedir}/${out.server.dir}/conf/server.xml"/>
<arg value="start"/>
<classpath>
<fileset dir="${tomcat.home}">
<include name="bin/bootstrap.jar"/>
<include name="server/catalina.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 Cactus test cases by starting a JUnit test runner.
======================================================================
-->
<target name="run_tests">
<junit printsummary="yes" haltonfailure="yes" haltonerror="yes" fork="yes">
<classpath>
<!-- The Servlet API jar -->
<pathelement location="${servlet.jar}"/>
<!-- (optional) Will be ignore if log4j.jar is not defined -->
<pathelement location="${log4j.jar}"/>
<pathelement location="${cactus.jar}"/>
<pathelement location="${junit.jar}"/>
<!-- for Cactus 1.2 and above only -->
<pathelement location="${httpclient.jar}"/>
<!-- The test classes and classes to test -->
<pathelement location="${out.classes.dir}"/>
</classpath>
<formatter type="plain" usefile="false"/>
<test name="your.package.YourTestCaseClass1"/>
[...]
<test name="your.package.YourTestCaseClassN"/>
<!-- Or you can gather all the tests in a TestAll class that start
them all -->
<!-- Or you can use the junit task batchtest nested element -->
</junit>
</target>
|
 |
The list of jars to include in your classpath is explained and
detailed in the Getting
Started guide.
|
|
Step 4: Stop the container |
Example :
<!--
======================================================================
Stop Tomcat 4.0
======================================================================
-->
<target name="stop_tomcat">
<java classname="org.apache.catalina.startup.Bootstrap" fork="yes">
<jvmarg value="-Dcatalina.home=${tomcat.home}"/>
<arg value="stop"/>
<classpath>
<fileset dir="${tomcat.home}">
<include name="bin/bootstrap.jar"/>
<include name="server/catalina.jar"/>
</fileset>
</classpath>
</java>
</target>
|
|
|
|