1. Overview

In this tutorial, we’ll investigate how we can monitor unit tests using JUnit test rules. JUnit provides TestWatcher class as a template to cover this kind of needs. In the end, we’ll have a basic monitoring rule using TestWatcher class.

2. Quick Look at TestWatcher

Let’s first look at TestWatcher class.

In essence, TestWatcher defines several hooks for capturing execution phases of a test. We can think of hooks as methods meant to be overridden by subclasses. As a result, a subclass can put its own logic to the existing process.

public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                List<Throwable> errors = new ArrayList<Throwable>();

                startingQuietly(description, errors);
                try {
                    base.evaluate();
                    succeededQuietly(description, errors);
                } catch (@SuppressWarnings("deprecation") org.junit.internal.AssumptionViolatedException  e) {
                    errors.add(e);
                    skippedQuietly(e, description, errors);
                } catch (Throwable e) {
                    errors.add(e);
                    failedQuietly(e, description, errors);
                } finally {
                    finishedQuietly(description, errors);
                }

                MultipleFailureException.assertEmpty(errors);
            }
        };
    }

Here, the apply() method shows general flow and hooks. As we can see, we have starting, succeeded, skipped, failed and finished hooks.

3. Implementing Test Rule using TestWatcher

MonitorRule is a TestRule extending TestWatcher. Moreover, it overrides the previously mentioned methods. Although it simply prints some messages, it shows that we can monitor the execution of our tests.

public class MonitorRule extends TestWatcher {

    /**
     * Invoked when a test succeeds
     */
    protected void succeeded(Description description) {
        System.out.printf("%s succeeded%n", description.getMethodName());
    }

    /**
     * Invoked when a test fails
     */
    protected void failed(Throwable e, Description description) {
        System.out.printf("%s failed with %s%n", description.getMethodName(), e);
    }

    /**
     * Invoked when a test is skipped due to a failed assumption.
     */
    @SuppressWarnings("deprecation")
    protected void skipped(AssumptionViolatedException e, Description description) {
        // For backwards compatibility with JUnit 4.11 and earlier, call the legacy version
        org.junit.internal.AssumptionViolatedException asInternalException = e;
        System.out.printf("%s skipped%n", description.getMethodName());
    }

    /**
     * Invoked when a test is about to start
     */
    protected void starting(Description description) {
        System.out.printf("%s is starting%n", description.getMethodName());
    }

    /**
     * Invoked when a test method finishes (whether passing or failing)
     */
    protected void finished(Description description) {
        System.out.printf("%s finished%n", description.getMethodName());
    }
}

 

4. Summary

In this tutorial, we’ve seen how to implement a custom test rule.

As always, the source code for all samples is available on Github.

Leave a Reply

Close Menu