Junit provides a series of junit 4 runners in the core package, for instance: org.junit.runner, JUnitCore, JUnit38ClassRunner, JUnit4ClassRunner, Parameterized and etc. these Junit runners are used to centralize and execute your test cases, JUnit4 is the default one If no customized runner annotated, our needs is to implement a customized Junit runner, in this how-to, we guide how do I write a custom Junit runner to run test cases.

1. Implement your Junit runner.

To implement a customized runner, you need to extend junit 4 abstract class Runner. and overwrite methods getDescription and run(RunNotifier runNotifier), the parameter RunNotifier is a instance of class which controls a set of test methods.

import org.junit.Ignore;
import org.junit.Test;
import org.junit.internal.runners.TestClass;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * User: asjava.com
 * Date: Sep 18, 2010
 * Time: 1:30:43 AM
 */
public class CustomTestRunner extends Runner {
    private List fTestMethods = new ArrayList();
    private final TestClass fTestClass;

    public CustomTestRunner(java.lang.Class aClass) {
        fTestClass = new TestClass(aClass);

        Method[] classMethods = aClass.getDeclaredMethods();
        for (int i = 0; i < classMethods.length; i++) {
            Method classMethod = classMethods[i];
            Class retClass = classMethod.getReturnType();
            int length = classMethod.getParameterTypes().length;
            int modifiers = classMethod.getModifiers();
            if (retClass == null || length != 0 || Modifier.isStatic(modifiers)
                    || !Modifier.isPublic(modifiers) || Modifier.isInterface(modifiers)
                    || Modifier.isAbstract(modifiers)) {
                continue;
            }
            String methodName = classMethod.getName();
            if (methodName.toUpperCase().startsWith("TEST")
                    || classMethod.getAnnotation(Test.class) != null) {
                fTestMethods.add(classMethod);
            }
            if (classMethod.getAnnotation(Ignore.class) != null) {
                fTestMethods.remove(classMethod);
            }
        }
    }

    @Override
    public Description getDescription() {
        Description spec = Description.createSuiteDescription(this.fTestClass.getName(),
                this.fTestClass.getJavaClass().getAnnotations());
        return spec;
    }

    @Override
    public void run(RunNotifier runNotifier) {
        for (int i = 0; i < fTestMethods.size(); i++) {
            Method method = fTestMethods.get(i);
            Description spec = Description.createTestDescription(method.getClass(), method.getName());
            runNotifier.fireTestStarted(spec);
        }
    }
}

2. Write test case and annotate it to use the customized Junit runner.

The annotation RunWith allows specifying a customized runner for these test cases, just simply annotate @RunWith in class definition.

import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(value=CustomTestRunner.class)
public class JunitExample extends Assert {

    @Test
    public  void testMethod() {
        int a = 10;
        assertEquals(a, 10);
    }
}

use a command line tool to run these tests as below example, the first one is a Junit runner, the second one is the test class.

java CustomTestRunner JunitExample