Skip to content

Commit

Permalink
#37: Extract ConsoleRunner logic into ConsoleTasks
Browse files Browse the repository at this point in the history
- Better separation of concerns
- Better testability
  • Loading branch information
marcphilipp committed Dec 4, 2015
1 parent 7e1e67e commit f0dfe1f
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 127 deletions.
130 changes: 18 additions & 112 deletions junit-console/src/main/java/org/junit/gen5/console/ConsoleRunner.java
Expand Up @@ -10,28 +10,15 @@

package org.junit.gen5.console;

import static org.junit.gen5.engine.TestPlanSpecification.allTests;
import static org.junit.gen5.engine.TestPlanSpecification.byTags;
import static org.junit.gen5.engine.TestPlanSpecification.classNameMatches;

import java.io.File;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.gen5.commons.util.Preconditions;
import org.junit.gen5.commons.util.ReflectionUtils;
import org.junit.gen5.console.options.CommandLineOptions;
import org.junit.gen5.console.options.CommandLineOptionsParser;
import org.junit.gen5.console.options.JOptSimpleCommandLineOptionsParser;
import org.junit.gen5.engine.TestPlanSpecification;
import org.junit.gen5.engine.TestPlanSpecificationElement;
import org.junit.gen5.launcher.Launcher;
import org.junit.gen5.launcher.listeners.SummaryCreatingTestListener;
import org.junit.gen5.launcher.listeners.TestExecutionSummary;
import org.junit.gen5.console.tasks.ConsoleTask;
import org.junit.gen5.console.tasks.DisplayHelpTask;
import org.junit.gen5.console.tasks.ExecuteTestsTask;

/**
* @since 5.0
Expand All @@ -41,115 +28,34 @@ public class ConsoleRunner {
public static void main(String... args) {
CommandLineOptionsParser parser = new JOptSimpleCommandLineOptionsParser();
CommandLineOptions options = parser.parse(args);
ConsoleTask task = determineTask(parser, options);

if (options.isDisplayHelp()) {
parser.printHelp();
System.exit(0);
}

PrintWriter out = new PrintWriter(System.out);
try {
TestExecutionSummary summary = new ConsoleRunner(options).run();
int exitCode = computeExitCode(options, summary);
int exitCode = task.execute(out);
System.exit(exitCode);
}
catch (Exception e) {
e.printStackTrace(System.err);
System.err.println();
parser.printHelp();
printException(e, System.err);
displayHelp(parser, out);
System.exit(-1);
}
}

private static int computeExitCode(CommandLineOptions options, TestExecutionSummary summary) {
if (options.isExitCodeEnabled()) {
long failedTests = summary.countFailedTests();
return (int) Math.min(Integer.MAX_VALUE, failedTests);
}
return 0;
}

private final CommandLineOptions options;

public ConsoleRunner(CommandLineOptions options) {
this.options = options;
}

private TestExecutionSummary run() {
updateClassLoader();

// TODO Configure launcher?
Launcher launcher = new Launcher();

TestExecutionSummary summary = new TestExecutionSummary();
registerListeners(launcher, summary);

TestPlanSpecification testPlanSpecification = createTestPlanSpecification();
launcher.execute(testPlanSpecification);

printSummaryToStandardOut(summary);
return summary;
}

private void updateClassLoader() {
List<String> additionalClasspathEntries = options.getAdditionalClasspathEntries();
if (!additionalClasspathEntries.isEmpty()) {
URL[] urls = new ClasspathEntriesParser().toURLs(additionalClasspathEntries);
ClassLoader parentClassLoader = ReflectionUtils.getDefaultClassLoader();
URLClassLoader customClassLoader = URLClassLoader.newInstance(urls, parentClassLoader);
Thread.currentThread().setContextClassLoader(customClassLoader);
}
}

private void registerListeners(Launcher launcher, TestExecutionSummary summary) {
SummaryCreatingTestListener testSummaryListener = new SummaryCreatingTestListener(summary);
launcher.registerTestPlanExecutionListeners(testSummaryListener);
if (!options.isHideDetails()) {
launcher.registerTestPlanExecutionListeners(
new ColoredPrintingTestListener(System.out, options.isAnsiColorOutputDisabled()));
}
}

private TestPlanSpecification createTestPlanSpecification() {
TestPlanSpecification testPlanSpecification;
if (options.isRunAllTests()) {
Set<File> rootDirectoriesToScan = new HashSet<>();
if (options.getArguments().isEmpty()) {
rootDirectoriesToScan.addAll(ReflectionUtils.getAllClasspathRootDirectories());
}
else {
options.getArguments().stream().map(File::new).forEach(rootDirectoriesToScan::add);
}
testPlanSpecification = TestPlanSpecification.build(allTests(rootDirectoriesToScan));
}
else {
testPlanSpecification = TestPlanSpecification.build(testPlanSpecificationElementsFromArguments());
}
options.getClassnameFilter().ifPresent(
classnameFilter -> testPlanSpecification.filterWith(classNameMatches(classnameFilter)));
if (!options.getTagsFilter().isEmpty()) {
testPlanSpecification.filterWith(byTags(options.getTagsFilter()));
}
return testPlanSpecification;
}

private void printSummaryToStandardOut(TestExecutionSummary summary) {
PrintWriter stdout = new PrintWriter(System.out);

if (options.isHideDetails()) { // Otherwise the failures have already been printed
summary.printFailuresOn(stdout);
private static ConsoleTask determineTask(CommandLineOptionsParser parser, CommandLineOptions options) {
if (options.isDisplayHelp()) {
return new DisplayHelpTask(parser);
}

summary.printOn(stdout);
stdout.close();
return new ExecuteTestsTask(options);
}

private List<TestPlanSpecificationElement> testPlanSpecificationElementsFromArguments() {
Preconditions.notEmpty(options.getArguments(), "No arguments given");
return toTestPlanSpecificationElements(options.getArguments());
private static void printException(Exception exception, PrintStream out) {
exception.printStackTrace(out);
out.println();
}

List<TestPlanSpecificationElement> toTestPlanSpecificationElements(List<String> arguments) {
return TestPlanSpecification.forNames(arguments);
private static void displayHelp(CommandLineOptionsParser parser, PrintWriter out) {
new DisplayHelpTask(parser).execute(out);
}

}
Expand Up @@ -10,10 +10,12 @@

package org.junit.gen5.console.options;

import java.io.Writer;

public interface CommandLineOptionsParser {

CommandLineOptions parse(String... arguments);

void printHelp();
void printHelp(Writer writer);

}
Expand Up @@ -11,6 +11,7 @@
package org.junit.gen5.console.options;

import java.io.IOException;
import java.io.Writer;

import joptsimple.BuiltinHelpFormatter;
import joptsimple.OptionParser;
Expand All @@ -27,11 +28,11 @@ public CommandLineOptions parse(String... arguments) {
}

@Override
public void printHelp() {
public void printHelp(Writer writer) {
OptionParser optionParser = getAvailableOptions().getParser();
optionParser.formatHelpWith(new BuiltinHelpFormatter(100, 4));
try {
optionParser.printHelpOn(System.out);
optionParser.printHelpOn(writer);
}
catch (IOException e) {
throw new RuntimeException("Error printing help", e);
Expand Down
Expand Up @@ -8,7 +8,7 @@
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.gen5.console;
package org.junit.gen5.console.tasks;

import static java.util.stream.Collectors.toList;

Expand Down
Expand Up @@ -8,15 +8,15 @@
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.gen5.console;
package org.junit.gen5.console.tasks;

import static org.junit.gen5.console.ColoredPrintingTestListener.Color.BLUE;
import static org.junit.gen5.console.ColoredPrintingTestListener.Color.GREEN;
import static org.junit.gen5.console.ColoredPrintingTestListener.Color.NONE;
import static org.junit.gen5.console.ColoredPrintingTestListener.Color.RED;
import static org.junit.gen5.console.ColoredPrintingTestListener.Color.YELLOW;
import static org.junit.gen5.console.tasks.ColoredPrintingTestListener.Color.BLUE;
import static org.junit.gen5.console.tasks.ColoredPrintingTestListener.Color.GREEN;
import static org.junit.gen5.console.tasks.ColoredPrintingTestListener.Color.NONE;
import static org.junit.gen5.console.tasks.ColoredPrintingTestListener.Color.RED;
import static org.junit.gen5.console.tasks.ColoredPrintingTestListener.Color.YELLOW;

import java.io.PrintStream;
import java.io.PrintWriter;

import org.junit.gen5.engine.TestDescriptor;
import org.junit.gen5.engine.TestEngine;
Expand All @@ -27,12 +27,12 @@
/**
* @since 5.0
*/
public class ColoredPrintingTestListener implements TestPlanExecutionListener, TestExecutionListener {
class ColoredPrintingTestListener implements TestPlanExecutionListener, TestExecutionListener {

private final PrintStream out;
private final PrintWriter out;
private final boolean disableAnsiColors;

public ColoredPrintingTestListener(PrintStream out, boolean disableAnsiColors) {
ColoredPrintingTestListener(PrintWriter out, boolean disableAnsiColors) {
this.out = out;
this.disableAnsiColors = disableAnsiColors;
}
Expand Down
@@ -0,0 +1,28 @@
/*
* Copyright 2015 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.gen5.console.tasks;

import java.io.PrintWriter;

/**
* A task to be executed from the console.
*/
public interface ConsoleTask {

/**
* Execute this task and return an exit code.
*
* @param out writer for console output
* @return exit code indicating success ({@code 0}) or failure ({@code != 0})
*/
int execute(PrintWriter out) throws Exception;

}
@@ -0,0 +1,31 @@
/*
* Copyright 2015 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/

package org.junit.gen5.console.tasks;

import java.io.PrintWriter;

import org.junit.gen5.console.options.CommandLineOptionsParser;

public class DisplayHelpTask implements ConsoleTask {

private final CommandLineOptionsParser parser;

public DisplayHelpTask(CommandLineOptionsParser parser) {
this.parser = parser;
}

@Override
public int execute(PrintWriter out) {
parser.printHelp(new PrintWriter(out));
return 0;
}

}

0 comments on commit f0dfe1f

Please sign in to comment.