[pigeon] Initial integration test setup (#2851)

* [pigeon] Initial integration test setup

This sets up initial proof-of-concept integration tests using the new
shared native test harness:
- Integration tests on the Dart side for void->void and
  Everything->Everything calls.
- macOS implementations in the test plugin on the native side.
- A new test target in the test script to drive them via `flutter test`.
- A minimal change to the example app so that `flutter run`-ing it will
  test that the void->void call is wired up.

Since this simple initial test hit
https://github.com/flutter/flutter/issues/111083, which caused the test
to fail, this includes a fix for that.

Short-term future work (by me):
- Add integration test native setup and script targets for the other
  generators. This includes one just to keep the initial review scope
  smaller.
- Update https://github.com/flutter/packages/pull/2816 to include the
  integration test since it's still blocked until I can address the CI
  issues.

Medium-term future work (not all by me):
- Remove the legacy iOS e2e test scaffold that is currently disabled.
- Add significantly more integration test coverage (likely including
  https://github.com/flutter/flutter/issues/115168 to reduce redundant
  API setup), including Flutter API integration tests rather than just
  host API tests.

Part of https://github.com/flutter/flutter/issues/111505
Fixes https://github.com/flutter/flutter/issues/111083

* Version bump for bugfix

* Check in generated files needed for analysis

* Add the actual integration test file, which was left out

* Address review comments

* Fix incorrect Swift unit test for void call fix

* Analysis ignore

* Autoformat
This commit is contained in:
stuartmorgan
2022-11-28 16:30:02 -05:00
committed by GitHub
parent 839447e525
commit ff16ee0b0a
14 changed files with 478 additions and 35 deletions

View File

@ -1,3 +1,7 @@
## 4.2.7
* [swift] Fixes a bug when calling methods that return `void`.
## 4.2.6
* Fixes bug with parsing documentation comments that start with '/'.

View File

@ -9,7 +9,7 @@ import 'dart:mirrors';
import 'ast.dart';
/// The current version of pigeon. This must match the version in pubspec.yaml.
const String pigeonVersion = '4.2.6';
const String pigeonVersion = '4.2.7';
/// Read all the content from [stdin] to a String.
String readStdin() {

View File

@ -232,7 +232,7 @@ void _writeHostApi(Indent indent, Api api, Root root) {
indent.write('$call ');
if (method.returnType.isVoid) {
indent.scoped('{', '}', () {
indent.writeln('reply(nil)');
indent.writeln('reply(wrapResult(nil))');
});
} else {
indent.scoped('{ result in', '}', () {
@ -242,7 +242,7 @@ void _writeHostApi(Indent indent, Api api, Root root) {
} else {
if (method.returnType.isVoid) {
indent.writeln(call);
indent.writeln('reply(nil)');
indent.writeln('reply(wrapResult(nil))');
} else {
indent.writeln('let result = $call');
indent.writeln('reply(wrapResult(result))');

View File

@ -0,0 +1,79 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(a14n): remove this import once Flutter 3.1 or later reaches stable (including flutter/flutter#104231)
// ignore: unnecessary_import
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:test_plugin/all_datatypes.gen.dart';
import 'package:test_plugin/all_void.gen.dart';
void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('Host API tests', () {
testWidgets('voidCallVoidReturn', (WidgetTester _) async {
final AllVoidHostApi api = AllVoidHostApi();
expect(api.doit(), completes);
});
testWidgets('allDataTypesEcho', (WidgetTester _) async {
final HostEverything api = HostEverything();
final Everything sentObject = Everything(
aBool: true,
anInt: 42,
aDouble: 3.14159,
aString: 'Hello host!',
aByteArray: Uint8List.fromList(<int>[1, 2, 3]),
a4ByteArray: Int32List.fromList(<int>[4, 5, 6]),
a8ByteArray: Int64List.fromList(<int>[7, 8, 9]),
aFloatArray: Float64List.fromList(<double>[2.71828, 3.14159]),
aList: <Object?>['Thing 1', 2],
aMap: <Object?, Object?>{'a': 1, 'b': 2.0},
nestedList: <List<bool>>[
<bool>[true, false],
<bool>[false, true]
],
);
final Everything echoObject = await api.echo(sentObject);
expect(echoObject.aBool, sentObject.aBool);
expect(echoObject.anInt, sentObject.anInt);
expect(echoObject.aDouble, sentObject.aDouble);
expect(echoObject.aString, sentObject.aString);
// TODO(stuartmorgan): Enable these once they work for all generators;
// currently at least Swift is broken.
// See https://github.com/flutter/flutter/issues/115906
//expect(echoObject.aByteArray, sentObject.aByteArray);
//expect(echoObject.a4ByteArray, sentObject.a4ByteArray);
//expect(echoObject.a8ByteArray, sentObject.a8ByteArray);
//expect(echoObject.aFloatArray, sentObject.aFloatArray);
expect(listEquals(echoObject.aList, sentObject.aList), true);
expect(mapEquals(echoObject.aMap, sentObject.aMap), true);
expect(echoObject.nestedList?.length, sentObject.nestedList?.length);
// TODO(stuartmorgan): Enable this once the Dart types are fixed; see
// https://github.com/flutter/flutter/issues/116117
//for (int i = 0; i < echoObject.nestedList!.length; i++) {
// expect(listEquals(echoObject.nestedList![i], sentObject.nestedList![i]),
// true);
//}
expect(
mapEquals(
echoObject.mapWithAnnotations, sentObject.mapWithAnnotations),
true);
expect(
mapEquals(echoObject.mapWithObject, sentObject.mapWithObject), true);
});
});
group('Flutter API tests', () {
// TODO(stuartmorgan): Add Flutter API tests, driven by wrapper host APIs
// that forward the arguments and return values in the opposite direction.
});
}

View File

@ -44,7 +44,7 @@ class AsyncHandlersTest: XCTestCase {
let expectation = XCTestExpectation(description: "voidvoid callback")
binaryMessenger.handlers[channelName]?(nil) { data in
let outputMap = binaryMessenger.codec.decode(data) as? [String: Any]
XCTAssertNil(outputMap?["result"])
XCTAssertEqual(outputMap?["result"] as! NSNull, NSNull())
XCTAssertNil(outputMap?["error"])
expectation.fulfill()
}

View File

@ -5,6 +5,7 @@
// ignore_for_file: public_member_api_docs
import 'package:flutter/material.dart';
import 'package:test_plugin/all_void.gen.dart';
import 'package:test_plugin/test_plugin.dart';
void main() {
@ -21,6 +22,8 @@ class MyApp extends StatefulWidget {
class _MyAppState extends State<MyApp> {
// ignore: unused_field
final TestPlugin _testPlugin = TestPlugin();
late final AllVoidHostApi api;
String status = 'Calling...';
@override
void initState() {
@ -29,9 +32,18 @@ class _MyAppState extends State<MyApp> {
}
Future<void> initPlatformState() async {
// TODO(tarrinneal): Call TestPlugin methods here for manual integration
// testing, once they exist. See
// https://github.com/flutter/flutter/issues/111505
api = AllVoidHostApi();
try {
await api.doit();
} catch (e) {
setState(() {
status = 'Failed: $e';
});
return;
}
setState(() {
status = 'Success!';
});
}
@override
@ -41,9 +53,8 @@ class _MyAppState extends State<MyApp> {
appBar: AppBar(
title: const Text('Pigeon integration tests'),
),
body: const Center(
child: Text(
'TODO, see https://github.com/flutter/flutter/issues/111505'),
body: Center(
child: Text(status),
),
),
);

View File

@ -14,6 +14,8 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
flutter:
uses-material-design: true

View File

@ -2,8 +2,7 @@
# changes on generated files. This will need a way to avoid unnecessary churn,
# such as a flag to suppress version stamp generation.
*.gen.dart
# TODO(stuartmorgan): Add exceptions for specific files that are used in
# integration tests, as they will need to be checked in to avoid analysis
# failures. The exclusion of other files is to prevent having multiple
# copies of all of the Dart output until more tests are restructured to
# minimize duplication.
# The following are files that are used in integration tests, which need to be
# checked in to avoid analysis failures.
!all_datatypes.gen.dart
!all_void.gen.dart

View File

@ -0,0 +1,245 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Autogenerated from Pigeon (v4.2.7), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
class Everything {
Everything({
this.aBool,
this.anInt,
this.aDouble,
this.aString,
this.aByteArray,
this.a4ByteArray,
this.a8ByteArray,
this.aFloatArray,
this.aList,
this.aMap,
this.nestedList,
this.mapWithAnnotations,
this.mapWithObject,
});
bool? aBool;
int? anInt;
double? aDouble;
String? aString;
Uint8List? aByteArray;
Int32List? a4ByteArray;
Int64List? a8ByteArray;
Float64List? aFloatArray;
List<Object?>? aList;
Map<Object?, Object?>? aMap;
List<List<bool?>?>? nestedList;
Map<String?, String?>? mapWithAnnotations;
Map<String?, Object?>? mapWithObject;
Object encode() {
final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
pigeonMap['aBool'] = aBool;
pigeonMap['anInt'] = anInt;
pigeonMap['aDouble'] = aDouble;
pigeonMap['aString'] = aString;
pigeonMap['aByteArray'] = aByteArray;
pigeonMap['a4ByteArray'] = a4ByteArray;
pigeonMap['a8ByteArray'] = a8ByteArray;
pigeonMap['aFloatArray'] = aFloatArray;
pigeonMap['aList'] = aList;
pigeonMap['aMap'] = aMap;
pigeonMap['nestedList'] = nestedList;
pigeonMap['mapWithAnnotations'] = mapWithAnnotations;
pigeonMap['mapWithObject'] = mapWithObject;
return pigeonMap;
}
static Everything decode(Object message) {
final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
return Everything(
aBool: pigeonMap['aBool'] as bool?,
anInt: pigeonMap['anInt'] as int?,
aDouble: pigeonMap['aDouble'] as double?,
aString: pigeonMap['aString'] as String?,
aByteArray: pigeonMap['aByteArray'] as Uint8List?,
a4ByteArray: pigeonMap['a4ByteArray'] as Int32List?,
a8ByteArray: pigeonMap['a8ByteArray'] as Int64List?,
aFloatArray: pigeonMap['aFloatArray'] as Float64List?,
aList: pigeonMap['aList'] as List<Object?>?,
aMap: pigeonMap['aMap'] as Map<Object?, Object?>?,
nestedList:
(pigeonMap['nestedList'] as List<Object?>?)?.cast<List<bool?>?>(),
mapWithAnnotations:
(pigeonMap['mapWithAnnotations'] as Map<Object?, Object?>?)
?.cast<String?, String?>(),
mapWithObject: (pigeonMap['mapWithObject'] as Map<Object?, Object?>?)
?.cast<String?, Object?>(),
);
}
}
class _HostEverythingCodec extends StandardMessageCodec {
const _HostEverythingCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is Everything) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return Everything.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
class HostEverything {
/// Constructor for [HostEverything]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
HostEverything({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
static const MessageCodec<Object?> codec = _HostEverythingCodec();
Future<Everything> giveMeEverything() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostEverything.giveMeEverything', codec,
binaryMessenger: _binaryMessenger);
final Map<Object?, Object?>? replyMap =
await channel.send(null) as Map<Object?, Object?>?;
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyMap['error'] != null) {
final Map<Object?, Object?> error =
(replyMap['error'] as Map<Object?, Object?>?)!;
throw PlatformException(
code: (error['code'] as String?)!,
message: error['message'] as String?,
details: error['details'],
);
} else if (replyMap['result'] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyMap['result'] as Everything?)!;
}
}
Future<Everything> echo(Everything arg_everything) async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.HostEverything.echo', codec,
binaryMessenger: _binaryMessenger);
final Map<Object?, Object?>? replyMap =
await channel.send(<Object?>[arg_everything]) as Map<Object?, Object?>?;
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyMap['error'] != null) {
final Map<Object?, Object?> error =
(replyMap['error'] as Map<Object?, Object?>?)!;
throw PlatformException(
code: (error['code'] as String?)!,
message: error['message'] as String?,
details: error['details'],
);
} else if (replyMap['result'] == null) {
throw PlatformException(
code: 'null-error',
message: 'Host platform returned null value for non-null return value.',
);
} else {
return (replyMap['result'] as Everything?)!;
}
}
}
class _FlutterEverythingCodec extends StandardMessageCodec {
const _FlutterEverythingCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is Everything) {
buffer.putUint8(128);
writeValue(buffer, value.encode());
} else {
super.writeValue(buffer, value);
}
}
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
return Everything.decode(readValue(buffer)!);
default:
return super.readValueOfType(type, buffer);
}
}
}
abstract class FlutterEverything {
static const MessageCodec<Object?> codec = _FlutterEverythingCodec();
Everything giveMeEverything();
Everything echo(Everything everything);
static void setup(FlutterEverything? api,
{BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterEverything.giveMeEverything', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
// ignore message
final Everything output = api.giveMeEverything();
return output;
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.FlutterEverything.echo', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.FlutterEverything.echo was null.');
final List<Object?> args = (message as List<Object?>?)!;
final Everything? arg_everything = (args[0] as Everything?);
assert(arg_everything != null,
'Argument for dev.flutter.pigeon.FlutterEverything.echo was null, expected non-null Everything.');
final Everything output = api.echo(arg_everything!);
return output;
});
}
}
}
}

View File

@ -0,0 +1,70 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Autogenerated from Pigeon (v4.2.7), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;
import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';
abstract class AllVoidFlutterApi {
static const MessageCodec<Object?> codec = StandardMessageCodec();
void doit();
static void setup(AllVoidFlutterApi? api,
{BinaryMessenger? binaryMessenger}) {
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.AllVoidFlutterApi.doit', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
// ignore message
api.doit();
return;
});
}
}
}
}
class AllVoidHostApi {
/// Constructor for [AllVoidHostApi]. The [binaryMessenger] named argument is
/// available for dependency injection. If it is left null, the default
/// BinaryMessenger will be used which routes to the host platform.
AllVoidHostApi({BinaryMessenger? binaryMessenger})
: _binaryMessenger = binaryMessenger;
final BinaryMessenger? _binaryMessenger;
static const MessageCodec<Object?> codec = StandardMessageCodec();
Future<void> doit() async {
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.AllVoidHostApi.doit', codec,
binaryMessenger: _binaryMessenger);
final Map<Object?, Object?>? replyMap =
await channel.send(null) as Map<Object?, Object?>?;
if (replyMap == null) {
throw PlatformException(
code: 'channel-error',
message: 'Unable to establish connection on channel.',
);
} else if (replyMap['error'] != null) {
final Map<Object?, Object?> error =
(replyMap['error'] as Map<Object?, Object?>?)!;
throw PlatformException(
code: (error['code'] as String?)!,
message: error['message'] as String?,
details: error['details'],
);
} else {
return;
}
}
}

View File

@ -6,14 +6,30 @@ import Cocoa
import FlutterMacOS
/**
* This plugin is currently a no-op since only unit tests have been set up.
* In the future, this will register Pigeon APIs used in integration tests.
* This plugin handles the native side of the integration tests in
* example/integration_test/.
*/
public class TestPlugin: NSObject, FlutterPlugin {
public class TestPlugin: NSObject, FlutterPlugin, AllVoidHostApi, HostEverything {
public static func register(with registrar: FlutterPluginRegistrar) {
let plugin = TestPlugin()
AllVoidHostApiSetup.setUp(binaryMessenger: registrar.messenger, api: plugin)
HostEverythingSetup.setUp(binaryMessenger: registrar.messenger, api: plugin)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
result(FlutterMethodNotImplemented)
// MARK: AllVoidHostApi implementation
func doit() {
// No-op
}
// MARK: HostEverything implementation
func giveMeEverything() -> Everything {
// Currently unused in integration tests, so just return an empty object.
return Everything()
}
func echo(everything: Everything) -> Everything {
return everything
}
}

View File

@ -2,7 +2,7 @@ name: pigeon
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
repository: https://github.com/flutter/packages/tree/main/packages/pigeon
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon
version: 4.2.6 # This must match the version in lib/generator_tools.dart
version: 4.2.7 # This must match the version in lib/generator_tools.dart
environment:
sdk: ">=2.12.0 <3.0.0"

View File

@ -166,7 +166,11 @@ run_ios_swift_unittests() {
}
run_macos_swift_unittests() {
dart run tool/run_tests.dart -t mac_swift_unittests --skip-generation
dart run tool/run_tests.dart -t macos_swift_unittests --skip-generation
}
run_macos_swift_e2e_tests() {
dart run tool/run_tests.dart -t macos_swift_integration_tests --skip-generation
}
run_android_kotlin_unittests() {
@ -255,6 +259,7 @@ should_run_ios_unittests=true
should_run_ios_swift_unittests=true
should_run_mock_handler_tests=true
should_run_macos_swift_unittests=true
should_run_macos_swift_e2e_tests=true
should_run_android_kotlin_unittests=true
while getopts "t:l?h" opt; do
case $opt in
@ -268,6 +273,7 @@ while getopts "t:l?h" opt; do
should_run_ios_swift_unittests=false
should_run_mock_handler_tests=false
should_run_macos_swift_unittests=false
should_run_macos_swift_e2e_tests=false
should_run_android_kotlin_unittests=false
case $OPTARG in
# TODO(stuartmorgan): Rename to include "java".
@ -281,6 +287,7 @@ while getopts "t:l?h" opt; do
ios_swift_unittests) should_run_ios_swift_unittests=true ;;
mock_handler_tests) should_run_mock_handler_tests=true ;;
macos_swift_unittests) should_run_macos_swift_unittests=true ;;
macos_swift_e2e_tests) should_run_macos_swift_e2e_tests=true ;;
android_kotlin_unittests) should_run_android_kotlin_unittests=true ;;
*)
echo "unrecognized test: $OPTARG"
@ -300,6 +307,7 @@ while getopts "t:l?h" opt; do
ios_swift_unittests - Unit tests on generated Swift code.
mock_handler_tests - Unit tests on generated Dart mock handler code.
macos_swift_unittests - Unit tests on generated Swift code on macOS.
macos_swift_e2e_tests - Integration tests on generated Swift code on macOS.
"
exit 1
;;
@ -356,6 +364,9 @@ fi
if [ "$should_run_macos_swift_unittests" = true ]; then
run_macos_swift_unittests
fi
if [ "$should_run_macos_swift_e2e_tests" = true ]; then
run_macos_swift_e2e_tests
fi
if [ "$should_run_android_kotlin_unittests" = true ]; then
run_android_kotlin_unittests
fi

View File

@ -24,7 +24,8 @@ const String _testFlag = 'test';
const String _listFlag = 'list';
const String _skipGenerationFlag = 'skip-generation';
const String testPluginRelativePath = 'platform_tests/test_plugin';
const String _testPluginRelativePath = 'platform_tests/test_plugin';
const String _integrationTestFileRelativePath = 'integration_test/test.dart';
@immutable
class _TestInfo {
@ -52,18 +53,18 @@ const Map<String, _TestInfo> _tests = <String, _TestInfo>{
'flutter_unittests': _TestInfo(
function: _runFlutterUnitTests,
description: 'Unit tests on generated Dart code.'),
'ios_e2e_tests': _TestInfo(
function: _runIosE2eTests,
description: 'End-to-end Objective-C tests run on iOS Simulator'),
'ios_unittests': _TestInfo(
function: _runIosUnitTests,
description: 'Unit tests on generated Objective-C code.'),
'ios_swift_unittests': _TestInfo(
function: _runIosSwiftUnitTests,
description: 'Unit tests on generated Swift code.'),
'mac_swift_unittests': _TestInfo(
'macos_swift_unittests': _TestInfo(
function: _runMacOSSwiftUnitTests,
description: 'Unit tests on generated Swift code on macOS.'),
'macos_swift_integration_tests': _TestInfo(
function: _runMacOSSwiftIntegrationTests,
description: 'Integration tests on generated Swift code on macOS.'),
'mock_handler_tests': _TestInfo(
function: _runMockHandlerTests,
description: 'Unit tests on generated Dart mock handler code.'),
@ -74,7 +75,7 @@ Future<int> _runAndroidUnitTests() async {
}
Future<int> _runAndroidKotlinUnitTests() async {
const String examplePath = './$testPluginRelativePath/example';
const String examplePath = './$_testPluginRelativePath/example';
const String androidProjectPath = '$examplePath/android';
final File gradleFile = File(p.join(androidProjectPath, 'gradlew'));
if (!gradleFile.existsSync()) {
@ -179,16 +180,12 @@ Future<int> _runFlutterUnitTests() async {
return 0;
}
Future<int> _runIosE2eTests() async {
throw UnimplementedError('See run_tests.sh.');
}
Future<int> _runIosUnitTests() async {
throw UnimplementedError('See run_tests.sh.');
}
Future<int> _runMacOSSwiftUnitTests() async {
const String examplePath = './$testPluginRelativePath/example';
const String examplePath = './$_testPluginRelativePath/example';
final int compileCode = await runFlutterBuild(examplePath, 'macos');
if (compileCode != 0) {
return compileCode;
@ -200,8 +197,17 @@ Future<int> _runMacOSSwiftUnitTests() async {
);
}
Future<int> _runMacOSSwiftIntegrationTests() async {
const String examplePath = './$_testPluginRelativePath/example';
return runFlutterCommand(
examplePath,
'test',
<String>[_integrationTestFileRelativePath, '-d', 'macos'],
);
}
Future<int> _runIosSwiftUnitTests() async {
const String examplePath = './$testPluginRelativePath/example';
const String examplePath = './$_testPluginRelativePath/example';
final int compileCode = await runFlutterBuild(
examplePath,
'ios',
@ -238,7 +244,7 @@ Future<int> _runMockHandlerTests() async {
}
Future<int> _runWindowsUnitTests() async {
const String examplePath = './$testPluginRelativePath/example';
const String examplePath = './$_testPluginRelativePath/example';
final int compileCode = await runFlutterBuild(examplePath, 'windows');
if (compileCode != 0) {
return compileCode;