package org.junit.runner.notification;

import static java.util.Arrays.asList;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.junit.runner.Description;
import org.junit.runner.Result;

If you write custom runners, you may need to notify JUnit of your progress running tests. Do this by invoking the RunNotifier passed to your implementation of Runner.run(RunNotifier). Future evolution of this class is likely to move fireTestRunStarted(Description) and fireTestRunFinished(Result) to a separate class since they should only be called once per run.
Since:4.0
/** * If you write custom runners, you may need to notify JUnit of your progress running tests. * Do this by invoking the <code>RunNotifier</code> passed to your implementation of * {@link org.junit.runner.Runner#run(RunNotifier)}. Future evolution of this class is likely to * move {@link #fireTestRunStarted(Description)} and {@link #fireTestRunFinished(Result)} * to a separate class since they should only be called once per run. * * @since 4.0 */
public class RunNotifier { private final List<RunListener> listeners = new CopyOnWriteArrayList<RunListener>(); private volatile boolean pleaseStop = false;
Internal use only
/** * Internal use only */
public void addListener(RunListener listener) { if (listener == null) { throw new NullPointerException("Cannot add a null listener"); } listeners.add(wrapIfNotThreadSafe(listener)); }
Internal use only
/** * Internal use only */
public void removeListener(RunListener listener) { if (listener == null) { throw new NullPointerException("Cannot remove a null listener"); } listeners.remove(wrapIfNotThreadSafe(listener)); }
Wraps the given listener with SynchronizedRunListener if it is not annotated with ThreadSafe.
/** * Wraps the given listener with {@link SynchronizedRunListener} if * it is not annotated with {@link RunListener.ThreadSafe}. */
RunListener wrapIfNotThreadSafe(RunListener listener) { return listener.getClass().isAnnotationPresent(RunListener.ThreadSafe.class) ? listener : new SynchronizedRunListener(listener, this); } private abstract class SafeNotifier { private final List<RunListener> currentListeners; SafeNotifier() { this(listeners); } SafeNotifier(List<RunListener> currentListeners) { this.currentListeners = currentListeners; } void run() { int capacity = currentListeners.size(); ArrayList<RunListener> safeListeners = new ArrayList<RunListener>(capacity); ArrayList<Failure> failures = new ArrayList<Failure>(capacity); for (RunListener listener : currentListeners) { try { notifyListener(listener); safeListeners.add(listener); } catch (Exception e) { failures.add(new Failure(Description.TEST_MECHANISM, e)); } } fireTestFailures(safeListeners, failures); } abstract protected void notifyListener(RunListener each) throws Exception; }
Do not invoke.
/** * Do not invoke. */
public void fireTestRunStarted(final Description description) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testRunStarted(description); } }.run(); }
Do not invoke.
/** * Do not invoke. */
public void fireTestRunFinished(final Result result) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testRunFinished(result); } }.run(); }
Invoke to tell listeners that an atomic test is about to start.
Params:
  • description – the description of the atomic test (generally a class and method name)
Throws:
/** * Invoke to tell listeners that an atomic test is about to start. * * @param description the description of the atomic test (generally a class and method name) * @throws StoppedByUserException thrown if a user has requested that the test run stop */
public void fireTestStarted(final Description description) throws StoppedByUserException { if (pleaseStop) { throw new StoppedByUserException(); } new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testStarted(description); } }.run(); }
Invoke to tell listeners that an atomic test failed.
Params:
  • failure – the description of the test that failed and the exception thrown
/** * Invoke to tell listeners that an atomic test failed. * * @param failure the description of the test that failed and the exception thrown */
public void fireTestFailure(Failure failure) { fireTestFailures(listeners, asList(failure)); } private void fireTestFailures(List<RunListener> listeners, final List<Failure> failures) { if (!failures.isEmpty()) { new SafeNotifier(listeners) { @Override protected void notifyListener(RunListener listener) throws Exception { for (Failure each : failures) { listener.testFailure(each); } } }.run(); } }
Invoke to tell listeners that an atomic test flagged that it assumed something false.
Params:
/** * Invoke to tell listeners that an atomic test flagged that it assumed * something false. * * @param failure the description of the test that failed and the * {@link org.junit.AssumptionViolatedException} thrown */
public void fireTestAssumptionFailed(final Failure failure) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testAssumptionFailure(failure); } }.run(); }
Invoke to tell listeners that an atomic test was ignored.
Params:
  • description – the description of the ignored test
/** * Invoke to tell listeners that an atomic test was ignored. * * @param description the description of the ignored test */
public void fireTestIgnored(final Description description) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testIgnored(description); } }.run(); }
Invoke to tell listeners that an atomic test finished. Always invoke this method if you invoke fireTestStarted(Description) as listeners are likely to expect them to come in pairs.
Params:
  • description – the description of the test that finished
/** * Invoke to tell listeners that an atomic test finished. Always invoke * this method if you invoke {@link #fireTestStarted(Description)} * as listeners are likely to expect them to come in pairs. * * @param description the description of the test that finished */
public void fireTestFinished(final Description description) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testFinished(description); } }.run(); }
Ask that the tests run stop before starting the next test. Phrased politely because the test currently running will not be interrupted. It seems a little odd to put this functionality here, but the RunNotifier is the only object guaranteed to be shared amongst the many runners involved.
/** * Ask that the tests run stop before starting the next test. Phrased politely because * the test currently running will not be interrupted. It seems a little odd to put this * functionality here, but the <code>RunNotifier</code> is the only object guaranteed * to be shared amongst the many runners involved. */
public void pleaseStop() { pleaseStop = true; }
Internal use only. The Result's listener must be first.
/** * Internal use only. The Result's listener must be first. */
public void addFirstListener(RunListener listener) { if (listener == null) { throw new NullPointerException("Cannot add a null listener"); } listeners.add(0, wrapIfNotThreadSafe(listener)); } }