| // 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. |
| |
| import 'package:args/command_runner.dart'; |
| import 'package:file/file.dart'; |
| import 'package:file/memory.dart'; |
| import 'package:flutter_plugin_tools/src/common/core.dart'; |
| import 'package:flutter_plugin_tools/src/common/file_utils.dart'; |
| import 'package:flutter_plugin_tools/src/firebase_test_lab_command.dart'; |
| import 'package:path/path.dart' as p; |
| import 'package:test/test.dart'; |
| |
| import 'mocks.dart'; |
| import 'util.dart'; |
| |
| void main() { |
| group('FirebaseTestLabCommand', () { |
| FileSystem fileSystem; |
| late MockPlatform mockPlatform; |
| late Directory packagesDir; |
| late CommandRunner<void> runner; |
| late RecordingProcessRunner processRunner; |
| |
| setUp(() { |
| fileSystem = MemoryFileSystem(); |
| mockPlatform = MockPlatform(); |
| packagesDir = createPackagesDirectory(fileSystem: fileSystem); |
| processRunner = RecordingProcessRunner(); |
| final FirebaseTestLabCommand command = FirebaseTestLabCommand( |
| packagesDir, |
| processRunner: processRunner, |
| platform: mockPlatform, |
| ); |
| |
| runner = CommandRunner<void>( |
| 'firebase_test_lab_command', 'Test for $FirebaseTestLabCommand'); |
| runner.addCommand(command); |
| }); |
| |
| void writeJavaTestFile(RepositoryPackage plugin, String relativeFilePath, |
| {String runnerClass = 'FlutterTestRunner'}) { |
| childFileWithSubcomponents( |
| plugin.directory, p.posix.split(relativeFilePath)) |
| .writeAsStringSync(''' |
| @DartIntegrationTest |
| @RunWith($runnerClass.class) |
| public class MainActivityTest { |
| @Rule |
| public ActivityTestRule<FlutterActivity> rule = new ActivityTestRule<>(FlutterActivity.class); |
| } |
| '''); |
| } |
| |
| test('fails if gcloud auth fails', () async { |
| processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[ |
| FakeProcessInfo(MockProcess(exitCode: 1), <String>['auth']) |
| ]; |
| |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--service-key=/path/to/key', |
| ], errorHandler: (Error e) { |
| commandError = e; |
| }); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Unable to activate gcloud account.'), |
| ])); |
| }); |
| |
| test('retries gcloud set', () async { |
| processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[ |
| FakeProcessInfo(MockProcess(), <String>['auth']), |
| FakeProcessInfo(MockProcess(exitCode: 1), <String>['config']), |
| ]; |
| |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--service-key=/path/to/key', |
| '--project=a-project' |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains( |
| 'Warning: gcloud config set returned a non-zero exit code. Continuing anyway.'), |
| ])); |
| }); |
| |
| test('only runs gcloud configuration once', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin1 = |
| createFakePlugin('plugin1', packagesDir, extraFiles: <String>[ |
| 'test/plugin_test.dart', |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin1, javaTestFileRelativePath); |
| final RepositoryPackage plugin2 = |
| createFakePlugin('plugin2', packagesDir, extraFiles: <String>[ |
| 'test/plugin_test.dart', |
| 'example/integration_test/bar_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin2, javaTestFileRelativePath); |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--project=a-project', |
| '--service-key=/path/to/key', |
| '--device', |
| 'model=redfin,version=30', |
| '--device', |
| 'model=seoul,version=26', |
| '--test-run-id', |
| 'testRunId', |
| '--build-id', |
| 'buildId', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for plugin1'), |
| contains('Firebase project configured.'), |
| contains('Testing example/integration_test/foo_test.dart...'), |
| contains('Running for plugin2'), |
| contains('Testing example/integration_test/bar_test.dart...'), |
| ]), |
| ); |
| |
| expect( |
| processRunner.recordedCalls, |
| orderedEquals(<ProcessCall>[ |
| ProcessCall( |
| 'gcloud', |
| 'auth activate-service-account --key-file=/path/to/key' |
| .split(' '), |
| null), |
| ProcessCall( |
| 'gcloud', 'config set project a-project'.split(' '), null), |
| ProcessCall( |
| '/packages/plugin1/example/android/gradlew', |
| 'app:assembleAndroidTest -Pverbose=true'.split(' '), |
| '/packages/plugin1/example/android'), |
| ProcessCall( |
| '/packages/plugin1/example/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin1/example/integration_test/foo_test.dart' |
| .split(' '), |
| '/packages/plugin1/example/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin1/buildId/testRunId/example/0/ --device model=redfin,version=30 --device model=seoul,version=26' |
| .split(' '), |
| '/packages/plugin1/example'), |
| ProcessCall( |
| '/packages/plugin2/example/android/gradlew', |
| 'app:assembleAndroidTest -Pverbose=true'.split(' '), |
| '/packages/plugin2/example/android'), |
| ProcessCall( |
| '/packages/plugin2/example/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin2/example/integration_test/bar_test.dart' |
| .split(' '), |
| '/packages/plugin2/example/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin2/buildId/testRunId/example/0/ --device model=redfin,version=30 --device model=seoul,version=26' |
| .split(' '), |
| '/packages/plugin2/example'), |
| ]), |
| ); |
| }); |
| |
| test('runs integration tests', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'test/plugin_test.dart', |
| 'example/integration_test/bar_test.dart', |
| 'example/integration_test/foo_test.dart', |
| 'example/integration_test/should_not_run.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| '--device', |
| 'model=seoul,version=26', |
| '--test-run-id', |
| 'testRunId', |
| '--build-id', |
| 'buildId', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for plugin'), |
| contains('Testing example/integration_test/bar_test.dart...'), |
| contains('Testing example/integration_test/foo_test.dart...'), |
| ]), |
| ); |
| expect(output, isNot(contains('test/plugin_test.dart'))); |
| expect(output, |
| isNot(contains('example/integration_test/should_not_run.dart'))); |
| |
| expect( |
| processRunner.recordedCalls, |
| orderedEquals(<ProcessCall>[ |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleAndroidTest -Pverbose=true'.split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/bar_test.dart' |
| .split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30 --device model=seoul,version=26' |
| .split(' '), |
| '/packages/plugin/example'), |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart' |
| .split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin/buildId/testRunId/example/1/ --device model=redfin,version=30 --device model=seoul,version=26' |
| .split(' '), |
| '/packages/plugin/example'), |
| ]), |
| ); |
| }); |
| |
| test('runs for all examples', () async { |
| const List<String> examples = <String>['example1', 'example2']; |
| const String javaTestFileExampleRelativePath = |
| 'android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir, |
| examples: examples, |
| extraFiles: <String>[ |
| for (final String example in examples) ...<String>[ |
| 'example/$example/integration_test/a_test.dart', |
| 'example/$example/android/gradlew', |
| 'example/$example/$javaTestFileExampleRelativePath', |
| ], |
| ]); |
| for (final String example in examples) { |
| writeJavaTestFile( |
| plugin, 'example/$example/$javaTestFileExampleRelativePath'); |
| } |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| '--device', |
| 'model=seoul,version=26', |
| '--test-run-id', |
| 'testRunId', |
| '--build-id', |
| 'buildId', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Testing example/example1/integration_test/a_test.dart...'), |
| contains('Testing example/example2/integration_test/a_test.dart...'), |
| ]), |
| ); |
| |
| expect( |
| processRunner.recordedCalls, |
| containsAll(<ProcessCall>[ |
| ProcessCall( |
| '/packages/plugin/example/example1/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/example1/integration_test/a_test.dart' |
| .split(' '), |
| '/packages/plugin/example/example1/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin/buildId/testRunId/example1/0/ --device model=redfin,version=30 --device model=seoul,version=26' |
| .split(' '), |
| '/packages/plugin/example/example1'), |
| ProcessCall( |
| '/packages/plugin/example/example2/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/example2/integration_test/a_test.dart' |
| .split(' '), |
| '/packages/plugin/example/example2/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin/buildId/testRunId/example2/0/ --device model=redfin,version=30 --device model=seoul,version=26' |
| .split(' '), |
| '/packages/plugin/example/example2'), |
| ]), |
| ); |
| }); |
| |
| test('fails if a test fails twice', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/bar_test.dart', |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[ |
| FakeProcessInfo(MockProcess(exitCode: 1), |
| <String>['firebase', 'test']), // integration test #1 |
| FakeProcessInfo(MockProcess(exitCode: 1), |
| <String>['firebase', 'test']), // integration test #1 retry |
| FakeProcessInfo( |
| MockProcess(), <String>['firebase', 'test']), // integration test #2 |
| ]; |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Testing example/integration_test/bar_test.dart...'), |
| contains('Testing example/integration_test/foo_test.dart...'), |
| contains('plugin:\n' |
| ' example/integration_test/bar_test.dart failed tests'), |
| ]), |
| ); |
| }); |
| |
| test('passes with warning if a test fails once, then passes on retry', |
| () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/bar_test.dart', |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| processRunner.mockProcessesForExecutable['gcloud'] = <FakeProcessInfo>[ |
| FakeProcessInfo(MockProcess(exitCode: 1), |
| <String>['firebase', 'test']), // integration test #1 |
| FakeProcessInfo(MockProcess(), |
| <String>['firebase', 'test']), // integration test #1 retry |
| FakeProcessInfo( |
| MockProcess(), <String>['firebase', 'test']), // integration test #2 |
| ]; |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Testing example/integration_test/bar_test.dart...'), |
| contains('bar_test.dart failed on attempt 1. Retrying...'), |
| contains('Testing example/integration_test/foo_test.dart...'), |
| contains('Ran for 1 package(s) (1 with warnings)'), |
| ]), |
| ); |
| }); |
| |
| test('fails for plugins with no androidTest directory', () async { |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| ]); |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for plugin'), |
| contains('No androidTest directory found.'), |
| contains('The following packages had errors:'), |
| contains('plugin:\n' |
| ' No tests ran (use --exclude if this is intentional).'), |
| ]), |
| ); |
| }); |
| |
| test('skips for non-plugin packages with no androidTest directory', |
| () async { |
| createFakePackage('a_package', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| ]); |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for a_package'), |
| contains('No androidTest directory found.'), |
| contains('No examples support Android.'), |
| contains('Skipped 1 package'), |
| ]), |
| ); |
| }); |
| |
| test('fails for packages with no integration test files', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for plugin'), |
| contains('No integration tests were run'), |
| contains('The following packages had errors:'), |
| contains('plugin:\n' |
| ' No tests ran (use --exclude if this is intentional).'), |
| ]), |
| ); |
| }); |
| |
| test('fails for packages with no integration_test runner', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'test/plugin_test.dart', |
| 'example/integration_test/bar_test.dart', |
| 'example/integration_test/foo_test.dart', |
| 'example/integration_test/should_not_run.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| // Use the wrong @RunWith annotation. |
| writeJavaTestFile(plugin, javaTestFileRelativePath, |
| runnerClass: 'AndroidJUnit4.class'); |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for plugin'), |
| contains('No integration_test runner found. ' |
| 'See the integration_test package README for setup instructions.'), |
| contains('plugin:\n' |
| ' No integration_test runner.'), |
| ]), |
| ); |
| }); |
| |
| test('skips packages with no android directory', () async { |
| createFakePackage('package', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| ]); |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for package'), |
| contains('No examples support Android'), |
| ]), |
| ); |
| expect(output, |
| isNot(contains('Testing example/integration_test/foo_test.dart...'))); |
| |
| expect( |
| processRunner.recordedCalls, |
| orderedEquals(<ProcessCall>[]), |
| ); |
| }); |
| |
| test('builds if gradlew is missing', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| final List<String> output = await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| '--test-run-id', |
| 'testRunId', |
| '--build-id', |
| 'buildId', |
| ]); |
| |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Running for plugin'), |
| contains('Running flutter build apk...'), |
| contains('Testing example/integration_test/foo_test.dart...'), |
| ]), |
| ); |
| |
| expect( |
| processRunner.recordedCalls, |
| orderedEquals(<ProcessCall>[ |
| ProcessCall( |
| 'flutter', |
| 'build apk --config-only'.split(' '), |
| '/packages/plugin/example/android', |
| ), |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleAndroidTest -Pverbose=true'.split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart' |
| .split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30' |
| .split(' '), |
| '/packages/plugin/example'), |
| ]), |
| ); |
| }); |
| |
| test('fails if building to generate gradlew fails', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| processRunner.mockProcessesForExecutable['flutter'] = <FakeProcessInfo>[ |
| FakeProcessInfo(MockProcess(exitCode: 1), <String>['build']) |
| ]; |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Unable to build example apk'), |
| ])); |
| }); |
| |
| test('fails if assembleAndroidTest fails', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| final String gradlewPath = plugin |
| .getExamples() |
| .first |
| .platformDirectory(FlutterPlatform.android) |
| .childFile('gradlew') |
| .path; |
| processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[ |
| FakeProcessInfo( |
| MockProcess(exitCode: 1), <String>['app:assembleAndroidTest']), |
| ]; |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Unable to assemble androidTest'), |
| ])); |
| }); |
| |
| test('fails if assembleDebug fails', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| final String gradlewPath = plugin |
| .getExamples() |
| .first |
| .platformDirectory(FlutterPlatform.android) |
| .childFile('gradlew') |
| .path; |
| processRunner.mockProcessesForExecutable[gradlewPath] = <FakeProcessInfo>[ |
| FakeProcessInfo(MockProcess(), <String>['app:assembleAndroidTest']), |
| FakeProcessInfo(MockProcess(exitCode: 1), <String>['app:assembleDebug']) |
| ]; |
| |
| Error? commandError; |
| final List<String> output = await runCapturingPrint( |
| runner, |
| <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| ], |
| errorHandler: (Error e) { |
| commandError = e; |
| }, |
| ); |
| |
| expect(commandError, isA<ToolExit>()); |
| expect( |
| output, |
| containsAllInOrder(<Matcher>[ |
| contains('Could not build example/integration_test/foo_test.dart'), |
| contains('The following packages had errors:'), |
| contains(' plugin:\n' |
| ' example/integration_test/foo_test.dart failed to build'), |
| ])); |
| }); |
| |
| test('experimental flag', () async { |
| const String javaTestFileRelativePath = |
| 'example/android/app/src/androidTest/MainActivityTest.java'; |
| final RepositoryPackage plugin = |
| createFakePlugin('plugin', packagesDir, extraFiles: <String>[ |
| 'example/integration_test/foo_test.dart', |
| 'example/android/gradlew', |
| javaTestFileRelativePath, |
| ]); |
| writeJavaTestFile(plugin, javaTestFileRelativePath); |
| |
| await runCapturingPrint(runner, <String>[ |
| 'firebase-test-lab', |
| '--results-bucket=a_bucket', |
| '--device', |
| 'model=redfin,version=30', |
| '--test-run-id', |
| 'testRunId', |
| '--build-id', |
| 'buildId', |
| '--enable-experiment=exp1', |
| ]); |
| |
| expect( |
| processRunner.recordedCalls, |
| orderedEquals(<ProcessCall>[ |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleAndroidTest -Pverbose=true -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1' |
| .split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| '/packages/plugin/example/android/gradlew', |
| 'app:assembleDebug -Pverbose=true -Ptarget=/packages/plugin/example/integration_test/foo_test.dart -Pextra-front-end-options=--enable-experiment%3Dexp1 -Pextra-gen-snapshot-options=--enable-experiment%3Dexp1' |
| .split(' '), |
| '/packages/plugin/example/android'), |
| ProcessCall( |
| 'gcloud', |
| 'firebase test android run --type instrumentation --app build/app/outputs/apk/debug/app-debug.apk --test build/app/outputs/apk/androidTest/debug/app-debug-androidTest.apk --timeout 7m --results-bucket=gs://a_bucket --results-dir=plugins_android_test/plugin/buildId/testRunId/example/0/ --device model=redfin,version=30' |
| .split(' '), |
| '/packages/plugin/example'), |
| ]), |
| ); |
| }); |
| }); |
| } |