Course Data project

A JISC funded project aimed at improving course-related data at Sussex University

A word on our unit testing

Jan

8

For our unit tests we opted to stick to the standard framework for unit testing Java applications, JUnit. As ever, it is very easy to unit test methods using JUnit, but there are some features of JUnit 4 that make it even easier.

Once again, the use of annotations has simplified the process of creating a test. Simply adding the @Test annotation, turns a normal method into a unit test. If any exceptions are found or assertions not met, the test fails otherwise the test passes. Here is a quick example:


/**
* Test of retrieveCatalog method, of class CatalogueLoaderBean.
*/
@Test
public void testRetrieveCatalog() throws Exception {
System.out.println("retrieveCatalog");
CatalogueLoaderBeanRemote result = (CatalogueLoaderBeanRemote)getInitialContext().lookup("uk.ac.susx.xcricap.session.CatalogueLoaderBeanRemote");
String catalogType = "MAIN";
Catalog expResult = result.retrieveCatalog(catalogType);
assertNotNull(expResult.getProvider().get(0));

}

So that’s great if we want to test just one class, but what if we want to test a whole suite of classes? JUnit gives us the ability to create a test suite and to name which test classes we want to make up that suite. Once again, annotations make this an easy thing to set up. Here’s an example of a test suite we used on the project:


@RunWith(Suite.class)
@Suite.SuiteClasses({uk.ac.susx.xcricap.test.XCRI_CAPSessionRemoteTest.class,
uk.ac.susx.xcricap.test.SchemaLoaderBeanTest.class,
uk.ac.susx.xcricap.test.CatalogueLoaderBeanTest.class
})
public class XCRI_CAPTestSuite {

When we run the test suite through my IDE (Netbeans), the following type of output is given, it is very easy to see if something passed or failed.

Testing output from Netbeans

For the project, we really wanted a way to automate the output of our tests in a more friendly way. All of our projects are built and deployed using Apache Ant. Ant uses a script to create ‘targets’ that are run depending on what we are trying to do (e.g. run, compile, deploy, debug, test). By including a report directory, Ant can work with JUnit to produce an HTML report. Here is an example of the test target:


  <target name="-init-macrodef-junit">
        <macrodef name="junit" uri="http://www.netbeans.org/ns/web-project/2">
            <attribute default="${includes}" name="includes"/>
            <attribute default="${excludes}" name="excludes"/>
            <attribute default="**" name="testincludes"/>
            <sequential>
                <junit dir="${basedir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true" tempdir="${java.io.tmpdir}">
                    <batchtest todir="${build.test.results.dir}">
                        <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
                            <filename name="@{testincludes}"/>
                        </fileset>
                    </batchtest>
                    <classpath>
                        <path path="${run.test.classpath}:${j2ee.platform.classpath}:${j2ee.platform.embeddableejb.classpath}"/>
                    </classpath>
                    <syspropertyset>
                        <propertyref prefix="test-sys-prop."/>
                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
                    </syspropertyset>
                    <formatter type="brief" usefile="false"/>
                    <formatter usefile="true" type="xml"/>
                    <jvmarg line="${endorsed.classpath.cmd.line.arg}"/>
                    <jvmarg value="-ea"/>
                    <jvmarg line="${runmain.jvmargs}"/>
                </junit>
                <junitreport todir="${build.test.results.dir}">
                <fileset dir="${build.test.results.dir}">
                    <include name="*.xml"/>
                    <exclude name="TEST-uk.ac.susx.xcricap.test.XCRI_CAPTestSuite.xml"/>
                </fileset>
                <report todir="${build.test.results.dir}/html"/>
            </junitreport> 
            </sequential>
        </macrodef>
    </target>

Running the target produces a nicely formatted, HTML report. Here is a link to the output from one of the test runs.

Unit testing is a very important process for any software project. It gives the developer the confidence that a change made does not impact on existing functionality. JUnit makes it very easy to create unit tests. By running our build process through Ant, the entire build process and testing is decoupled from the developer’s PC meaning it can be changed, retested and redeployed independently of whatever development tools a developer may have been using.

Leave a Reply