Index: lib/src/executable.dart |
diff --git a/lib/src/executable.dart b/lib/src/executable.dart |
index 6a10cf36f3909df86fd550b36cb9a3031ba334ba..b1a792e2948a473b35c1f7c6df7e044a6980d17b 100644 |
--- a/lib/src/executable.dart |
+++ b/lib/src/executable.dart |
@@ -9,35 +9,23 @@ library test.executable; |
import 'dart:async'; |
import 'dart:io'; |
-import 'dart:math' as math; |
-import 'package:args/args.dart'; |
import 'package:async/async.dart'; |
import 'package:stack_trace/stack_trace.dart'; |
import 'package:yaml/yaml.dart'; |
import 'backend/metadata.dart'; |
-import 'backend/test_platform.dart'; |
-import 'runner/engine.dart'; |
import 'runner/application_exception.dart'; |
+import 'runner/configuration.dart'; |
+import 'runner/engine.dart'; |
import 'runner/load_exception.dart'; |
import 'runner/load_suite.dart'; |
import 'runner/loader.dart'; |
import 'runner/reporter/compact.dart'; |
import 'runner/reporter/expanded.dart'; |
import 'util/exit_codes.dart' as exit_codes; |
-import 'util/io.dart'; |
import 'utils.dart'; |
-/// The argument parser used to parse the executable arguments. |
-final _parser = new ArgParser(allowTrailingOptions: true); |
- |
-/// The default number of test suites to run at once. |
-/// |
-/// This defaults to half the available processors, since presumably some of |
-/// them will be used for the OS and other processes. |
-final _defaultConcurrency = math.max(1, Platform.numberOfProcessors ~/ 2); |
- |
/// A merged stream of all signals that tell the test runner to shut down |
/// gracefully. |
/// |
@@ -78,69 +66,23 @@ bool get _usesTransformer { |
}); |
} |
+Configuration _configuration; |
+ |
main(List<String> args) async { |
- var allPlatforms = TestPlatform.all.toList(); |
- if (!Platform.isMacOS) allPlatforms.remove(TestPlatform.safari); |
- if (!Platform.isWindows) allPlatforms.remove(TestPlatform.internetExplorer); |
- |
- _parser.addFlag("help", abbr: "h", negatable: false, |
- help: "Shows this usage information."); |
- _parser.addFlag("version", negatable: false, |
- help: "Shows the package's version."); |
- _parser.addOption("package-root", hide: true); |
- _parser.addOption("name", |
- abbr: 'n', |
- help: 'A substring of the name of the test to run.\n' |
- 'Regular expression syntax is supported.'); |
- _parser.addOption("plain-name", |
- abbr: 'N', |
- help: 'A plain-text substring of the name of the test to run.'); |
- _parser.addOption("platform", |
- abbr: 'p', |
- help: 'The platform(s) on which to run the tests.', |
- allowed: allPlatforms.map((platform) => platform.identifier).toList(), |
- defaultsTo: 'vm', |
- allowMultiple: true); |
- _parser.addOption("concurrency", |
- abbr: 'j', |
- help: 'The number of concurrent test suites run.\n' |
- '(defaults to $_defaultConcurrency)', |
- valueHelp: 'threads'); |
- _parser.addOption("pub-serve", |
- help: 'The port of a pub serve instance serving "test/".', |
- hide: !supportsPubServe, |
- valueHelp: 'port'); |
- _parser.addOption("reporter", |
- abbr: 'r', |
- help: 'The runner used to print test results.', |
- allowed: ['compact', 'expanded'], |
- defaultsTo: Platform.isWindows ? 'expanded' : 'compact', |
- allowedHelp: { |
- 'compact': 'A single line, updated continuously.', |
- 'expanded': 'A separate line for each update.' |
- }); |
- _parser.addFlag("verbose-trace", negatable: false, |
- help: 'Whether to emit stack traces with core library frames.'); |
- _parser.addFlag("js-trace", negatable: false, |
- help: 'Whether to emit raw JavaScript stack traces for browser tests.'); |
- _parser.addFlag("color", defaultsTo: null, |
- help: 'Whether to use terminal colors.\n(auto-detected by default)'); |
- |
- var options; |
try { |
- options = _parser.parse(args); |
+ _configuration = new Configuration.parse(args); |
} on FormatException catch (error) { |
_printUsage(error.message); |
exitCode = exit_codes.usage; |
return; |
} |
- if (options["help"]) { |
+ if (_configuration.help) { |
_printUsage(); |
return; |
} |
- if (options["version"]) { |
+ if (_configuration.version) { |
if (!_printVersion()) { |
stderr.writeln("Couldn't find version number."); |
exitCode = exit_codes.data; |
@@ -148,14 +90,8 @@ main(List<String> args) async { |
return; |
} |
- var color = options["color"]; |
- if (color == null) color = canUseSpecialChars; |
- |
- var pubServeUrl; |
- if (options["pub-serve"] != null) { |
- pubServeUrl = Uri.parse("http://localhost:${options['pub-serve']}"); |
- if (!_usesTransformer) { |
- stderr.write(''' |
+ if (_configuration.pubServeUrl != null && !_usesTransformer) { |
+ stderr.write(''' |
When using --pub-serve, you must include the "test/pub_serve" transformer in |
your pubspec: |
@@ -163,54 +99,26 @@ transformers: |
- test/pub_serve: |
\$include: test/**_test.dart |
'''); |
- exitCode = exit_codes.data; |
- return; |
- } |
- } |
- |
- var concurrency = _defaultConcurrency; |
- if (options["concurrency"] != null) { |
- try { |
- concurrency = int.parse(options["concurrency"]); |
- } catch (error) { |
- _printUsage('Couldn\'t parse --concurrency "${options["concurrency"]}":' |
- ' ${error.message}'); |
- exitCode = exit_codes.usage; |
- return; |
- } |
- } |
- |
- var paths = options.rest; |
- if (paths.isEmpty) { |
- if (!new Directory("test").existsSync()) { |
- _printUsage('No test files were passed and the default "test/" ' |
- "directory doesn't exist."); |
- exitCode = exit_codes.data; |
- return; |
- } |
- paths = ["test"]; |
+ exitCode = exit_codes.data; |
+ return; |
} |
- var pattern; |
- if (options["name"] != null) { |
- if (options["plain-name"] != null) { |
- _printUsage("--name and --plain-name may not both be passed."); |
- exitCode = exit_codes.data; |
- return; |
- } |
- pattern = new RegExp(options["name"]); |
- } else if (options["plain-name"] != null) { |
- pattern = options["plain-name"]; |
+ if (!_configuration.explicitPaths && |
+ !new Directory(_configuration.paths.single).existsSync()) { |
+ _printUsage('No test files were passed and the default "test/" ' |
+ "directory doesn't exist."); |
+ exitCode = exit_codes.data; |
+ return; |
} |
- var metadata = new Metadata(verboseTrace: options["verbose-trace"]); |
- var platforms = options["platform"].map(TestPlatform.find); |
- var loader = new Loader(platforms, |
- pubServeUrl: pubServeUrl, |
- packageRoot: options["package-root"], |
- color: color, |
+ var metadata = new Metadata( |
+ verboseTrace: _configuration.verboseTrace); |
+ var loader = new Loader(_configuration.platforms, |
+ pubServeUrl: _configuration.pubServeUrl, |
+ packageRoot: _configuration.packageRoot, |
+ color: _configuration.color, |
metadata: metadata, |
- jsTrace: options["js-trace"]); |
+ jsTrace: _configuration.jsTrace); |
var closed = false; |
var signalSubscription; |
@@ -221,19 +129,19 @@ transformers: |
}); |
try { |
- var engine = new Engine(concurrency: concurrency); |
+ var engine = new Engine(concurrency: _configuration.concurrency); |
- var watch = options["reporter"] == "compact" |
+ var watch = _configuration.reporter == "compact" |
? CompactReporter.watch |
: ExpandedReporter.watch; |
watch( |
engine, |
- color: color, |
- verboseTrace: options["verbose-trace"], |
- printPath: paths.length > 1 || |
- new Directory(paths.single).existsSync(), |
- printPlatform: platforms.length > 1); |
+ color: _configuration.color, |
+ verboseTrace: _configuration.verboseTrace, |
+ printPath: _configuration.paths.length > 1 || |
+ new Directory(_configuration.paths.single).existsSync(), |
+ printPlatform: _configuration.platforms.length > 1); |
// Override the signal handler to close [reporter]. [loader] will still be |
// closed in the [whenComplete] below. |
@@ -260,7 +168,7 @@ transformers: |
try { |
var results = await Future.wait([ |
- _loadSuites(paths, pattern, loader, engine), |
+ _loadSuites(loader, engine), |
engine.run() |
], eagerError: true); |
@@ -275,13 +183,14 @@ transformers: |
} |
if (engine.passed.length == 0 && engine.failed.length == 0 && |
- engine.skipped.length == 0 && pattern != null) { |
+ engine.skipped.length == 0 && _configuration.pattern != null) { |
stderr.write('No tests match '); |
- if (pattern is RegExp) { |
- stderr.writeln('regular expression "${pattern.pattern}".'); |
+ if (_configuration.pattern is RegExp) { |
+ var pattern = (_configuration.pattern as RegExp).pattern; |
+ stderr.writeln('regular expression "$pattern".'); |
} else { |
- stderr.writeln('"$pattern".'); |
+ stderr.writeln('"${_configuration.pattern}".'); |
} |
exitCode = exit_codes.data; |
} |
@@ -302,16 +211,15 @@ transformers: |
} |
} |
-/// Load the test suites in [paths] that match [pattern] and pass them to |
-/// [engine]. |
+/// Load the test suites in [_configuration.paths] that match |
+/// [_configuration.pattern] and pass them to [engine]. |
/// |
/// This completes once all the tests have been added to the engine. It does not |
/// run the engine. |
-Future _loadSuites(List<String> paths, Pattern pattern, Loader loader, |
- Engine engine) async { |
+Future _loadSuites(Loader loader, Engine engine) async { |
var group = new FutureGroup(); |
- mergeStreams(paths.map((path) { |
+ mergeStreams(_configuration.paths.map((path) { |
if (new Directory(path).existsSync()) return loader.loadDir(path); |
if (new File(path).existsSync()) return loader.loadFile(path); |
@@ -322,9 +230,9 @@ Future _loadSuites(List<String> paths, Pattern pattern, Loader loader, |
})).listen((loadSuite) { |
group.add(new Future.sync(() { |
engine.suiteSink.add(loadSuite.changeSuite((suite) { |
- if (pattern == null) return suite; |
- return suite.change( |
- tests: suite.tests.where((test) => test.name.contains(pattern))); |
+ if (_configuration.pattern == null) return suite; |
+ return suite.change(tests: suite.tests.where( |
+ (test) => test.name.contains(_configuration.pattern))); |
})); |
})); |
}, onError: (error, stackTrace) { |
@@ -355,7 +263,7 @@ void _printUsage([String error]) { |
Usage: pub run test:test [files or directories...] |
-${_parser.usage} |
+${Configuration.usage} |
"""); |
} |