Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: lib/src/runner/loader.dart

Issue 983573002: Add support for running browser tests to the test runner. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library unittest.runner.loader; 5 library unittest.runner.loader;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:io'; 8 import 'dart:io';
9 import 'dart:isolate'; 9 import 'dart:isolate';
10 10
11 import 'package:path/path.dart' as p; 11 import 'package:path/path.dart' as p;
12 12
13 import '../backend/suite.dart'; 13 import '../backend/suite.dart';
14 import '../runner/test_platform.dart';
14 import '../util/dart.dart'; 15 import '../util/dart.dart';
15 import '../util/io.dart'; 16 import '../util/io.dart';
16 import '../util/remote_exception.dart'; 17 import '../util/remote_exception.dart';
18 import '../utils.dart';
19 import 'browser/server.dart';
20 import 'load_exception.dart';
17 import 'vm/isolate_test.dart'; 21 import 'vm/isolate_test.dart';
18 import 'load_exception.dart';
19 22
20 /// A class for finding test files and loading them into a runnable form. 23 /// A class for finding test files and loading them into a runnable form.
21 class Loader { 24 class Loader {
25 /// All platforms for which tests should be loaded.
26 final List<TestPlatform> _platforms;
27
28 /// Whether to enable colors for Dart compilation.
29 final bool _color;
30
22 /// The package root to use for loading tests, or `null` to use the automatic 31 /// The package root to use for loading tests, or `null` to use the automatic
23 /// root. 32 /// root.
24 final String _packageRoot; 33 final String _packageRoot;
25 34
26 /// All isolates that have been spun up by the loader. 35 /// All isolates that have been spun up by the loader.
27 final _isolates = new Set<Isolate>(); 36 final _isolates = new Set<Isolate>();
28 37
38 /// The server that serves browser test pages.
39 ///
40 /// This is lazily initialized the first time it's accessed.
41 Future<BrowserServer> get _browserServer {
42 if (_browserServerCompleter == null) {
43 _browserServerCompleter = new Completer();
44 BrowserServer.start(packageRoot: _packageRoot, color: _color)
45 .then(_browserServerCompleter.complete)
46 .catchError(_browserServerCompleter.completeError);
47 }
48 return _browserServerCompleter.future;
49 }
50 Completer<BrowserServer> _browserServerCompleter;
51
29 /// Creates a new loader. 52 /// Creates a new loader.
30 /// 53 ///
31 /// If [packageRoot] is passed, it's used as the package root for all loaded 54 /// If [packageRoot] is passed, it's used as the package root for all loaded
32 /// tests. Otherwise, the `packages/` directories next to the test entrypoints 55 /// tests. Otherwise, the `packages/` directories next to the test entrypoints
33 /// will be used. 56 /// will be used.
34 Loader({String packageRoot}) 57 ///
35 : _packageRoot = packageRoot; 58 /// If [color] is true, console colors will be used when compiling Dart.
59 Loader(Iterable<TestPlatform> platforms, {String packageRoot,
60 bool color: false})
61 : _platforms = platforms.toList(),
62 _packageRoot = packageRoot,
63 _color = color;
36 64
37 /// Loads all test suites in [dir]. 65 /// Loads all test suites in [dir].
38 /// 66 ///
39 /// This will load tests from files that end in "_test.dart". 67 /// This will load tests from files that end in "_test.dart".
40 Future<Set<Suite>> loadDir(String dir) { 68 Future<List<Suite>> loadDir(String dir) {
41 return Future.wait(new Directory(dir).listSync(recursive: true) 69 return Future.wait(new Directory(dir).listSync(recursive: true)
42 .map((entry) { 70 .map((entry) {
43 if (entry is! File) return new Future.value(); 71 if (entry is! File) return new Future.value([]);
44 if (!entry.path.endsWith("_test.dart")) return new Future.value(); 72 if (!entry.path.endsWith("_test.dart")) return new Future.value([]);
45 if (p.split(entry.path).contains('packages')) return new Future.value(); 73 if (p.split(entry.path).contains('packages')) return new Future.value([]);
46 74
47 // TODO(nweiz): Provide a way for the caller to gracefully handle some 75 // TODO(nweiz): Provide a way for the caller to gracefully handle some
48 // isolates failing to load without stopping the rest. 76 // suites failing to load without stopping the rest.
49 return loadFile(entry.path); 77 return loadFile(entry.path);
50 })).then((suites) => suites.toSet()..remove(null)); 78 })).then((suites) => flatten(suites));
51 } 79 }
52 80
53 /// Loads a test suite from the file at [path]. 81 /// Loads a test suite from the file at [path].
54 /// 82 ///
55 /// This will throw a [LoadException] if the file fails to load. 83 /// This will throw a [LoadException] if the file fails to load.
56 Future<Suite> loadFile(String path) { 84 Future<List<Suite>> loadFile(String path) {
57 // TODO(nweiz): Support browser tests. 85 return Future.wait(_platforms.map((platform) {
86 if (platform == TestPlatform.chrome) return _loadBrowserFile(path);
87 assert(platform == TestPlatform.vm);
88 return _loadVmFile(path);
89 }));
90 }
91
92 /// Load the test suite at [path] in a browser.
93 Future<Suite> _loadBrowserFile(String path) =>
94 _browserServer.then((browserServer) => browserServer.loadSuite(path));
95
96 /// Load the test suite at [path] in VM isolate.
97 Future<Suite> _loadVmFile(String path) {
58 var packageRoot = packageRootFor(path, _packageRoot); 98 var packageRoot = packageRootFor(path, _packageRoot);
59 var receivePort = new ReceivePort(); 99 var receivePort = new ReceivePort();
60 return runInIsolate(''' 100 return runInIsolate('''
61 import "package:unittest/src/runner/vm/isolate_listener.dart"; 101 import "package:unittest/src/runner/vm/isolate_listener.dart";
62 102
63 import "${p.toUri(p.absolute(path))}" as test; 103 import "${p.toUri(p.absolute(path))}" as test;
64 104
65 void main(_, Map message) { 105 void main(_, Map message) {
66 var sendPort = message['reply']; 106 var sendPort = message['reply'];
67 IsolateListener.start(sendPort, () => test.main); 107 IsolateListener.start(sendPort, () => test.main);
(...skipping 10 matching lines...) Expand all
78 }).then((response) { 118 }).then((response) {
79 if (response["type"] == "loadException") { 119 if (response["type"] == "loadException") {
80 return new Future.error(new LoadException(path, response["message"])); 120 return new Future.error(new LoadException(path, response["message"]));
81 } else if (response["type"] == "error") { 121 } else if (response["type"] == "error") {
82 var asyncError = RemoteException.deserialize(response["error"]); 122 var asyncError = RemoteException.deserialize(response["error"]);
83 return new Future.error( 123 return new Future.error(
84 new LoadException(path, asyncError.error), 124 new LoadException(path, asyncError.error),
85 asyncError.stackTrace); 125 asyncError.stackTrace);
86 } 126 }
87 127
88 return new Suite(path, response["tests"].map((test) { 128 return new Suite(response["tests"].map((test) {
89 return new IsolateTest(test['name'], test['sendPort']); 129 return new IsolateTest(test['name'], test['sendPort']);
90 })); 130 }), path: path, platform: "VM");
91 }); 131 });
92 } 132 }
93 133
94 /// Closes the loader and releases all resources allocated by it. 134 /// Closes the loader and releases all resources allocated by it.
95 Future close() { 135 Future close() {
96 for (var isolate in _isolates) { 136 for (var isolate in _isolates) {
97 isolate.kill(); 137 isolate.kill();
98 } 138 }
99 _isolates.clear(); 139 _isolates.clear();
100 return new Future.value(); 140
141 if (_browserServerCompleter == null) return new Future.value();
142 return _browserServer.then((browserServer) => browserServer.close());
101 } 143 }
102 } 144 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698