Maven tips and Tricks: running a subset of tests

So, you wanna run only some of your tests because they take too
long? check this as a sample to avoid running dao tests (provided that
you use some naming convention, as calling them *Dao*Test):

    <!-- test configurations -->
    <goal name="test:notdao">
        <j:set var="testmatchpattern" value="**/*Test.*"/>
        <j:set var="testnotmatchpattern" value="**/Abstract*,**/*Dao*Test.*"/>
        <attainGoal name="test:match"/>
    </goal>

The only drawback is that you need the latest maven test plugin (1.7). You can just add this dependency to your project.xml.

        <dependency>
            <groupId>maven</groupId>
            <artifactId>maven-test-plugin</artifactId>
            <version>1.7</version>
            <type>plugin</type>
        </dependency>

Managing your clustered application with jManage

One of the drawbacks of JMX is the lack of cluster support, you have
to invoke the operation in each one of the servers. The solution? use a
JMX client that does that for you, as jManage.
You setup the servers as in any other administration console and then
you can group them in clusters, allowing you to see the value of the
properties in each one of the servers in the cluster and invoke operations
in all of them getting the results of each server in a single page.

Using jManage with JBoss 4

Download jManage version 0.5.3.

Go to jmanage-0.5.3/modules/jboss and copy there the following jars from jboss installation.

  • jboss-4.0.2/client/jbossall-client.jar
  • jboss-4.0.2/lib/jboss-jmx.jar

Start JBoss servers with the java option  -Djava.rmi.server.hostname=hostname (you can set JAVA_OPTS environment variable)

Run jManage with jmanage-0.5.3/bin/startup.sh, you’ll be asked for a password (123456 by default). Then you can login at http://localhost:9090 with username/password admin/123456

Hibernate 3.0.5 statistics + TreeCache bugs

When working at a client site we decided to enable Hibernate
statistics, so we can access all this information about cache
hits/misses, transactions, entities,… and all kind of cool stuff
through a JMX interface at runtime, allowing runtime configuration
changes and monitoring.

But seems that not many people is using this feature, because we
got the frustrating NullPointerException. After debugging a bit through
the Hibernate sources (if you have ever tried you know that it’s a PITA) I found the errors, same exception in two places,
and told JBoss support (the client was paying for it). Anyway I fixed them
locally while they fixed them in CVS, see the cvs diff or the JIRA issue. This bugs are present in hibernate 3.0.5 when using TreeCache.

Now we can get a lot of useful information at runtime, through a JMX console, I really like jManage,
mostly due to it’s cluster support, but you’ll need some tricks to make
it run with JBoss 4, that I’ll post in a separate entry.

Guestmap

I’ve created a guestmap so you can left a mark on the city your reading this weblog from.

dbUnit, useful more than just for unit tests

I really like dbUnit for unit tests, but I like it more for other
tasks, as exporting data from the database in xml or Excel formats with
a few lines of code and without bothering about writing xml tags or
interacting with POI to write Excel cells.

For
instance the next code can be used to export the result of a query into
an Excel file.

public class Report {

    private DataSource dataSource;

    public void exportData() throws Exception {

        IDatabaseConnection connection = new DatabaseConnection(dataSource
                .getConnection());

        try {

            // partial database export
            QueryDataSet partialDataSet = new QueryDataSet(connection);

            String query =
                    "SELECT a, b FROM t WHERE a = 'whatever'");

            partialDataSet.addTable("Report", query);
            XlsDataSet.write(partialDataSet, new FileOutputStream(
                    "report.xls"));

        } finally {
            connection.close();
        }

    }

Maven tips and Tricks: Avoid running tests twice

Sometimes you may find that your tests are run twice, once to make
the report for the site (thus not breaking the build if they fail) and
second time to create a jar, war or any other artifact, and probably in
this step you want the build to break if tests don’t succeed. This is
very common in a continuous integration scenario where the machine with
CruiseControl or any other CI tool deploys the site and generated
artifacts.

My suggestion is to create a goal in your maven.xml like this

    <goal name="continuousintegration">
        <attainGoal name="clean"/>
        <attainGoal name="site:deploy"/>
        <!-- avoid running tests again -->
        <j:if test="${maven.test.failure}">
          <fail message="There were test failures."/>
        </j:if>
        <j:set var="maven.test.skip" value="true"/>
        <attainGoal name="jar:deploy"/>
        <j:set var="maven.test.skip" value="false"/>
    </goal>

The trick is checking the maven.test.failure property after creating
the site, if it’s true the build has to fail and if it’s false you can
skip tests in next steps.

Maven tips and Tricks: Perforce

Lately I had the bad time to use the Perforce SCM system. I created a maven goal to sync (=cvs update) my sources from the SCM.

You need:

  • jakarta oro as a dependency in your project.xml and loaded by the root classloader.
        <!--
         | Oro is needed by the Perforce tasks and needs to be loaded
         | by the root classloader
         +-->
        <dependency>
            <groupId>oro</groupId>
            <artifactId>oro</artifactId>
            <version>2.0.8</version>
            <properties>
                <classloader>root</classloader>
            </properties>
        </dependency>
  • The actual goal in maven.xml
        <!-- perforce -->
        <goal name="p4sync">
            <p4sync view="//depot/whatever/..." />
        </goal>

You can check all the perforce ant tasks you can use besides p4sync.

Cobertura, an open source alternative to Clover

Cobertura is a free Java tool that calculates the percentage of code
accessed by tests. It can be used to identify which parts of your
Java program are lacking test coverage. It is based on jcoverage, but more actively developed.

I will talk about the maven cobertura plugin,
after releasing the first two versions (7/11 and 7/21) you can have
cool reports about test coverage and the ability to see all the classes
that don’t meet your minimum coverage criteria, both at line and branch
level.

The first report about code coverage is pretty similar to the one provided by Clover, but the second one
makes the difference, not provided by clover and in fact neither by
cobertura ant tasks, just the maven plugin. Another interested feature
to be used for instance in conjuction with a continuos integration tool
as CruiseControl is the option to make the build fail if any of the
classes test coverage fails below a threshold you can set. AFAIK clover
only allows to fail the test if the overall code coverage doesn’t meet
the requirements, not class by class, which is very convenient.

To use it in your maven projects you can add the dependency to the plugin
        <dependency>
            <groupId>maven-plugins</groupId>
            <artifactId>maven-cobertura-plugin</artifactId>
            <version>1.1</version>
            <type>plugin</type>
        </dependency>
and the report
        <report>maven-cobertura-plugin</report>

I hope you find it useful.

Inheriting annotations from implemented interfaces

In relation to Rick Hightower entry on annotations and inheritance I also checked if annotations on implemented interfaces are accesible
from the class implementing them. The answer is NO, neither using the
@Inherited annotation on the annotation class. The only way is getting
the implemented interfaces and iterate over them to see if they have
annotations.

public class AnnotationTest extends TestCase {

    @Retention(RetentionPolicy.RUNTIME) // This makes the annotation available at runtime
    @Inherited
    public static @interface Developer {
        String name();

        String email() default “[email protected]”;

        int rank() default 1;
    }

    // Using the annotation to decorate a class and a method
    @Developer(name = “RickHightower”)
    interface MyInterface {
        @Developer(name = “ScottFauerbach”, email = “[email protected]”)
        void myMethod();
    }

    class MyClassSub implements MyInterface {
        
        public void myMethod() {
            // …
        }
    }

    // Testing the annotation
    public void testAnnotation() throws Exception {
        assertFalse (MyClassSub.class.isAnnotationPresent(Developer.class));
        Method method2 = MyClassSub.class.getMethod(“myMethod”, (Class[]) null);
        assertFalse (method2.isAnnotationPresent(Developer.class));
        
        Class[] interfaces = MyClassSub.class.getInterfaces();
        boolean annotationPresent = false;
        for (Class iClass : interfaces) {
            if (iClass.isAnnotationPresent(Developer.class)) {
                   
annotationPresent = true;
                    break;
            }
        }
        assertTrue(annotationPresent);
    }
}