diff --git a/.analysis_options b/.analysis_options
index a10d4c5a05c981eb3b5a454f1af297abfdf18b18..32fe5bc60d6a8facc7f56aa336a4e5a35c6a43f5 100644
--- a/.analysis_options
+++ b/.analysis_options
@@ -1,2 +1,4 @@
 analyzer:
   strong-mode: true
+  exclude:
+    - test/**/*.dart
diff --git a/lib/src/runner/browser/content_shell.dart b/lib/src/runner/browser/content_shell.dart
index 35908dcf8532779d596f5741a3d4d6920227f8fe..c3002404b523018bbb59a86027f573efe68f78bb 100644
--- a/lib/src/runner/browser/content_shell.dart
+++ b/lib/src/runner/browser/content_shell.dart
@@ -105,7 +105,7 @@ class ContentShell extends Browser {
       var client = new HttpClient();
       var request = await client.getUrl(base.resolve("/json/list"));
       var response = await request.close();
-      var json = await JSON.fuse(UTF8).decoder.bind(response).single;
+      var json = await JSON.fuse(UTF8).decoder.bind(response).single as List;
       return base.resolve(json.first["devtoolsFrontendUrl"]);
     } catch (_) {
       // If we fail to talk to the remote debugger protocol, give up and return
diff --git a/lib/src/runner/loader.dart b/lib/src/runner/loader.dart
index 67c2835f282aaeff308c15ca7f06c96cc87415bb..9f74b952355158f78cb0c17b717e3c4498fae7d3 100644
--- a/lib/src/runner/loader.dart
+++ b/lib/src/runner/loader.dart
@@ -30,9 +30,6 @@ class Loader {
   /// The test runner configuration.
   final Configuration _config;
 
-  /// The root directory that will be served for browser tests.
-  final String _root;
-
   /// All suites that have been created by the loader.
   final _suites = new Set<RunnerSuite>();
 
@@ -48,8 +45,7 @@ class Loader {
   ///
   /// [root] is the root directory that will be served for browser tests. It
   /// defaults to the working directory.
-  Loader(this._config, {String root})
-      : _root = root == null ? p.current : root {
+  Loader(this._config, {String root}) {
     registerPlatformPlugin([TestPlatform.vm], () => new VMPlatform(_config));
     registerPlatformPlugin([
       TestPlatform.dartium,
diff --git a/lib/src/util/io.dart b/lib/src/util/io.dart
index 59638dccba37b0bcb2e2d7986301c53af5532159..4ede6045862efb5b7121e6b87b4f092d96d6ca34 100644
--- a/lib/src/util/io.dart
+++ b/lib/src/util/io.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:io';
 import 'dart:mirrors';
 
@@ -39,8 +38,7 @@ final OperatingSystem currentOS = (() {
 })();
 
 /// A queue of lines of standard input.
-final stdinLines = new StreamQueue(
-    UTF8.decoder.fuse(const LineSplitter()).bind(stdin));
+final stdinLines = new StreamQueue(lineSplitter.bind(stdin));
 
 /// Whether this is being run as a subprocess in the test package's own tests.
 bool inTestTests = Platform.environment["_DART_TEST_TESTING"] == "true";
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index bc5a2701e9dbe16aff2b2c337f36061191cf9f71..e31e284801ebe0944a35ad7224e31b5a08d4fab0 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -27,8 +27,12 @@ typedef AsyncFunction();
 /// A typedef for a zero-argument callback function.
 typedef void Callback();
 
-/// A converter that decodes bytes using UTF-8 and splits them on newlines.
-final lineSplitter = UTF8.decoder.fuse(const LineSplitter());
+/// A transformer that decodes bytes using UTF-8 and splits them on newlines.
+final lineSplitter = new StreamTransformer<List<int>, String>(
+    (stream, cancelOnError) => stream
+        .transform(UTF8.decoder)
+        .transform(const LineSplitter())
+        .listen(null, cancelOnError: cancelOnError));
 
 /// A regular expression to match the exception prefix that some exceptions'
 /// [Object.toString] values contain.
diff --git a/test/io.dart b/test/io.dart
index 00bb3e0c12bf801fd3ab5a5e59ad6babd7bbf560..b89e40cb90916bcf5f8b41d6fe663dc5262114ae 100644
--- a/test/io.dart
+++ b/test/io.dart
@@ -7,7 +7,6 @@
 library test.test.io;
 
 import 'dart:async';
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
@@ -16,7 +15,6 @@ import 'package:scheduled_test/scheduled_process.dart';
 import 'package:scheduled_test/scheduled_stream.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 import 'package:test/src/util/io.dart';
-import 'package:yaml/yaml.dart';
 
 /// The path to the root directory of the `test` package.
 final String packageDir = p.dirname(p.dirname(libraryPath(#test.test.io)));
@@ -104,7 +102,7 @@ StreamMatcher containsInOrder(Iterable<String> strings) =>
 ///
 /// If [forwardStdio] is true, the standard output and error from the process
 /// will be printed as part of the parent test. This is used for debugging.
-ScheduledProcess runTest(List args, {String reporter,
+ScheduledProcess runTest(List<String> args, {String reporter,
     int concurrency, Map<String, String> environment,
     bool forwardStdio: false}) {
   concurrency ??= 1;
@@ -133,7 +131,7 @@ ScheduledProcess runTest(List args, {String reporter,
 }
 
 /// Runs Dart.
-ScheduledProcess runDart(List args, {Map<String, String> environment,
+ScheduledProcess runDart(List<String> args, {Map<String, String> environment,
     String description}) {
   var allArgs = Platform.executableArguments.map((arg) {
     // The package root might be relative, so we need to make it absolute if
@@ -163,7 +161,7 @@ ScheduledProcess runPub(List args, {Map<String, String> environment}) {
 ///
 /// This returns assigns [_pubServePort] to a future that will complete to the
 /// port of the "pub serve" instance.
-ScheduledProcess runPubServe({List args, String workingDirectory,
+ScheduledProcess runPubServe({List<String> args, String workingDirectory,
     Map<String, String> environment}) {
   _pubServePortCompleter = new Completer();
   currentSchedule.onComplete.schedule(() => _pubServePortCompleter = null);