What is Ant and How Does Jameleon Use Ant?

Ant is a tool that makes compiling, packaging and even running Java applications easier.

Jameleon uses Ant to help make building custom tags, registering them and executing Jameleon test cases easier. Currently the GUI cannot be used to register nor build custom tags.

Add the following line to the build.xml which needs access any of the Jameleon Ant Tasks

<taskdef resource="ant/JameleonAntTasks.properties" format="properties" classpathref="base.classpath"/>

Jameleon Ant Tasks?

Jameleon provides the following Ant tasks.

Task FunctionShort Description
Upgrade Jameleon TaskApplies any needed configuration changes between releases. This is new as of jameleon-core-3.3-M3
Tag Registration TaskRegisters Java files matching a given criteria in Jameleon.
Test Case Execution TaskExecutes Jameleon test case scripts in the same JVM as Ant is running in.
Test Case Execution Separate VM TaskExecutes Jameleon test case scripts in a separate JVM from the one Ant is running in.

Upgrade Jameleon Task

This tag is used to make any required changes to your configuration and or directory structure that may occur between version releases. This tag is new as of Jameleon-core-3.3-M3 and may or may not need to be executed in future releases.

The UpgradeTask has the following attributes:

attributeDescriptionRequiredDefault
environmentPropertiesThe location of the Environment.properties file to be affected.YESres/Environment.properties
jameleonGUIPropertiesThe location of the jameleon-gui.properties file to be affected.NOlib/jameleon-gui.properties

Tag Registration Task

The Tag Registration Task auto registers any Jameleon tags into the Jameleon Scripting Engine ( Jelly ). Simply by adding the appropriate javadoc tag, this task will know the required information about the tags to be registered.

The JameleonXDoclet task has the following attributes:

attributeDescriptionRequiredDefault
outputdirThe directory to save the file(s) to. This directory should be included in the jar file that is created from all of the custom tags. It is recommended to use the same location the compiled java files are compiled to.YESN/A
outputfilenameThe name of the file to save. Unless being used by a plug-in developer, this setting should not be changed. For plug-in developers, this file name should be the name of your plug-in and all plugins should end in -plugin. So for a jRex plug-in, the outputfilename would be jrex-plugin.propertiesNOTestCaseTagDefs.properties
quietDon't print warnings for files that don't have the appropriate tags.NOfalse
isA The class types to include in the registration. In other words, all classes that extend or implement the value of isA will be parsed for information. If you're tag isn't getting registered, it could be that you aren't extending FunctionTag. In that case, just change the isA to the class your tag is extending. NOnet.sf.jameleon.function.FunctionTag.

This task also accepts an Ant fileset to define where the source files that need registering are. For example, to register source files that exist in src/java where the registered files would be placed in build, the following would work:

<target name="register.tags" description="Registers Custom Tags">
    <taskdef resource="ant/JameleonAntTasks.properties" 
             format="properties" 
             classpathref="classpath"/>
    <jmln-register outputdir="build">
        <fileset dir="src/java">
            <include name="**/*.java"/>
        </fileset>
    </jmln-register>
</target>

Syntax Reference Docs Generator

Once all of the tags are registered, you can generate a file that describes the details of each tag. TODO: add examples. There is currently an example in the jameleon-core/src/xml/standard-build.xml file.

The the following attributes are supported

attributeDescriptionRequiredDefault
outputFileThe file to generateYESxdocs/syntax-reference.xml
pluginThe begining of the .properties file to generate from. For the selenium plug-in, this would be selenium-plugin.YESTestCaseTagDefs - or the file that is generated for custom tags
templateNameThe template to use for file generation. Not that the file is loaded through the CLASSPATH.YESsyntaxReference.txt - This file is bundled with jameleon-core.jar
templateParamThis is a nested tag set. <templateParam name="templateVarName" value="var value"/>. The existing template expects a variable called "pluginName" which is really the library name (i.e. HtmlUnit).NON/A

Test Case Execution Task

This tasks is used to execute test cases that match a certain pattern. If any of the test cases fail, the build fails with a list of files, line numbers and short descriptions why they failed.

All of the jar files that come with Jameleon and any plug-ins must be in the CLASSPATH. The ExecuteTestCaseTask task has the following attributes and it supports the Ant fileset data type as well as the selectortype.

Atribute NameDescriptionDefault
debug Prints all stack traces to std out. This is very useful when the test case won't execute for some reason of if you aren't sure whey something is happening. false
throwExceptionOnFailure Throws a build exception when a test fails if set to true. true
waitTimeBetweenScripts Waits n milliseconds between each script being executed. 0
printTestSuiteSummary This is used when want to break up your tests into several test suites and run any number of test suites, but only include the test suite summary at the bottom once. Set this to false when you don't want to print out the summary. true

The fileset data type allows test cases to be executed based on the filename and/or directory structure. The selector option (which is encapsulated in a fileset) is used to scan for text in the matching files.

The selector Ant tag can be used to execute all test cases that have a keyword or that contain a certain functional point. Because of the nature of the scripting engine, unknown tags are ignored. This is another good reason to use test case doc tags and set a selector to execute all files that contain the tag and value in them. For example, to execute all test cases with a test-case-level of SMOKE:

<target name="run.tests" description="Execute Smoke tests">                        
    <taskdef resource="ant/JameleonAntTasks.properties" 
             format="properties" 
             classpathref="classpath"/>

    <jmln-test debug="true">
        <fileset dir="scripts">
            <include name="**/*.xml"/>
            <exlcude name="**/*.fragment"/>
            <contains text="test-case-level>SMOKE" casesensitive="no"/>
        </fileset>
    </jmln-test>
</target>

This would execute all test cases in the scripts directory, containing the word test-case-level>SMOKE, except for files that end in .fragment.

Sometimes you may want to pass in a variable that can be used in a Jameleon script. This can be accomplished via the <variable/> tag. It has name and value attributes that can be set. The following is an example of how to use it:

<target name="run.variable.test" description="Runs a script, passing in a variable on the fly">                        
    <taskdef resource="ant/JameleonAntTasks.properties"
             format="properties" 
             classpathref="classpath"/>

    <jmln-test debug="true">
        <fileset dir="scripts">
            <include name="somescript.xml"/>
        </fileset>
        <variable name="varName" value="varValue"/>
    </jmln-test>
</target>
The variable ${varName} can now be used inside any scripts that match the fileset; in this case, just somescript.xml.

Sometimes you may want to pass in jameleon.conf settings via Ant. This can be accomplished via the <config/> tag. It has name and value attributes that can be set. The following is an example of how to use it:

<target name="run.alpha.tests" description="Runs all scripts under the alpha testEnvironment and sf organization">                        
    <taskdef resource="ant/JameleonAntTasks.properties"
             format="properties" 
             classpathref="classpath"/>

    <jmln-test debug="true">
        <fileset dir="scripts">
            <include name="somescript.xml"/>
        </fileset>
        <config name="testEnvironment" value="alpah"/>
        <config name="organization" value="sf"/>
    </jmln-test>
</target>
These settings override the settings in jameleon.conf.

While executing several tests simultaneously is not officially supported, it could drastically reduce test execution time. To execute several scripts at the same time, the <parallel/> Ant task can be used. A possible strategy to do this might be to create several "run" targets, representing different groups of test suites. These suites can then be executed in threads. The only caveat to this is that the first suite of tests being executed must run at least 1500 milliseconds before the other ones are. The following is an example:


<taskdef resource="ant/JameleonAntTasks.properties" 
         format="properties" 
         classpathref="classpath"/>

<target name="test.admin" description="Run all scripts for the foo admin application">
    <jmln-test printTestSuiteSummary="false" >
        <fileset dir="scripts/admin">
            <include name="**.xml"/>
        </fileset>
    </jmln-test>
</target>

<target name="test.userprefs" description="Run all scripts for the user prefs application">
    <jmln-test printTestSuiteSummary="false" >
        <fileset dir="scripts/userprefs">
            <include name="**.xml"/>
        </fileset>
    </jmln-test>
</target>

<target name="test.crm" description="Run all scripts for the crm application">
    <jmln-test printTestSuiteSummary="false" >
        <fileset dir="scripts/crm">
            <include name="**.xml"/>
        </fileset>
    </jmln-test>
</target>

<target name="test.sales" description="Run all scripts for the sales lead application">
    <jmln-test printTestSuiteSummary="false" >
        <fileset dir="scripts/sales">
            <include name="**.xml"/>
        </fileset>
    </jmln-test>
</target>

<target name="print.test.summary" description="Prints the test case execution summary at the end of the HTML results">
    <jmln-test printTestSuiteSummary="true" >
        <fileset dir="tst/xml/acceptance">
            <exclude name="*.*"/>
        </fileset>
    </jmln-test>
</target>

<target name="test.suites" description="Runs all test suites in order"
        depends="test.mapvariables, test.prop, test.csv, print.test.summary"/>

<target name="test.threaded">
    <parallel>
        <antcall target="test.admin"/>
        <antcall target="test.userprefs"/>
        <antcall target="test.crm"/>
        <antcall target="test.sales"/>
    </parallel>
    <!-- Run this one last so the correct summary is printed -->
    <antcall target="print.test.summary"/>
</target>

Test Case Execution Separate VM Task

The ExecuteTestCaseSeparateVMTask acts mostly the same as the ExecuteTestCaseTask,except it executes under a different VM. This makes it easier to run tests under IDEs like Eclipse or even plug-ins that JNI like the jiffie-plugin.

The following attributes are supported by this tag:

Attribute NameDescriptionRequired
classpathrefA reference to the classpath used when running this tagtrue if the nested classpath tag is not used
forkExecute in a separate VMtrue - Default is true
newenvironment Do not propagate old environment when new environment variables are specified. Default is "false" (ignored if fork is disabled). false - Default is false
baseDir The directory to start the JVM in. false - Defaults to the Ant project baseDir attribute
failOnError Fails the build when an error occurs. false - Defaults to false
timeout Time in milliseconds to wait until the execution halts false - Defaults to 0
separateVmPerScript Execute each script in a separate JVM. This is helpful for code that doesn't clean up memory very well. The side effect of using this feature is that the HTML logs (TestResults.html) file counts each test script as a suite of test scripts. In other words, percentages and total numbers will only represent the single script executed. false - Defaults to false
printFooter When separateVmPerScript is set to true, the test results are not calculated correctly because the logging system is started and stopped between each test case execution. The result of this is TestResults.xml file with a summary for each script. To get rid of this, set printFooter to false and the footer or summary will no longer be logged. false - Defaults to true

An example might look like:

<target name="run.tests.vm" description="Execute Smoke Tests in a separate VM">                        
    <taskdef resource="ant/JameleonAntTasks.properties" 
             format="properties" 
             classpathref="classpath"/>
    <jmln-test classpathref="classpath">
        <fileset dir="scripts">
            <include name="**/*.xml"/>
            <exlcude name="**/*.fragment"/>
            <contains text="test-case-level>SMOKE" casesensitive="no"/>
        </fileset>
    </jmln-test>
</target>