JUnitEE
$Revision: 1.19 $
    
User's Guide

JUnitEE is an extension to the external linkJUnit test framework. JUnit provides the framework for writing your unit tests, and JUnitEE gives you the possibility to run these tests inside your application server. This has the advantage of testing your EJB/servlet-based application in the same environment it will run when in production.

You may operate the JUnit TestRunner in one of two different modes:

  • in Basic Test Mode the TestRunner will execute a set of test suites which has to be defined manually
  • in Smart Test Mode the TestRunner will try to find all test suites available in one or more jar files included in the .war file and will allow you to choose which of the tests should be run

This guide will tell you how to package JUnitEE and your test cases to a deployable web archive. It will also describe the user interface of the JUnitEE TestRunner and how to integrate JUnitEE with your Ant build process by using the JUnitEE Ant tasks. Finally there are some SecurityManager issues related to the deployment of JUnitEE.

 
Packaging JUnitEE

Adding JUnitEE to your server application is quite easy. You just have to create a web application which contains the JUnitEE Test Servlet and your test classes. Place junitee.jar and junit.jar and the jar containing your tests in the WEB-INF/lib directory of the web archive. The minimal deployment descriptor contains the declaration of the JUnitEE servlet and the corresponding servlet mapping. JUnitEE provides three servlets which differ in the format of the test report they generate by default and the thread mode they use. In general you will use org.junitee.servlet.JUnitEEServlet:

<?xml version="1.0"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>
  <display-name> Einstein Unit Tester Web Application </display-name>

  <servlet>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <description>JUnitEE test runner</description>
    <servlet-class>org.junitee.servlet.JUnitEEServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <url-pattern>/TestServlet/*</url-pattern>
  </servlet-mapping>
</web-app>

IMPORTANT NOTE: Orion Application Server has a bug in it's url pattern matching algorithm that causes some problems for JUnitEE. If you are using Orion please change the servlet mapping in the deployment descriptor to

  <servlet-mapping>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <url-pattern>/TestServlet*</url-pattern>
  </servlet-mapping>


This servlet generates html output by default and does not fork a new thread for test execution.

Another servlet provided by JUnitEE is org.junitee.servlet.JUnitEEThreadedServlet which by default forks a new thread for test execution. This is usefull if test execution takes a long time and therefore could be interrupted by socket or browser timeouts. For the other servlets you get the same behaviour by using the thread parameter in the request. To use this servlet the deployment descriptor looks like this:

<?xml version="1.0"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>
  <display-name> Einstein Unit Tester Web Application </display-name>

  <servlet>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <description>JUnitEE test runner</description>
    <servlet-class>org.junitee.servlet.JUnitEEThreadedServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <url-pattern>/TestServlet/*</url-pattern>
  </servlet-mapping>
</web-app>


In case you prefer xml output you use org.junitee.servlet.JUnitEEXMLServlet:

<?xml version="1.0"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>
  <display-name> Einstein Unit Tester Web Application </display-name>

  <servlet>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <description>JUnitEE test runner</description>
    <servlet-class>org.junitee.servlet.JUnitEEXMLServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <url-pattern>/TestServlet/*</url-pattern>
  </servlet-mapping>
</web-app>


All three servlets support the output request parameter to overwrite the default behaviour, so it is possible to use the org.junitee.servlet.JUnitEEServlet to produce xml output and to get html output out of the org.junitee.servlet.JUnitEEXMLServlet.

To use the Smart Test Mode of JUnitEE you have to tell the servlet which jar file in the WEB-INF/lib folder of your war file contains your test cases. Therefore you have to add an init parameter named searchResources to the servlet declaration. Considering that the jar file WEB-INF/lib/test.jar contains the test classes, this looks like

<servlet>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <description>JUnitEE test runner</description>
    <servlet-class>org.junitee.servlet.JUnitEEServlet</servlet-class>
    <init-param>
      <param-name>searchResources</param-name>
      <param-value>test.jar</param-value>
    </init-param>
  </servlet>


Note that the parameter value is the name of the jar file relative to WEB-INF/lib. You may also tell JUnitEE to search more than one file for your tests. In this case the parameter value is a comma-separated list of file names like in this example:

<servlet>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <description>JUnitEE test runner</description>
    <servlet-class>org.junite.servlet.JUnitEEServlet</servlet-class>
    <init-param>
      <param-name>searchResources</param-name>
      <param-value>unit-test.jar, functional-test.jar</param-value>
    </init-param>
  </servlet>


JUnitEE will look for classes with a name ending with Test or Tests in the jar files you specified.

An alternative way to use the Smart Test Mode is to add a text file named WEB-INF/testCase.txt to your .war file. If no jar files are specified, JUnitEE will look for that file and use the list of test case names declared in testCase.txt instead. testCase.txt has to be a simple text file containing one test class name per line like in this example:

# This is a comment
org.junitee.example.SimpleUnitTests
org.junitee.example.ComplexUnitTests


A convenient way to create the testCase.txt file is by using the JUnitEEWar Ant task.

Finally there is the option to use the search request parameter to specify the resources.

In case you want your test servlet to generate xml output it is possible to define the URL of a stylesheet by using the init parameter named xslStylesheet:

<servlet>
    <servlet-name>JUnitEETestServlet</servlet-name>
    <description>JUnitEE test runner</description>
    <servlet-class>org.junitee.servlet.JUnitEEXMLServlet</servlet-class>
    <init-param>
      <param-name>xslStylesheet</param-name>
      <param-value>myStylesheet</param-value>
    </init-param>
  </servlet>


JUnitEE will use this information to add a stylesheet instruction to the generated xml. Another way to obtain the same result is to use the xsl request parameter.

The final step is to package the test.war together with your application in an EAR and to deploy it to your application server. Now you may start your tests from any browser you like.

The JUnitEE distribution contains an Ant task which automates the creation of the test.war including the deployment descriptor and testCase.txt, so you don't have to create the web archive manually. But anyway it's good to know what's going on behind the scenes.

 
JUnitEE TestRunner

After deploying your test.war the JUnitEE TestRunner is ready to execute your tests. Enter the URL to the JUnitEE servlet in your browser - for the example above this would be http://my.host:port/test/TestServlet where test is the name of the .war and TestServlet is the URL pattern the JUnitEE servlet is mapped to. Your browser should now display the user interface of the JUnitEE TestRunner:

 
Screenshot JUnitEE TestRunner
 

You may now enter the name of your test class in the text field or choose from the list of available test cases. In any case press the corresponding Run button to start execution of the tests. (Note that the lis of available test cases is shown only if the servlet is configured for the Smart Test Mode).

It is also possible to expand all the view to display all available tests. Use the link labeled "show tests" to list all tests:

 
Screenshot JUnitEE TestRunner
 

Now it is possible to select a single test for execution. Use the link labeled "hide tests" to toggle the view back to display test suites only.

After some time - it depends on how long the selected tests will run - your browser will display the test report generated by the JUnitEE TestRunner like in this example:

 
Screenshot JUnitEE TestRunner
 

The test report is separated in three parts:

  • the summary shows the list of all executed test suites and their test result
  • for each test suite there is a list of executed tests with their respective test results
  • for each failed test there is a detailed description of the reason for the failure

The icons showing the result of a test suite/test have the following meaning:

success icontest suite/test successful
failure icontest suite/test failed because an assertion failed
error icontest suite/test failed because of an error

By clicking on one of this icons the corresponding test suite or test will be executed again which is useful if you would like to debug failed tests.

By clicking on the info icon icon in the summary the browser will scroll to the list of corresponding tests. By clicking on the info icon icon in the list of executed tests (available only for failed tests) the browser will scroll to the description of the failure/error.

Here is a description of all request parameters the JUnitEE servlet will accept:

JUnitEE servlet request parameters
ParameterDescriptionRequired
suiteDefines the class name of the test suite to be executed by the test servlet. This parameter may be used multiple times in one request.YES
allTell the servlet to run all tests it has found. This will work only if one of the following conditions is true:
  • the init parameter searchResources of the servlet is set
  • the file WEB-INF/testCase.txt is available
  • the search request parameter is set
No
searchDefine the resource the servlet should use to search for test classes. If there is no searchResource init parameter and no WEB-INF/testCase.txt
outputTell the servlet to generate the test report in the given format. JUnitEE supports
  • html for the html test report described above
  • xml for a test report in xml format
No
xslDefine the URL of an xsl stylesheet. This URL will be used to generate a stylesheet instruction at the beginning of the xml output (in case xml output is active). No
threadTell the servlet to fork a new thread to run the tests. A thread will be forked if this parameter is true and two or more suite parameters or all is set.

You should use this feature for html output only, because in this case the output will be refreshed in the browser until all tests are finished or test execution is stopped by the user. For xml output there is not way for an automatic refresh.
No

 
JUnitEE Ant Task

JUnitEE provides two Ant task to integrate execution of your JUnitEE tests with your build process:

  • the JUnitEEWar task creates the .war file you need to run your tests inside a servlet container (similar to the War task included in the standard Ant distribution)
  • the JUnitEE task allows you to start execution of your server-side tests from within your ant build script (similar to the JUnit task included in the standard Ant distribution)

To use these tasks you have to declare them as external tasks in your build script:

<taskdef name="junitee" classname="org.junitee.anttask.JUnitEETask">
  <classpath>
    <pathelement location="lib/junitee-anttask.jar"/>
  </classpath>
</taskdef>

<taskdef name="juniteewar" classname="org.junitee.anttask.JUnitEEWarTask">
  <classpath>
    <pathelement location="lib/junitee-anttask.jar"/>
  </classpath>
</taskdef>


The JUnitEETask supports the following attributes:

JUnitEETask attributes
AttributeDescriptionRequired
urlURL of the JUnitEE Test ServletYES
haltonfailureStop the build if a failure occursNo
haltonerrorStop the build if an error or a failure occursNo
printsummaryPrint a summary of all executed testsNo
filtertraceFilter the stack trace in case of an error/failure. This removes JUnit methods from the stack trace.No; default is true
threadedRun tests in threaded mode to avoid HTTP timeoutsNo; default is true

The results of the tests can be printed in different formats. To specify the format of the output <junitee> may contain nested <formatter> elements. The output of a formatter will always be sent to a file, unless you set the usefile attribute to false. The name of the file is determined by the name of the test and can be set by the outfile attribute of <test>.

There are two predefined formatters - one prints the test results in XML format, the other emits plain text. The formatter named plain will only print detailed information for testcases that failed, while plain gives a little statistics for all test cases. Custom formatters that need to implement org.junitee.anttask.JUnitEEResultFormatter can be specified using the classname attribute.

The formatter element supports the following attributes:

Formatter attributes
AttributeDescriptionRequired
typeUse a predefined formatter (either xml, plain, or brief).YES, if classname is not set.
classnameName of a custom formatter class.YES, if type is not set.
extensionExtension to append to the output filename.YES, if classname has been specified.
usefileBoolean that determines whether output should be sent to a file.No; default is true

The task requires a set of nested <test> elements to define which tests to run. Each <test> may contain nested <formatter> elements which are added to the list of formatters specified by <junitee>. The following attributes are supported by <test>:

Test attributes
AttributeDescriptionRequired
nameName of the test class to be executedIf runall is not set
runallExecute all testsIf name is not set
resourceComma-separated list of all resources containing test classes If runall is set and the test servlet is not configured for Smart Test Mode. This attribute will overwrite the configuration of the servlet.
failurepropertySpecify a property that will be set in case a this test failesNo
errorpropertySpecify a property that will be set in case an error caused this test to failNo
haltonfailureStop the build if this test failsNo
haltonerrorStop the build if an error or a failure occurs while running this testNo
filtertraceFilter the stack trace in case of an error/failure. This overwrites the setting of the task.No
outfileBase name of the test result. The full filename is determined by this attribute, the name of the test and the extension of the formatter. No; default is TEST-, or TEST-ALL- if runall is set for this test.
todirDirectory to write the reports to.No; default is the current directory.
ifOnly run test if the named property is set.No
unlessOnly run test if the named property is not set.No

The following example will run the test suite org.infohazard.test.EinsteinTest and halt the build if a failure occurs.

<target name="run-tests">
  <junitee url="http://localhost:8080/exampletest/TestServlet">
    <test name="org.infohazard.test.EinsteinTest" haltonfailure="true" />
  </junitee>
</target>

The next example will run all tests available in WEB-INF/lib/mytests.jar.

<target name="run-tests">
  <junitee url="http://localhost:8080/exampletest/TestServlet">
    <test runall="true" resource="WEB-INF/lib/mytests.jar" />
  </junitee>
</target>


The JUnitEEWarTask is an extension of the War task available in the standard Ant distribution. In addition to the attributes of the War task the JUnitEEWarTask supports the following attributes:

JUnitEEWarTask attributes
AttributeDescriptionRequired
testjarnameThis parameter defines the name of the .jar file which will contain all the test classes defined in the nested <classes> element. This file will then be placed in the WEB-INF/lib directory of the war file. If this parameter is not set, the test classes will be stored in the WEB-INF/classes directory of the war file.No
servletclassSpecify the servlet class which will be used to generate the web.xml.No
webxmlThe deployment descriptor to use (WEB-INF/web.xml). This attribute workes like in the War task, except that if not set, web.xml will be generated.No
htmlRefreshDelaySpecify the interval the result page will be reloaded in threaded mode.No; default is 2 seconds.

In addition to the War task, the JUnitEEWarTask supports nested <testcase> elements which specify a FileSet. All files included in this fileset are the Junit test cases which will be executed if all=true is used when calling the JUnitEE servlet.

To use EJBs from your test cases it is possible to declare EJB references which should be included in the generated deployment descriptor of the war file using nested <ejbRef> elements. An <ejbRef> element supports the following attributes:

ejbRef attributes
AttributeDescriptionRequired
ejbRefNameset <ejb-ref-name> valueYes
ejbRefTypeset <ejb-ref-type> valueYes
homeset <home> valueYes
remoteset <remote> valueYes
ejbLinkset <ejbLink> valueNo

To use local EJBs from your test cases it is possible to declare EJB local references which should be included in the generated deployment descriptor of the war file using nested <ejbLocalRef> elements. An <ejbLocalRef> element supports the following attributes:

ejbLocalRef attributes
AttributeDescriptionRequired
ejbRefNameset <ejb-ref-name> valueYes
ejbRefTypeset <ejb-ref-type> valueYes
localhomeset <local-home> valueYes
localset <local> valueYes
ejbLinkset <ejbLink> valueNo

Finally the JUnitEEWarTask supports nested <resourceRef> elements to delcare resource reference entries to be included in the generated deployment descriptor of the war file. <resourceRef> elements provide the following attributes:

resourceRef attributes
AttributeDescriptionRequired
resRefNameset <res-ref-name> valueYes
resTypeset <res-type> valueYes
resAuthset <res-auth> valueYes

Consider for the following example that you have a project with the following characteristics:

  • the classes to test are located in the directory build/classes
  • the test classes are compiled to the directory build/test
  • the test classe names have Test as their prefix
  • the .jar files you need are stored in the lib directory

In this case the following Ant target will build a file called myTest.war which contains

  • junit.jar and junitee.jar under WEB-INF/lib
  • the classes to test and all test cases under WEB-INF/classes
  • a file named WEB-INF/testCase.txt which contains a list of all test case names
  • a file named index.html which allows you to run tests manually using your browser
  • the deployment descriptor WEB-INF/web.xml which makes myTest.war a deployable web archive

<juniteewar destFile="myTest.war">
  <lib dir="lib" includes="junitee.jar"/>
  <lib dir="lib" includes="junit.jar"/>
  <classes dir="build/classes">
    <include name="**/*.class"/>
  </classes>
  <classes dir="build/test">
    <include name="**/*.class"/>
  </classes>
  <testcases dir="build/test">
    <include name="**/Test*.class"/>
  </testcases>
</juniteewar>


 
Jakarta Cactus support

All JUnitEE servlets set the system property cactus.contextURL to the context of the web application the JUnitEE servlet is part of. Therefore you don't have to specify this property another way (e.g. by providing a client.properties file as part of your web application) when using JUnitEE to run Cactus tests.

 
SecurityManager issues

JUnitEE takes some actions which are under control of the Java security manager:

  • set the system property cactus.contextURL
  • read the file junit.properties from user home
In case the security manager is enabled in your J2EE environment (which for example is the case for the J2EE reference implementation provided by Sun) you have to grant permission for these actions in your security policy:

grant {
    permission java.util.PropertyPermission "cactus.contextURL", "read,write";
    // replace <USERHOME> with your home directory
    permission java.io.FilePermission "<USERHOME>\junit.properties", "read";
};

 
 
This project is hosted by  SourceForge Logo