The first time I wrote source code analysis, I introduced the running process and important classes and interfaces!
Junitcore
Junitcore adopts the facade mode. You can start the junit4 and junit3 tests, or test the specified class. Junitcore declares the runnotifier class, which uses the observer mode to manage events. Runlistener is the base class of the test event. If you want to customize an event, you can inherit this class. Two runlistener parameters are added by default. One is textlistener, and the other is the listener constructed by the result function createlistener, which is used to record the start and end times, the total number of executions, and the total number of failures. You can see that firetestrunstarted is triggered before the run method is called, and firetestrunfinished is triggered after execution. Key code (truncation)
private final RunNotifier notifier = new RunNotifier(); Result runMain(JUnitSystem system, String... args) { RunListener listener = new TextListener(system); addListener(listener); return run(jUnitCommandLineParseResult.createRequest(defaultComputer())); } public Result run(Request request) { return run(request.getRunner()); } public Result run(Runner runner) { Result result = new Result(); RunListener listener = result.createListener(); notifier.addFirstListener(listener); try { notifier.fireTestRunStarted(runner.getDescription()); runner.run(notifier); notifier.fireTestRunFinished(result); } finally { removeListener(listener); } return result; }
Request
The encapsulation of class and test can be all tests under a class, all tests under all classes, and can be combined with filters. Use the classes method to obtain the suite. The Suite contains the runner of each class. Key code (truncation)
public static Request classes(Computer computer, Class<?>... classes) { try { AllDefaultPossibilitiesBuilder builder = new AllDefaultPossibilitiesBuilder(true); Runner suite = computer.getSuite(builder, classes); return runner(suite); } catch (InitializationError e) { throw new RuntimeException( "Bug in saff‘s brain: Suite constructor, called as above, should always complete"); } }
Runnerbuilder
The runner creation adopts the builder mode and generates a runner for each class.
private List<Runner> runners(Class<?>[] children) { ArrayList<Runner> runners = new ArrayList<Runner>(); for (Class<?> each : children) { Runner childRunner = safeRunnerForClass(each); if (childRunner != null) { runners.add(childRunner); } } return runners; }
Alldefapospossibilitiesbuilder
Select a specific builder. The default value is junit4builder. If the class has @ ignore annotation, the value is ignoredbuilder. If the class has @ runwith annotation, the value is ignoredbuilder. If the test method has suite, the value is suitemethodbuilder, if the class inherits from JUnit. framework. the value of testcase is junit38classrunner. Otherwise, the default value of junit4builder is used to return blockjunit4classrunner.
public Runner runnerForClass(Class<?> testClass) throws Throwable { List<RunnerBuilder> builders = Arrays.asList( ignoredBuilder(), annotatedBuilder(), suiteMethodBuilder(), junit3Builder(), junit4Builder()); for (RunnerBuilder each : builders) { Runner runner = each.safeRunnerForClass(testClass); if (runner != null) { return runner; } } return null; }
Junit4.12 source code analysis-start to select runner