Skip to content

Commit

Permalink
#37: Encapsulate command line options parser
Browse files Browse the repository at this point in the history
  • Loading branch information
marcphilipp committed Dec 3, 2015
1 parent 79c6f9f commit 6c9d0a5
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 72 deletions.
111 changes: 39 additions & 72 deletions junit-console/src/main/java/org/junit/gen5/console/ConsoleRunner.java
Expand Up @@ -10,27 +10,19 @@


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


import static io.airlift.airline.SingleCommand.singleCommand; import static org.junit.gen5.engine.TestPlanSpecification.*;
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.File;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;


import javax.inject.Inject;

import io.airlift.airline.Arguments;
import io.airlift.airline.Command;
import io.airlift.airline.Help;
import io.airlift.airline.Option;
import io.airlift.airline.model.CommandMetadata;

import org.junit.gen5.commons.util.Preconditions; import org.junit.gen5.commons.util.Preconditions;
import org.junit.gen5.commons.util.ReflectionUtils; import org.junit.gen5.commons.util.ReflectionUtils;
import org.junit.gen5.console.options.AirlineCommandLineOptionsParser;
import org.junit.gen5.console.options.CommandLineOptions;
import org.junit.gen5.console.options.CommandLineOptionsParser;
import org.junit.gen5.engine.TestPlanSpecification; import org.junit.gen5.engine.TestPlanSpecification;
import org.junit.gen5.engine.TestPlanSpecificationElement; import org.junit.gen5.engine.TestPlanSpecificationElement;
import org.junit.gen5.launcher.Launcher; import org.junit.gen5.launcher.Launcher;
Expand All @@ -40,67 +32,45 @@
/** /**
* @since 5.0 * @since 5.0
*/ */
@Command(name = "ConsoleRunner", description = "console test runner")
public class ConsoleRunner { public class ConsoleRunner {


// @formatter:off private CommandLineOptions options;
@Option(name = {"-h", "--help"}, description = "Display help information")
private boolean help;

@Option(name = { "-x", "--enable-exit-code" },
description = "Exit process with number of failing tests as exit code")
private boolean enableExitCode;

@Option(name = { "-C", "--disable-ansi-colors" },
description = "Disable colored output (not supported by all terminals)")
private boolean disableAnsiColors;

@Option(name = {"-a", "--all"}, description = "Run all tests")
private boolean runAllTests;

@Option(name = {"-D", "--hide-details"}, description = "Hide details while tests are being executed. "
+ "Only show the summary and test failures.")
private boolean hideDetails;

@Option(name = {"-n", "--filter-classname"}, description = "Give a regular expression to include only classes whose fully qualified names match.")
private String classnameFilter;

@Option(name = {"-t", "--filter-tags"}, description = "Give a tag to include in the test run. This option can be repeated.")
private List<String> tagsFilter;

@Arguments(description = "Test classes, methods or packages to execute."
+ " If --all|-a has been chosen, arguments can list all classpath roots that should be considered for test scanning,"
+ " or none if the full classpath shall be scanned.")
private List<String> arguments;

// @formatter:on

@Inject
public CommandMetadata commandMetadata;


public static void main(String... args) { public static void main(String... args) {
ConsoleRunner consoleRunner = singleCommand(ConsoleRunner.class).parse(args); CommandLineOptionsParser parser = new AirlineCommandLineOptionsParser();
CommandLineOptions options = parser.parse(args);


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


try { try {
consoleRunner.run(); TestExecutionSummary summary = new ConsoleRunner(options).run();
int exitCode = computeExitCode(options, summary);
System.exit(exitCode);
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(System.err); e.printStackTrace(System.err);
System.err.println(); System.err.println();
showHelp(consoleRunner); parser.printHelp();
System.exit(-1); System.exit(-1);
} }
} }


private static void showHelp(ConsoleRunner consoleRunner) { private static int computeExitCode(CommandLineOptions options, TestExecutionSummary summary) {
Help.help(consoleRunner.commandMetadata); if (options.isExitCodeEnabled()) {
long failedTests = summary.countFailedTests();
return (int) Math.min(Integer.MAX_VALUE, failedTests);
}
return 0;
} }


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

private TestExecutionSummary run() {
// TODO Configure launcher? // TODO Configure launcher?
Launcher launcher = new Launcher(); Launcher launcher = new Launcher();


Expand All @@ -114,49 +84,46 @@ private void run() {


printSummaryToStandardOut(summary); printSummaryToStandardOut(summary);


if (enableExitCode) { return summary;
long failedTests = summary.countFailedTests();
int exitCode = (int) Math.min(Integer.MAX_VALUE, failedTests);
System.exit(exitCode);
}
} }


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


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


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


if (hideDetails) { //Otherwise the failures have already been printed if (options.isHideDetails()) { // Otherwise the failures have already been printed
summary.printFailuresOn(stdout); summary.printFailuresOn(stdout);
} }


Expand All @@ -165,8 +132,8 @@ private void printSummaryToStandardOut(TestExecutionSummary summary) {
} }


private List<TestPlanSpecificationElement> testPlanSpecificationElementsFromArguments() { private List<TestPlanSpecificationElement> testPlanSpecificationElementsFromArguments() {
Preconditions.notNull(arguments, "No arguments given"); Preconditions.notNull(options.getArguments(), "No arguments given");
return toTestPlanSpecificationElements(arguments); return toTestPlanSpecificationElements(options.getArguments());
} }


List<TestPlanSpecificationElement> toTestPlanSpecificationElements(List<String> arguments) { List<TestPlanSpecificationElement> toTestPlanSpecificationElements(List<String> arguments) {
Expand Down
@@ -0,0 +1,93 @@
/*
* 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.options;

import java.util.List;

import io.airlift.airline.Arguments;
import io.airlift.airline.Command;
import io.airlift.airline.Option;

@Command(name = "ConsoleRunner", description = "console test runner")
public class AirlineCommandLineOptions implements CommandLineOptions {

// @formatter:off
@Option(name = {"-h", "--help"}, description = "Display help information")
private boolean displayHelp;

@Option(name = { "-x", "--enable-exit-code" },
description = "Exit process with number of failing tests as exit code")
private boolean exitCodeEnabled;

@Option(name = { "-C", "--disable-ansi-colors" },
description = "Disable colored output (not supported by all terminals)")
private boolean ansiColorOutputDisabled;

@Option(name = {"-a", "--all"}, description = "Run all tests")
private boolean runAllTests;

@Option(name = {"-D", "--hide-details"}, description = "Hide details while tests are being executed. "
+ "Only show the summary and test failures.")
private boolean hideDetails;

@Option(name = {"-n", "--filter-classname"}, description = "Give a regular expression to include only classes whose fully qualified names match.")
private String classnameFilter;

@Option(name = {"-t", "--filter-tags"}, description = "Give a tag to include in the test run. This option can be repeated.")
private List<String> tagsFilter;

@Arguments(description = "Test classes, methods or packages to execute."
+ " If --all|-a has been chosen, arguments can list all classpath roots that should be considered for test scanning,"
+ " or none if the full classpath shall be scanned.")
private List<String> arguments;
// @formatter:on

@Override
public boolean isDisplayHelp() {
return displayHelp;
}

@Override
public boolean isExitCodeEnabled() {
return exitCodeEnabled;
}

@Override
public boolean isAnsiColorOutputDisabled() {
return ansiColorOutputDisabled;
}

@Override
public boolean isRunAllTests() {
return runAllTests;
}

@Override
public boolean isHideDetails() {
return hideDetails;
}

@Override
public String getClassnameFilter() {
return classnameFilter;
}

@Override
public List<String> getTagsFilter() {
return tagsFilter;
}

@Override
public List<String> getArguments() {
return arguments;
}

}
@@ -0,0 +1,29 @@
/*
* 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.options;

import static io.airlift.airline.Help.help;
import static io.airlift.airline.SingleCommand.singleCommand;
import static io.airlift.airline.model.MetadataLoader.loadCommand;

public class AirlineCommandLineOptionsParser implements CommandLineOptionsParser {

@Override
public CommandLineOptions parse(String... arguments) {
return singleCommand(AirlineCommandLineOptions.class).parse(arguments);
}

@Override
public void printHelp() {
help(loadCommand(AirlineCommandLineOptions.class));
}

}
@@ -0,0 +1,33 @@
/*
* 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.options;

import java.util.List;

public interface CommandLineOptions {

boolean isDisplayHelp();

boolean isExitCodeEnabled();

boolean isAnsiColorOutputDisabled();

boolean isRunAllTests();

boolean isHideDetails();

String getClassnameFilter();

List<String> getTagsFilter();

List<String> getArguments();

}
@@ -0,0 +1,19 @@
/*
* 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.options;

public interface CommandLineOptionsParser {

CommandLineOptions parse(String... arguments);

void printHelp();

}

0 comments on commit 6c9d0a5

Please sign in to comment.