Jiffle Blog

RSS

Extending JUnit functionality with additional annotation support

I’m currently developing on the Play Framework (1.x), and some of its biggest advantages are its built-in testing framework and automatic support for transactions. One of the downsides of this, however, is that for some tests to work correctly the setup needs to be run inside a separate transaction. Thus you cannot just add extra fixture data at the beginning of the actual test and have it run in the same transaction.

Hence I needed the ability to optionally load extra data within have the setup method, depending on the test being run. JUnit 4.7 added a TestName class which allowed a test (but not @Before methods) to find the name of the test being run, and that was generalised in 4.9 to have a TestWatcher base class, which now ran before the @Before methods.

But having setup perform conditional work depending on the name of the test isn’t the best solution, as the setup could be broken by refactoring the test names.

What I really wanted was to be able to add an annotation to denote the tests which require special work - preferably with the ability to define exactly which special work was required. Fortunately, the TestWatcher provides an easily extensible base for such a class and thus it is the work of five minutes to implement such annotation-driven behaviour:

Firstly, create your custom annotation class, thus:

@Retention( value = RetentionPolicy.RUNTIME)
@Target( value = { ElementType.METHOD})
public @interface Marker {
    public String value() default "";
}

Then create your own TestWatcher, which gets filled in by JUnit with any Markers annotated against the test method being executed:

public class TestAnnotated extends TestWatcher {
    private Marker marker;

    @Override
    protected void starting( Description description) {
        marker = description.getAnnotation( Marker.class);
    }

    public Marker getMarker() {
        return marker;
    }

    /** @return the name field attached to the marker. 
                Null if no annotation, "" if no value field. */
    public String getMarkerValue() {
        if( marker == null) {
            return null;
        }
        return marker.value();
    }
}

The value parameter in the annotation can be used to specify extra information about the test.

And that’s it. Here is how you use it in your tests:

public class SomeTest {
    private static final String LOAD_SPECIAL_DATA 
                 = "Load Special Data";
    @Rule
    public TestAnnotated annotated = new TestAnnotated();

    @Before
    public void setup() {
        // load basic fixtures

        if( null != annotated.getMarker()) {
            // do extra setup for all marked tests
        }

        if( LOAD_SPECIAL_DATA.equals( annotated.getMarkerValue())) {
            // do special setup just for those tests
        }
    }

    @Test
    public void ordinaryTest() {
        // just standard fixtures for this test
    }

    @Test
    @Marker
    public void testRequiringExtraData() {
        // extra data will be loaded for this test
    }

    @Test
    @Marker( LOAD_SPECIAL_DATA)
    public void testRequiringSpecialData() {
        // both extra data and special data 
        // will be loaded for this test
    }
}

Q: "How much does an app cost?" A: "About as much as a car."

darwinapps:

Credit: Alex Lakas, Creative Director @ DarwinApps

How much does an app cost? It costs about as much as a car does, it just depends on what you want.

“I just want an app and I want it to work” = 1994 Honda Civic = $1-5K.
You just want a simple app. Nothing fancy, and you don’t really care who works on it….

Very handy guide. Good tips on how those commissioning apps can cut costs too.

Converting a Maven Multi-module Build to SBT

Great worked example, taking a multi-module build and converting it to SBT.

My main take-way from that is that a three-module build in Maven was 174 lines. In SBT the same build is 71 lines.

Unfuddle Markdown Syntax Reference

Unfuddle uses a really next variant of the Markdown markup syntax. However the documentation of their extensions over the standard syntax is somewhat hard to find, so this page is an ongoing attempt to gather that information onto one page.

Linking one Notebook page to another page in the same Notebook

Use double square brackets around the name of the page that you’re linking to:

See [[Name of other page]] for more information

Linking one Notebook page to a page in another Notebook

Use double square brackets around the name of the other notebook, a colon, and the name of the target page:

See [[Other notebook:Other page]] for more information

Including an attached image attachment in a Notebook page

Use the filename of the uploaded image in double curly braces in the url part of the image syntax:

![Image Title]({{name-of-file-attachment.png}})

This is a work in progress: I’ll add other tricks as I find them

SuperTool For Diagnosing Email (MX) Problems

Fixing Homebrew OS X Error: You have no /usr/bin/cc

I got this error a while ago. The solution is to go into XCode application, select Preferences menu and chose /Downloads/Components tabs.

Then click the Install button for Command Line Tools.

Fixing SBT PermGen space errors

To summarise the fix: edit or create the file ~/.sbtconfig and add the line:

SBT_OPTS="-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"

CSS Form Layouts without using Floats

Nice looking approach, but if you need to support IE 6 & 7 you’ll still need another stylesheet using floats or some other approach.

Getting Started With SBT and Command Quick Reference

Beginning SBT - A Simple Java-Only Project with Eclipse

As someone learning Scala, I wanted to learn the basics of doing builds with SBT, and when I was asked to do a small Java project it seemed a good opportunity to do so. However, as I quickly found, SBT is naturally focussed on Scala and so needs a few extra build settings to get a java project going. This is what I found:

A Simple SBT Java Project File

This is what you need as the basic java project file:

organization := "org.somename"

name := "Some Project Name"

version := "1.0-SNAPSHOT"

libraryDependencies ++= Seq( 
    "orgname1" % "artifact1" % "version1",
    "orgname2" % "artifact2" % "version2"
    )

Which is a very nice, simple build file, but you’ll quickly find that it there are a few shortcomings, like there’s no Eclipse project integration, java unit tests aren’t invoked by SBT’s test command, and the run command won’t run anything. So here’s what you need to add to get a proper java project running:

Disabling Unnecessary Scala Features

Firstly, to make the project build cleaner (which helps when we come to Eclipse integration, next), we disable use of the Scala library and make sure that the Scala version isn’t added to project artefacts and output paths:

autoScalaLibrary := false

crossPaths := false

Eclipse Integration

Adding the SbtEclipse plugin

The SbtEclipse plugin allows you to autogenerate an Eclipse project and classpath from the SBT build file. It can be installed in either the project or on your system-wide SBT settings. In this case we’ll install it system-wide.

Find or create the file ~/.sbt/plugins/plugins.sbt. Add the following line to it and save it (you may need to update the version number in line with the latest version):

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")

The plugin will auto install next time you run SBT. To create or recreate the eclipse project run sbt eclipse, but but default it will add a Scala project nature, so to tell it to use a Java project nature we need to add:

EclipseKeys.projectFlavor := EclipseProjectFlavor.Java

Setting the Main Class

Next we need to tell SBT what class to use as the main class when executing sbt run. To do this add the following line:

mainClass in (Compile, run) := Some( "somepackage.MainClassName")

Enabling JUnit Testing

SBT supports several Scala unit testing frameworks out of the box, but needs an adaptor library to invoke our JUnit tests when running sbt test, so the following library dependencies are needed:

libraryDependencies ++= Seq( 
    "junit" % "junit" % "4.10",
    "com.novocode" % "junit-interface" % "0.10-M1" % "test"
    )

Wrap Up: A Template Java Project Build File

This is what it looks like when you put it all together:

organization := "org.somename"

name := "Some Project Name"

version := "1.0-SNAPSHOT"

autoScalaLibrary := false

crossPaths := false

EclipseKeys.projectFlavor := EclipseProjectFlavor.Java

mainClass in (Compile, run) := Some( "somepackage.MainClassName")

libraryDependencies ++= Seq( 
    "junit" % "junit" % "4.10",
    "com.novocode" % "junit-interface" % "0.10-M1" % "test"
    )

Postscipt: Add The Commands To Use It

Note that all of these commands can be invoked directly from the SBT interactive console.

sbt eclipse          // creates the eclipse project
sbt update           // resolves library dependencies
sbt compile          // compiles code (having optionally done update first)
sbt run              // runs main method on main class
sbt test             // runs the test suites