Run Citrus using ANT
In this how-to tutorial I will use ANT to manage a Citrus project and we will use Ant to execute Citrus test cases. First of all I downloaded the latest Citrus release archive with dependencies (citrus-with-dependencies-1.x.zip). I have unzipped the archive to a temporary location on my local storage in order to have access to the Citrus binaries and sources.
So now lets start to set up a new Citrus Java project. In contrast to a Maven generated project we have to create our project structure ourself when using Ant. So lets have a look at a usual Citrus project structure. I am using the Eclipse IDE development tool to set up the new Java project. I am also accessing Ant from the command line in this tutorial so you may also want to install Ant first before continuing. See the Ant homepage for detailed installation instructions.
Have a look at the folder structure I created for our new Citrus project
I created a simple Java project in Eclipse called "citrus-sample". I manually added folders and files to the project as follows. The Citrus project knows three source folders, that are also added to the Java build path as source folders:
- src/citrus/java: Storage for generated Java TestNG tests
- src/citrus/resources: Configuration files go in here (e.g. Spring application context files, citrus.properties, log4j.xml, ...)
- src/citrus/tests: XML test case describing files (generated by Citrus)
<project name="citrus-sample" basedir="." default="citrus.run.tests">
<property file="src/citrus/resources/citrus.properties"/>
<path id="citrus-classpath">
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
</path>
<typedef resource="citrustasks" classpath="lib/citrus-ant-tasks-1.2-SNAPSHOT.jar"/>
<target name="compile.tests">
<javac srcdir="src/citrus/java" classpathref="citrus-classpath"/>
<javac srcdir="src/citrus/tests" classpathref="citrus-classpath"/>
</target>
<target name="create.test" description="Creates a new empty test case">
<input message="Enter test name:" addproperty="test.name"/>
<input message="Enter test description:" addproperty="test.description"/>
<input message="Enter author's name:" addproperty="test.author" defaultvalue="${default.test.author}"/>
<input message="Enter package:" addproperty="test.package" defaultvalue="${default.test.package}"/>
<input message="Enter framework:" addproperty="test.framework" defaultvalue="testng"/>
<java classname="com.consol.citrus.util.TestCaseCreator">
<classpath refid="citrus-classpath"/>
<arg line="-name ${test.name} -author ${test.author} -description ${test.description} -package ${test.package} -framework ${test.framework}"/>
</java>
</target>
<target name="citrus.run.tests" depends="compile.tests" description="Runs all Citrus tests">
<citrus package="com.consol.citrus.*"/>
</target>
<target name="citrus.run.single.test" depends="compile.tests" description="Runs a single test by name">
<touch file="test.history"/>
<loadproperties srcfile="test.history"/>
<echo message="Last test executed: ${last.test.executed}"/>
<input message="Enter test name or leave empty for last test executed:" addproperty="testclass" defaultvalue="${last.test.executed}"/>
<propertyfile file="test.history">
<entry key="last.test.executed" type="string" value="${testclass}"/>
</propertyfile>
<citrus test="${testclass}"/>
</target>
</project>
Those who are familiar with Ant will understand this file easily. A Java classpath is defined with its conventional name "citrus-classpath". The classpath definition includes all Java libraries found inside the lib folder. Besides that the build file declares the Citrus special Ant tasks.
<typedef resource="citrustasks" classpath="lib/citrus-ant-tasks-1.2-SNAPSHOT.jar"/>
These Citrus Ant task definitions will help to execute Citrus out of a Ant build script. For instance the Ant task will automatically add the source folders to the classpath. We will handle the Citrus tasks later in this tutorial in more detail. For now we will start with the "create.test" target. This target creates new test cases for your project. So let us give it a try! I execute the "create.test" target from the command line using my seperate Ant installation. To be honest it is more comfortable to use the built-in Eclipse Ant plugin to execute Ant targets, but I choose the command line first to be more independent from the IDE tool.
The target will prompt for some information when executed, see the output below:
$ ant create.test
Buildfile: build.xml
create.test:
[input] Enter test name: MyFirstTest
[input] Enter test description: This is my first Citrus test
[input] Enter author's name: [Christoph]
[input] Enter package: [com.consol.citrus.ant.sample]
[input] Enter framework: [testng]
BUILD SUCCESSFUL
Total time: 21 seconds
The target will ask you for the name of the test first. After that you give a description for the test. The author's default name is located in the "citrus.properties", but you can also specify another author of course. Same thing with the test's package. In the "citrus.properties" you can define a default package or you can type in another package when prompted.
Now that we have given all information for the test Citrus will create all test files automatically. Let us have a look at the generated files.
The generated files are:
- src/citrus/java/MyFirstTest.java: TestNG Java test case that is executable right now
- src/citrus/tests/MyFirstTest.xml: Citrus XML test case describing file
<?xml version="1.0" encoding="UTF-8"?>
<spring:beans xmlns="http://www.citrusframework.org/schema/testcase"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.citrusframework.org/schema/testcase
http://www.citrusframework.org/schema/testcase/citrus-testcase.xsd">
<testcase name="MyFirstTest">
<meta-info>
<author>Christoph</author>
<creationdate>2009-08-19</creationdate>
<status>DRAFT</status>
<last-updated-by>Christoph</last-updated-by>
<last-updated-on>2009-08-19T11:18:06</last-updated-on>
</meta-info>
<description>This is my first Citrus test</description>
<actions>
<echo>
<message>TODO: Code the test MyFirstTest</message>
</echo>
</actions>
</testcase>
</spring:beans>
Citrus created an empty test case that does nothing but print a simple message to the console. The test is in status "DRAFT" which means it is not finished yet but be aware that the test is executable in this state. In case you need to disable the test because it is not entirely finished yet and may cause failures in a test run you can use the status DISABLED. You may code the test first and then change its status to "FINAL" in order to finally enable the test for execution. Right now we do not want to code any additional logic into the test case for this tutorial, so we change its status right now to "FINAL" and try to execute the test with Ant.
We switch again to the command line to execute the Ant target called "citrus.run.single.test". We are asked to type in the name of the test to execute. In our example we type "MyFirstTest" and Citrus will execute the test.
$ ant citrus.run.single.test
Buildfile: build.xml
citrus.run.single.test:
[echo] Last test executed: Unknown
[input] Enter test name: [Unknown] MyFirstTest
CITRUS TESTFRAMEWORK
Found test 'com.consol.citrus.ant.sample.MyFirstTest'
RUNNING CITRUS TESTS
------------------------------------------------------------------------
INIT
Found 0 tasks in init phase
------------------------------------------------------------------------
INIT successfully
------------------------------------------------------------------------
STARTING TEST: MyFirstTest
Initializing TestCase
TestCase using the following global variables:
project.name = Citrus sample
1. action in test chain
echo TODO: Code the test MyFirstTest
TEST FINISHED: MyFirstTest
------------------------------------------------------------------------
FINISH CITRUS TEST
------------------------------------------------------------------------
________________________________________________________________________
CITRUS TEST RESULTS
MyFirstTest : SUCCESS
Found 1 test cases to execute
Skipped 0 test cases (0.0%)
Executed 1 test cases
Tests failed: 0 (0.0%)
Tests successfully: 1 (100.0%)
________________________________________________________________________
Found 0 tasks after
------------------------------------------------------------------------
FINISH successfully
If we have a closer look at the "citrus.run.single.test" target we see how Citrus is called with the special Ant task.
<citrus test="MyFirstTest"/>
The task executes Citrus using the test suite named "citrus-samples". All we need to run one specific test is to specify its name. You can also run multiple test cases when using a space seperated list.
<citrus test="MyFirstTest AnotherTest SomeOtherTest"/>
The execution by test names only is suitable for executing a small amount of test cases. If you want to run a whole package of tests use the package notation instead as it is used in the "citrus.run.tests" target.
<citrus package="com.consol.citrus.*"/>
Citrus will now execute all tests in the package "com.consol.citrus". Also here you are able to run multiple packages by adding them to a space seperated list.
<citrus package="com.consol.citrus.package
com.consol.citrus.someotherpackage"/>
The last option you have when executing Citrus is a TestNG suite xml file. TestNG can configure test suites via XML. We have a look at a very simple testng.xml.
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="citrus-samples">
<test verbose="2" name="com.consol.citrus.ant.sample.MyFirstTest" annotations="JDK">
<classes>
<class name="com.consol.citrus.ant.sample.MyFirstTest"/>
</classes>
</test>
</suite>
The testng.xml is very powerful and you have a lot of options how to group tests together to suites. Citrus can work on those testng.xml files when executed with Ant.
<citrus testngxml="src/citrus/resources/testng.xml"/>
That's it! This is how Citrus connects with a normal Eclipse Java project and Ant. With Ant you can integrate your Citrus tests easily in your continuous build environment, so the tests are executed every time something has changed in the code base of your project.