From 34d06fd6db8995e4837d49038ec9dbd9f324b97b Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Sep 2019 08:27:09 -0700 Subject: [PATCH 1/3] Support for running tests with Flutter driver --- packages/instrumentation_adapter/CHANGELOG.md | 4 +++ packages/instrumentation_adapter/README.md | 12 +++++++ .../lib/instrumentation_adapter.dart | 36 +++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/packages/instrumentation_adapter/CHANGELOG.md b/packages/instrumentation_adapter/CHANGELOG.md index 73557c5c704a..e3e890b30c23 100644 --- a/packages/instrumentation_adapter/CHANGELOG.md +++ b/packages/instrumentation_adapter/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.2 + +* Added support for running tests using Flutter driver. + ## 0.1.1 * Updates about using *androidx* library. diff --git a/packages/instrumentation_adapter/README.md b/packages/instrumentation_adapter/README.md index 81f515569ac5..b2dad9798593 100644 --- a/packages/instrumentation_adapter/README.md +++ b/packages/instrumentation_adapter/README.md @@ -90,3 +90,15 @@ gcloud firebase test android run --type instrumentation \ --results-bucket= \ --results-dir= ``` + +## Flutter driver support + +`InstrumentationAdapterFlutterBinding` also reports test results to `FlutterDriver` +when run on the command line via `flutter drive`. + +```dart + final FlutterDriver driver = await FlutterDriver.connect(); + final String result = await driver.requestData(null, timeout: const Duration(minutes: 1)); + driver.close(); + exit(result == 'pass' ? 0 : 1); +``` diff --git a/packages/instrumentation_adapter/lib/instrumentation_adapter.dart b/packages/instrumentation_adapter/lib/instrumentation_adapter.dart index 81f81872d950..c9f35bfa5521 100644 --- a/packages/instrumentation_adapter/lib/instrumentation_adapter.dart +++ b/packages/instrumentation_adapter/lib/instrumentation_adapter.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; @@ -16,9 +17,13 @@ class InstrumentationAdapterFlutterBinding tearDownAll(() async { await _channel.invokeMethod( 'allTestsFinished', {'results': _results}); + if (!_allTestsPassed.isCompleted) + _allTestsPassed.complete(true); }); } + final Completer _allTestsPassed = Completer(); + static WidgetsBinding ensureInitialized() { if (WidgetsBinding.instance == null) { InstrumentationAdapterFlutterBinding(); @@ -32,14 +37,45 @@ class InstrumentationAdapterFlutterBinding static Map _results = {}; + // Emulates the Flutter driver extension, returning 'pass' or 'fail'. + @override + void initServiceExtensions() { + super.initServiceExtensions(); + Future> callback(Map params) async { + final String command = params['command']; + Map response; + switch (command) { + case 'request_data': + final bool allTestsPassed = await _allTestsPassed.future; + response = { + 'message': allTestsPassed ? 'pass' : 'fail', + }; + break; + case 'get_health': + response = { 'status': 'ok' }; + break; + default: + throw UnimplementedError('$command is not implemented'); + } + return { + 'isError' : false, + 'response': response, + }; + } + registerServiceExtension(name: 'driver', callback: callback); + } + @override Future runTest(Future testBody(), VoidCallback invariantTester, {String description = '', Duration timeout}) async { // TODO(jackson): Report the results individually instead of all at once // See https://github.com/flutter/flutter/issues/38985 + TestExceptionReporter valueBeforeTest = reportTestException; reportTestException = (FlutterErrorDetails details, String testDescription) { _results[description] = 'failed'; + _allTestsPassed.complete(false); + valueBeforeTest(details, testDescription); }; await super.runTest(testBody, invariantTester, description: description, timeout: timeout); From cc1c6d8ef8cbe63ad2c72fb40ff77e899f5bbf25 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Sep 2019 08:16:29 -0700 Subject: [PATCH 2/3] Fix analyzer issues --- .../instrumentation_adapter/lib/instrumentation_adapter.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/instrumentation_adapter/lib/instrumentation_adapter.dart b/packages/instrumentation_adapter/lib/instrumentation_adapter.dart index c9f35bfa5521..51891f4af56c 100644 --- a/packages/instrumentation_adapter/lib/instrumentation_adapter.dart +++ b/packages/instrumentation_adapter/lib/instrumentation_adapter.dart @@ -70,7 +70,7 @@ class InstrumentationAdapterFlutterBinding {String description = '', Duration timeout}) async { // TODO(jackson): Report the results individually instead of all at once // See https://github.com/flutter/flutter/issues/38985 - TestExceptionReporter valueBeforeTest = reportTestException; + final TestExceptionReporter valueBeforeTest = reportTestException; reportTestException = (FlutterErrorDetails details, String testDescription) { _results[description] = 'failed'; From 04adbcd04f24255205dcbb964b123b15260d5bc2 Mon Sep 17 00:00:00 2001 From: Collin Jackson Date: Mon, 9 Sep 2019 08:42:42 -0700 Subject: [PATCH 3/3] Reformat --- .../lib/instrumentation_adapter.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/instrumentation_adapter/lib/instrumentation_adapter.dart b/packages/instrumentation_adapter/lib/instrumentation_adapter.dart index 51891f4af56c..2ec16c4ebe56 100644 --- a/packages/instrumentation_adapter/lib/instrumentation_adapter.dart +++ b/packages/instrumentation_adapter/lib/instrumentation_adapter.dart @@ -17,8 +17,7 @@ class InstrumentationAdapterFlutterBinding tearDownAll(() async { await _channel.invokeMethod( 'allTestsFinished', {'results': _results}); - if (!_allTestsPassed.isCompleted) - _allTestsPassed.complete(true); + if (!_allTestsPassed.isCompleted) _allTestsPassed.complete(true); }); } @@ -52,16 +51,17 @@ class InstrumentationAdapterFlutterBinding }; break; case 'get_health': - response = { 'status': 'ok' }; + response = {'status': 'ok'}; break; default: throw UnimplementedError('$command is not implemented'); } - return { - 'isError' : false, + return { + 'isError': false, 'response': response, }; } + registerServiceExtension(name: 'driver', callback: callback); }