Index: lib/src/runner/engine.dart |
diff --git a/lib/src/runner/engine.dart b/lib/src/runner/engine.dart |
index 355686b0e01a5b66f3ac61edd748e9bc7c10c821..6aba4ed1e1155a2545fc5254c310fc2ec5b80023 100644 |
--- a/lib/src/runner/engine.dart |
+++ b/lib/src/runner/engine.dart |
@@ -7,6 +7,8 @@ library test.runner.engine; |
import 'dart:async'; |
import 'dart:collection'; |
+import 'package:pool/pool.dart'; |
+ |
import '../backend/live_test.dart'; |
import '../backend/state.dart'; |
import '../backend/suite.dart'; |
@@ -26,6 +28,9 @@ class Engine { |
/// Whether [close] has been called. |
var _closed = false; |
+ /// A pool that limits the number of test suites running concurrently. |
+ final Pool _pool; |
+ |
/// An unmodifiable list of tests to run. |
/// |
/// These are [LiveTest]s, representing the in-progress state of each test. |
@@ -33,7 +38,10 @@ class Engine { |
/// that have finished are marked [Status.complete]. |
/// |
/// [LiveTest.run] must not be called on these tests. |
- final List<LiveTest> liveTests; |
+ List<LiveTest> get liveTests => |
+ new UnmodifiableListView(flatten(_liveTestsBySuite)); |
+ |
+ final List<List<LiveTest>> _liveTestsBySuite; |
/// A stream that emits each [LiveTest] as it's about to start running. |
/// |
@@ -42,9 +50,10 @@ class Engine { |
final _onTestStartedController = new StreamController<LiveTest>.broadcast(); |
/// Creates an [Engine] that will run all tests in [suites]. |
- Engine(Iterable<Suite> suites) |
- : liveTests = new UnmodifiableListView(flatten(suites.map((suite) => |
- suite.tests.map((test) => test.load(suite))))); |
+ Engine(Iterable<Suite> suites, {int concurrency}) |
+ : _liveTestsBySuite = suites.map((suite) => |
+ suite.tests.map((test) => test.load(suite)).toList()).toList(), |
+ _pool = new Pool(concurrency == null ? 1 : concurrency); |
/// Runs all tests in all suites defined by this engine. |
/// |
@@ -56,16 +65,23 @@ class Engine { |
} |
_runCalled = true; |
- return Future.forEach(liveTests, (liveTest) { |
- if (_closed) return new Future.value(); |
- _onTestStartedController.add(liveTest); |
+ return Future.wait(_liveTestsBySuite.map((suite) { |
+ return _pool.withResource(() { |
+ if (_closed) return null; |
+ |
+ return Future.forEach(suite, (liveTest) { |
+ if (_closed) return new Future.value(); |
+ _onTestStartedController.add(liveTest); |
- // First, schedule a microtask to ensure that [onTestStarted] fires before |
- // the first [LiveTest.onStateChange] event. Once the test finishes, use |
- // [new Future] to do a coarse-grained event loop pump to avoid starving |
- // the DOM or other non-microtask events. |
- return new Future.microtask(liveTest.run).then((_) => new Future(() {})); |
- }).then((_) => |
+ // First, schedule a microtask to ensure that [onTestStarted] fires |
+ // before the first [LiveTest.onStateChange] event. Once the test |
+ // finishes, use [new Future] to do a coarse-grained event loop pump |
+ // to avoid starving the DOM or other non-microtask events. |
+ return new Future.microtask(liveTest.run) |
+ .then((_) => new Future(() {})); |
+ }); |
+ }); |
+ })).then((_) => |
liveTests.every((liveTest) => liveTest.state.result == Result.success)); |
} |