Commit b9f49a40 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Handle missing flutter_test dependency cleanly (#7421)

We now produce a more reasonable error message when we're missing the
flutter_test dependency in a test. Also, remove the flutter_tools stack traces
when the engine dies.

Fixes #6187
parent 2155fb74
.atom
.DS_Store
.buildlog
.idea
.packages
.pub/
build/
packages
pubspec.lock
name: missing_dependency_tests
dependencies:
flutter:
sdk: flutter
<<skip until matching line>>
<<stderr>>
<<skip until matching line>>
Failed to load test harness\. +Are you missing a dependency on flutter_test\?
\ No newline at end of file
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:test/test.dart';
void main() {
test('Trival test', () {
expect(42, 42);
});
}
......@@ -105,7 +105,7 @@ class FlutterPlatform extends PlatformPlugin {
subprocessActive = false;
if (!controllerSinkClosed && exitCode != 0) {
String message = _getErrorMessage(_getExitCodeMessage(exitCode, 'after tests finished'), testPath, shellPath);
controller.sink.addError(new Exception(message));
controller.sink.addError(message);
}
});
......@@ -127,13 +127,13 @@ class FlutterPlatform extends PlatformPlugin {
case _InitialResult.crashed:
int exitCode = await process.exitCode;
String message = _getErrorMessage(_getExitCodeMessage(exitCode, 'before connecting to test harness'), testPath, shellPath);
controller.sink.addError(new Exception(message));
controller.sink.addError(message);
controller.sink.close();
await controller.sink.done;
break;
case _InitialResult.timedOut:
String message = _getErrorMessage('Test never connected to test harness.', testPath, shellPath);
controller.sink.addError(new Exception(message));
controller.sink.addError(message);
controller.sink.close();
await controller.sink.done;
break;
......@@ -169,7 +169,7 @@ class FlutterPlatform extends PlatformPlugin {
int exitCode = await process.exitCode;
subprocessActive = false;
String message = _getErrorMessage(_getExitCodeMessage(exitCode, 'before test harness closed its WebSocket'), testPath, shellPath);
controller.sink.addError(new Exception(message));
controller.sink.addError(message);
controller.sink.close();
await controller.sink.done;
break;
......@@ -214,8 +214,12 @@ class FlutterPlatform extends PlatformPlugin {
import 'dart:convert';
import 'dart:io'; // ignore: dart_io_import
import 'package:stream_channel/stream_channel.dart';
// We import this library first in order to trigger an import error for
// package:test (rather than package:stream_channel) when the developer forgets
// to add a dependency on package:test.
import 'package:test/src/runner/plugin/remote_platform_helpers.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test/src/runner/vm/catch_isolate_errors.dart';
import '$testUrl' as test;
......@@ -285,7 +289,9 @@ void main() {
stream.transform(UTF8.decoder)
.transform(const LineSplitter())
.listen((String line) {
if (line != null)
if (line.startsWith('error: Unable to read Dart source \'package:test/'))
printError('\n\nFailed to load test harness. Are you missing a dependency on flutter_test?\n');
else if (line != null)
printStatus('Shell: $line');
});
}
......
......@@ -17,23 +17,30 @@ import 'src/context.dart';
void main() {
group('test', () {
final String automatedTestsDirectory = path.join('..', '..', 'dev', 'automated_tests');
final String flutterTestDirectory = path.join(automatedTestsDirectory, 'flutter_test');
testUsingContext('TestAsyncUtils guarded function test', () async {
Cache.flutterRoot = '../..';
return _testFile('test_async_utils_guarded', 1);
return _testFile('test_async_utils_guarded', 1, automatedTestsDirectory, flutterTestDirectory);
});
testUsingContext('TestAsyncUtils unguarded function test', () async {
Cache.flutterRoot = '../..';
return _testFile('test_async_utils_unguarded', 1);
return _testFile('test_async_utils_unguarded', 1, automatedTestsDirectory, flutterTestDirectory);
});
testUsingContext('Missing flutter_test dependency', () async {
final String missingDependencyTests = path.join('..', '..', 'dev', 'missing_dependency_tests');
Cache.flutterRoot = '../..';
return _testFile('trivial', 1, missingDependencyTests, missingDependencyTests);
});
}, timeout: new Timeout(const Duration(seconds: 5)));
}
Future<Null> _testFile(String testName, int wantedExitCode) async {
final String manualTestsDirectory = path.join('..', '..', 'dev', 'automated_tests');
final String fullTestName = path.join(manualTestsDirectory, 'flutter_test', '${testName}_test.dart');
Future<Null> _testFile(String testName, int wantedExitCode, String workingDirectory, String testDirectory) async {
final String fullTestName = path.join(testDirectory, '${testName}_test.dart');
final File testFile = fs.file(fullTestName);
expect(testFile.existsSync(), true);
final String fullTestExpectation = path.join(manualTestsDirectory, 'flutter_test', '${testName}_expectation.txt');
final String fullTestExpectation = path.join(testDirectory, '${testName}_expectation.txt');
final File expectationFile = fs.file(fullTestExpectation);
expect(expectationFile.existsSync(), true);
final ProcessResult exec = await Process.run(
......@@ -44,14 +51,17 @@ Future<Null> _testFile(String testName, int wantedExitCode) async {
'--no-color',
fullTestName
],
workingDirectory: manualTestsDirectory
workingDirectory: workingDirectory
);
expect(exec.exitCode, wantedExitCode);
final List<String> output = exec.stdout.split('\n');
output.add('<<stderr>>');
output.addAll(exec.stderr.split('\n'));
final List<String> expectations = fs.file(fullTestExpectation).readAsLinesSync();
bool allowSkip = false;
int expectationLineNumber = 0;
int outputLineNumber = 0;
bool haveSeenStdErrMarker = false;
while (expectationLineNumber < expectations.length) {
expect(output, hasLength(greaterThan(outputLineNumber)));
final String expectationLine = expectations[expectationLineNumber];
......@@ -68,10 +78,15 @@ Future<Null> _testFile(String testName, int wantedExitCode) async {
}
allowSkip = false;
}
if (expectationLine == '<<stderr>>') {
expect(haveSeenStdErrMarker, isFalse);
haveSeenStdErrMarker = true;
}
expect(outputLine, matches(expectationLine));
expectationLineNumber += 1;
outputLineNumber += 1;
}
expect(allowSkip, isFalse);
expect(exec.stderr, '');
if (!haveSeenStdErrMarker)
expect(exec.stderr, '');
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment