Sample

Schnappinger/junit4/org.junit.runner.notification.RunNotifier

Human rating uses the original dataset scale.

Human3.9
Lines214

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
35.8Δ 13.1
Scalabrino0.7950–1; higher is more readable
61.3Δ 12.5
Dorn0.1630–1; higher is more readable
38.6Δ 10.2
Mi0.5590–1; higher is more readable
44.6Δ 4.3
LLOC67Logical lines; fewer is more readable
31.7Δ 17.2
DeepSeek V4 Pro16.330–20; mean of three runs
53.1Δ 4.3
GPT-6.1 Sol170–20; mean of three runs
55.3Δ 6.4
BTTF0.6480–1; higher is more readable
67.3Δ 18.5
Human3.91–4; original rating
48.8

Views

Source code

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 <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> fListeners = new CopyOnWriteArrayList<RunListener>(); private volatile boolean fPleaseStop = false; /** * Internal use only */ public void addListener(RunListener listener) { if (listener == null) { throw new NullPointerException("Cannot add a null listener"); } fListeners.add(wrapIfNotThreadSafe(listener)); } /** * Internal use only */ public void removeListener(RunListener listener) { if (listener == null) { throw new NullPointerException("Cannot remove a null listener"); } fListeners.remove(wrapIfNotThreadSafe(listener)); } /** * 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> fCurrentListeners; SafeNotifier() { this(fListeners); } SafeNotifier(List<RunListener> currentListeners) { fCurrentListeners = currentListeners; } void run() { int capacity = fCurrentListeners.size(); ArrayList<RunListener> safeListeners = new ArrayList<RunListener>(capacity); ArrayList<Failure> failures = new ArrayList<Failure>(capacity); for (RunListener listener : fCurrentListeners) { 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. */ public void fireTestRunStarted(final Description description) { new SafeNotifier() { @Override protected void notifyListener(RunListener each) throws Exception { each.testRunStarted(description); } }.run(); } /** * 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. * * @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 (fPleaseStop) { 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. * * @param failure the description of the test that failed and the exception thrown */ public void fireTestFailure(Failure failure) { fireTestFailures(fListeners, 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. * * @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. * * @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 {@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 <code>RunNotifier</code> is the only object guaranteed * to be shared amongst the many runners involved. */ public void pleaseStop() { fPleaseStop = true; } /** * 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"); } fListeners.add(0, wrapIfNotThreadSafe(listener)); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.4920.47−162.376
Source linesThe number of non-empty source lines.214+85.6
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.372−6.557

Intercept 8.87 + feature contributions = -74.463 (log-odds).
Score = sigmoid(-74.463) = 0.

Score0.795

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.215−6.576
Indentation frequencyHow rapidly indentation changes from line to line.163+4.901
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.163−3.32
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.213.784+2.578
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.92.898+0.694
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.054+0.416
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.95.944−0.399

Intercept 0.07 + feature contributions = -1.635 (log-odds).
Score = sigmoid(-1.635) = 0.163.

Score0.559
Score67
Run 1

The code is generally well-structured and readable. It uses clear class and method names, and Javadocs explain intent. The SafeNotifier inner class centralizes listener notification logic, reducing duplication. However, readability is hampered by some issues: the wrapIfNotThreadSafe method uses a ternary on separate lines, which can be slightly hard to scan. The fireTestFailures method has a non-standard parameter indentation. Deep nesting is mild, but the SafeNotifier.run() method contains a try/catch and loop, which is acceptable. The code is concise overall. The use of an abstract inner class with anonymous subclasses for each event adds some overhead to reading flow, as each fireTest* method follows a similar pattern. The unusual 'f' prefix for field names (e.g., fListeners, fPleaseStop) is a holdover from older Java style and may confuse modern readers.

Run 2

The code is generally well-structured and readable. It uses a clear class-level organization with a helper inner class (SafeNotifier) to centralize listener notification and error handling, which reduces duplication. Nesting is moderate and largely unavoidable due to anonymous inner classes for event-specific notifications. Intent is mostly clear through descriptive method names and Javadoc, though some methods rely on comments like 'Do not invoke' which could be more explicit. Length is reasonable, but the repeated anonymous SafeNotifier subclasses add verbosity. Action granularity is good—most methods perform one logical action per statement. Reading flow is natural, with public API methods followed by private helpers. Minor issues include the use of Hungarian notation (fListeners, fPleaseStop), a long method signature split over lines, and the SafeNotifier's run() method handling multiple responsibilities (collecting listeners, catching exceptions, firing failures) in one block.

Run 3

The code is well-structured with clear separation of concerns. The RunNotifier class manages listeners efficiently using CopyOnWriteArrayList for thread safety. The SafeNotifier inner class elegantly handles exception isolation between listeners, preventing one faulty listener from breaking the notification chain. Method names are descriptive and follow clear intent. However, the repetitive anonymous inner class pattern for each fire method adds verbosity, though it maintains consistency. The nesting is shallow with only one level in most methods. The field naming convention (fListeners, fPleaseStop) is somewhat dated and reduces modern readability. Each line performs a single action, aiding comprehension. The Javadoc comments are helpful but could be more concise. Overall, the code is highly readable with minor stylistic concerns around the Hungarian notation and repetitive patterns that could be refactored using lambda expressions in modern Java.

Run 1

Code Structure: Small, focused methods and the shared SafeNotifier abstraction organize listener management and event dispatch logically. Nesting: Mostly shallow, though anonymous classes and the failure-dispatch loop introduce moderate nesting. Clarity of intent: Descriptive method names and useful Javadoc make the purpose clear; prefixed field names and recursive failure reporting require closer attention. Code length: Individual methods are concise, but repeated anonymous-class boilerplate makes the class longer than its core behavior warrants. Action granularity: Statements generally perform one action per line, with clean separation of validation, notification, and failure collection. Reading flow: Consistent formatting and repeated dispatch patterns make navigation predictable, although tracing error handling between SafeNotifier.run and fireTestFailures interrupts the otherwise natural flow.

Run 2

Code Structure: Responsibilities are logically separated into listener management, safe dispatch, and event methods; SafeNotifier centralizes exception handling. Nesting: Mostly shallow, although anonymous classes and the failure-dispatch loop introduce moderate nesting. Clarity of intent: Descriptive method names and useful Javadoc clearly communicate behavior; prefixed fields and generic names such as 'each' are minor weaknesses. Code length: Methods are short, but repeated anonymous-class boilerplate makes the class longer than its functionality warrants. Action granularity: Statements generally perform one action per line, with clear separation of validation and execution. Reading flow: Consistent formatting and repeated dispatch patterns make navigation predictable, though tracing recursive failure reporting between SafeNotifier.run and fireTestFailures requires extra attention.

Run 3

Code Structure: Well-organized methods and a shared SafeNotifier abstraction centralize notification and exception handling. Nesting: Generally shallow, although anonymous classes and the failure-notification loop introduce moderate nesting. Clarity of intent: Descriptive method names and useful Javadoc clearly explain the API; prefixed fields and generic names such as 'each' are minor weaknesses. Code length: Individual methods are concise, but repeated anonymous-class boilerplate makes the class longer than necessary. Action granularity: Statements generally perform one action per line, with straightforward validation and dispatch. Reading flow: Consistent formatting and repeated notification patterns make the code easy to follow. However, failure handling cycles between SafeNotifier.run and fireTestFailures, requiring extra effort to understand recursive propagation and termination.