In the past weeks I'm configuring a Continuous Integration environment with CruiseControl. It wasn't a easy task. CruiseControl lacks from updated documentation and you have to know Ant very well (in my view) to get along with it. Since Ant isn't a easy thing to learn (again, in my view) I had some hard time putting all to work. In this series Ant Power, Cruise under Control and Selenium fuel, I'll try to show some of what I have learned.

Can we run selenium?

One not always in cookbooks is conditional behavior of Ant. Ant is capable of a myriad of conditionals but if you look at the official manual you will not find a good example on how to use it. So let's see how Ant was used in my project.

As you probably know, Selenium is a test framework that can emulates a user using a browser. It's a good way to automate acceptance tests. But to run selenium the project has to successfully be deployed on server, so how to know if the project was deployed?

  • First: Learn target depends

Ant can establish dependencies between targets, here a simple build.xml file.

 <project name="target_depends" default="build">
    <target name="setup">
            <echo message="initial setup." />
    </target>
    <target name="build" depends="setup">
            <echo message="building..." />
    </target>
</project>

When you run this build file you get this:

$ ant -f a.xml build
Buildfile: a.xml

setup:
     [echo] initial setup.

build:
     [echo] building...

BUILD SUCCESSFUL
Total time: 0 seconds

What happens is that the target build declares a dependency which is the target setup, so Ant takes care to execute setup before build. Nothing too complex for now.

  • Second: Learn target if/unless

Something clever about Ant is the if/unless attributes on target element, you can abort the execution of a target if you need to. In the next build file we have three targets, the first inhibits the execution of the second.

<project name="target_depends" default="build">
    <target name="setup">
            <echo message="initial setup."/>
            <property name="setup_is_ok" value=""/>
    </target>
    <target name="notify_failed_setup" unless="setup_is_ok">
            <echo message="setup failed."/>
    </target>
    <target name="build" depends="setup,notify_failed_setup">
          <echo message="building."/>
  </target>
</project>

When you run this build file:

$ ant -f a.xml build
Buildfile: a.xml

setup:
     [echo] initial setup.

notify_failed_setup:

build:
     [echo] building.

BUILD SUCCESSFUL
Total time: 0 seconds

You can note that when we set the property setup_is_ok and since the next target on the chain, notify_failed_setup, has a unless attribute this target will not be fired. The catch here is on the depends of the build target, it tell us the order of our build. Ant doesn't have a if/then/else per se, but with depends and if/unless attributes on the target element you can do similar behavior.

<target name="build" depends="setup,notify_failed_setup">
  • Last: A simple waitfor it

For the last step I will use waitfor to know if a project have been successfully deployed, if it is, then we run tests, if is not, I will email me to know that my project isn't deployed.

 <project name="cond_demo" default="run_tests" >

  <target name="check_if_page_exists">
    <waitfor maxwait="5" maxwaitunit="second" checkevery="1000" timeoutproperty="page_not_loaded">
      <http url="http://localhost/"/>
    </waitfor>
  </target>

  <target name="email_failed_deployment" if="page_not_loaded">
    <mail
      from="Cruise Control"
      tolist="me"
      subject="Failed to deploy project: ${ant.project.name}"/>

  </target>
                 
  <target name="run_tests" depends="check_if_page_exists,email_failed_deployment" unless="page_not_loaded">
    <echo message="Will run some tests!" />
  </target>

  </project>

Now I have some smart behavior, if Ant can't load the page in waitfor in 5 seconds, it will set the property page_not_loaded, this will validate the call to target email_failed_deployment and invalidate the call to target run_tests.

The waitfor task returns ok if the server returns a code 200, if the server returns 404 the waitfor continues until maxwait. Since during deployment (in JBoss) the server returns 404, for my setup is a way to test a successful deployment. The run of this last build file I leave to the reader.

One last word, use ant -debug in these build examples to see exactly how Ant works these files.

That's it.