Test-driven Configuration Management with Maven

As an agile software developer practicing test-driven development (TDD) it is normal to write the tests first. Unfortunately, switching roles and wearing the "configuration manager hat" it is sometimes hard to adhere to the same rules of TDD because there are tools missing which provides test infrastructure for build management. One solution might be to use the build server for such tasks.

This is an example of Test-driven dependency mangement with Maven:

We can use the versions-maven-plugin to list all available updates of plugins used in the pom.xml.

For example Maven might produce this information on an updated version of the release plugin:

mvn versions:display-property-updates
...
[08:01:04][de.timomeinen.maven:maven-parent] 
[INFO] The following version property updates are available:
[08:01:04][de.timomeinen.maven:maven-parent] 
[INFO] ${version.plugin.release}......... 2.4.1 -> 2.4.2

If we trigger a nightly build on the CI server and let the build fail on an update message, we have a nice test if there are any updates available for our Maven project.

This example uses TeamCity, but you can surely adopt it to other CI server as well.

Configure a new Maven Build Step:
teamcity-setup

And define a Build Failure Condition (Step 4):
teamcity-setup-build-failure-condition

Fail build if build log contains exact text "The following version property updates are available" with the Failure message "Updates available".

The result looks like this:
teamcity-01

This will let the build fail on a dependency update, gives you a nice message and TeamCity even produces a link to the part of the build log, where you can see which dependencies you can update.

That's a nice example of what I call "Test-driven System Administration (TDSA)".

Test for private constructor to get full code coverage

Imagine we have a simple helper class which only consists of public static methods.

public class Helper {
  public static void doSomething() {}
}

And the test:

import org.junit.Test;

public class HelperTest {
 @Test
 public void testDoSomething() {
   Helper.doSomething();
 }
}

Our code coverage tool won't show us a 100% coverage, because the (default) constructor is not invoked. For example Intellij IDEA only shows 50%.

One solution would be to simply invoke the default constructor with new Helper.doSomething(). But we don't want to have objects of this class and therefore override the default constructor with a private one:

public class Helper {
    private Helper() {}
    public static void doSomething() {}
}

The problem is, that now even the test cannot instantiate the class. And as we are testdriven, the question is: Should the decision to create a class without any objects be motivated by tests, too? In my opinion yes. I don't want some other programmer to remove the private constructor. At least a test shall break.

We reach this by the following test:

import static org.junit.Assert.assertTrue;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import org.junit.Test;

public class HelperTest {

    @Test
    public void testDoSomething() throws Exception {
        Helper.doSomething();
    }

    @Test
    public void testPrivateConstructor() throws Exception {
        Constructor constructor = Helper.class.getDeclaredConstructor();
        assertTrue("Constructor is not private", Modifier.isPrivate(constructor.getModifiers()));

        constructor.setAccessible(true);
        constructor.newInstance();
    }
}

Now we have a guard to the design decision of a private constructor and our tests are back on 100% coverage again.