diff --git a/lib/src/frontend/retry.dart b/lib/src/frontend/retry.dart
new file mode 100644
index 0000000000000000000000000000000000000000..0c57f674d04727528a034dc014a9341616485cff
--- /dev/null
+++ b/lib/src/frontend/retry.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// An annotation for marking a test to be retried.
+///
+/// A test with retries enabled will be re-run if it fails for a reason
+/// other than [TestFailure].
+class Retry {
+  /// The number of times the test will be retried.
+  final int count;
+
+  /// Marks a test to be retried.
+  const Retry(this.count);
+}
diff --git a/lib/src/runner/compiler_pool.dart b/lib/src/runner/compiler_pool.dart
index 506aefa4d49b18e7637bc8cf6b8dcd4d551d750e..6a6b5e30f223dbe66fd129b132fd01b321c3726f 100644
--- a/lib/src/runner/compiler_pool.dart
+++ b/lib/src/runner/compiler_pool.dart
@@ -115,8 +115,8 @@ class CompilerPool {
     var map = jsonDecode(new File(mapPath).readAsStringSync());
     var root = map['sourceRoot'] as String;
 
-    map['sources'] = map['sources'].map((String source) {
-      var url = Uri.parse(root + source);
+    map['sources'] = map['sources'].map((source) {
+      var url = Uri.parse(root + '$source');
       if (url.scheme != '' && url.scheme != 'file') return source;
       if (url.path.endsWith("/runInBrowser.dart")) return "";
       return p.toUri(mapPath).resolveUri(url).toString();
diff --git a/lib/test.dart b/lib/test.dart
index 2c98dba209ee73ee1c6b7428f23dba0f51e63a6a..2712bd3ecc5533219ef51c02ce5b080cb26ef5d9 100644
--- a/lib/test.dart
+++ b/lib/test.dart
@@ -27,6 +27,7 @@ export 'src/frontend/future_matchers.dart';
 export 'src/frontend/on_platform.dart';
 export 'src/frontend/never_called.dart';
 export 'src/frontend/prints_matcher.dart';
+export 'src/frontend/retry.dart';
 export 'src/frontend/skip.dart';
 export 'src/frontend/spawn_hybrid.dart';
 export 'src/frontend/stream_matcher.dart';
diff --git a/test/runner/loader_test.dart b/test/runner/loader_test.dart
index 13eeae5db393bad75f64a44a873835c6e5802fdc..da093cb8f1292de2550e54c9277711988a24e227 100644
--- a/test/runner/loader_test.dart
+++ b/test/runner/loader_test.dart
@@ -5,6 +5,7 @@
 @TestOn("vm")
 
 import 'package:path/path.dart' as p;
+import 'package:test/src/runner/runner_suite.dart';
 import 'package:test_descriptor/test_descriptor.dart' as d;
 
 import 'package:test/src/backend/state.dart';
@@ -123,7 +124,8 @@ void main() {
       });
 
       test("can run tests in those suites", () {
-        var suite = suites.firstWhere((suite) => suite.path.contains("a_test"));
+        var suite = suites
+            .firstWhere((RunnerSuite suite) => suite.path.contains("a_test"));
         var liveTest = suite.group.entries[1].load(suite);
         expectSingleFailure(liveTest);
         return liveTest.run().whenComplete(() => liveTest.close());