blob: 22b737aa9307f7e80193858ec75b04cb28af75b0 [file] [log] [blame]
// Copyright 2014 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 'dart:async';
import 'dart:convert';
import 'package:args/command_runner.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/test.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/runner/flutter_command.dart';
import 'package:flutter_tools/src/test/runner.dart';
import 'package:flutter_tools/src/test/test_time_recorder.dart';
import 'package:flutter_tools/src/test/test_wrapper.dart';
import 'package:flutter_tools/src/test/watcher.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fake_devices.dart';
import '../../src/logging_logger.dart';
import '../../src/test_flutter_command_runner.dart';
const String _pubspecContents = '''
dev_dependencies:
flutter_test:
sdk: flutter
integration_test:
sdk: flutter''';
final String _packageConfigContents = json.encode(<String, Object>{
'configVersion': 2,
'packages': <Map<String, Object>>[
<String, String>{
'name': 'test_api',
'rootUri': 'file:///path/to/pubcache/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19',
'packageUri': 'lib/',
'languageVersion': '2.12',
},
<String, String>{
'name': 'integration_test',
'rootUri': 'file:///path/to/flutter/packages/integration_test',
'packageUri': 'lib/',
'languageVersion': '2.12',
},
],
'generated': '2021-02-24T07:55:20.084834Z',
'generator': 'pub',
'generatorVersion': '2.13.0-68.0.dev',
});
void main() {
Cache.disableLocking();
late MemoryFileSystem fs;
late LoggingLogger logger;
setUp(() {
fs = MemoryFileSystem.test();
fs.file('/package/pubspec.yaml').createSync(recursive: true);
fs.file('/package/pubspec.yaml').writeAsStringSync(_pubspecContents);
(fs.directory('/package/.dart_tool')
.childFile('package_config.json')
..createSync(recursive: true))
.writeAsString(_packageConfigContents);
fs.directory('/package/test').childFile('some_test.dart').createSync(recursive: true);
fs.directory('/package/integration_test').childFile('some_integration_test.dart').createSync(recursive: true);
fs.currentDirectory = '/package';
logger = LoggingLogger();
});
testUsingContext('Missing dependencies in pubspec',
() async {
// Clear the dependencies already added in [setUp].
fs.file('pubspec.yaml').writeAsStringSync('');
fs.directory('.dart_tool').childFile('package_config.json').writeAsStringSync('');
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
expect(() => commandRunner.run(const <String>[
'test',
'--no-pub',
]), throwsToolExit());
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Logger: () => logger,
});
testUsingContext('Missing dependencies in pubspec for integration tests',
() async {
// Only use the flutter_test dependency, integration_test is deliberately
// absent.
fs.file('pubspec.yaml').writeAsStringSync('''
dev_dependencies:
flutter_test:
sdk: flutter
''');
fs.directory('.dart_tool').childFile('package_config.json').writeAsStringSync(json.encode(<String, Object>{
'configVersion': 2,
'packages': <Map<String, Object>>[
<String, String>{
'name': 'test_api',
'rootUri': 'file:///path/to/pubcache/.pub-cache/hosted/pub.dartlang.org/test_api-0.2.19',
'packageUri': 'lib/',
'languageVersion': '2.12',
},
],
'generated': '2021-02-24T07:55:20.084834Z',
'generator': 'pub',
'generatorVersion': '2.13.0-68.0.dev',
}));
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
expect(() => commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]), throwsToolExit());
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('Pipes test-randomize-ordering-seed to package:test',
() async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--test-randomize-ordering-seed=random',
'--no-pub',
]);
expect(
fakePackageTest.lastArgs,
contains('--test-randomize-ordering-seed=random'),
);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
group('shard-index and total-shards', () {
testUsingContext('with the params they are Piped to package:test',
() async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--total-shards=1',
'--shard-index=2',
'--no-pub',
]);
expect(fakePackageTest.lastArgs, contains('--total-shards=1'));
expect(fakePackageTest.lastArgs, contains('--shard-index=2'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('without the params they not Piped to package:test',
() async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
]);
expect(fakePackageTest.lastArgs, isNot(contains('--total-shards')));
expect(fakePackageTest.lastArgs, isNot(contains('--shard-index')));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
});
testUsingContext('Supports coverage and machine', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
expect(() => commandRunner.run(const <String>[
'test',
'--no-pub',
'--machine',
'--coverage',
'--',
'test/fake_test.dart',
]), throwsA(isA<ToolExit>().having((ToolExit toolExit) => toolExit.message, 'message', isNull)));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('Pipes start-paused to package:test',
() async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--start-paused',
'--',
'test/fake_test.dart',
]);
expect(
fakePackageTest.lastArgs,
contains('--pause-after-load'),
);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('Pipes run-skipped to package:test',
() async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--run-skipped',
'--',
'test/fake_test.dart',
]);
expect(
fakePackageTest.lastArgs,
contains('--run-skipped'),
);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('Pipes enable-observatory', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--enable-vmservice',
'--',
'test/fake_test.dart',
]);
expect(
testRunner.lastEnableObservatoryValue,
true,
);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--start-paused',
'--no-enable-vmservice',
'--',
'test/fake_test.dart',
]);
expect(
testRunner.lastEnableObservatoryValue,
true,
);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--',
'test/fake_test.dart',
]);
expect(
testRunner.lastEnableObservatoryValue,
false,
);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
});
testUsingContext('Verbose prints phase timings', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0, const Duration(milliseconds: 1));
final TestCommand testCommand = TestCommand(testRunner: testRunner, verbose: true);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--',
'test/fake_test.dart',
]);
// Expect one message for each phase.
final List<String> logPhaseMessages = logger.messages.where((String m) => m.startsWith('Runtime for phase ')).toList();
expect(logPhaseMessages, hasLength(TestTimePhases.values.length));
// As we force the `runTests` command to take at least 1 ms expect at least
// one phase to take a non-zero amount of time.
final List<String> logPhaseMessagesNonZero = logPhaseMessages.where((String m) => !m.contains(Duration.zero.toString())).toList();
expect(logPhaseMessagesNonZero, isNotEmpty);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
Logger: () => logger,
});
testUsingContext('Non-verbose does not prints phase timings', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0, const Duration(milliseconds: 1));
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner =
createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--',
'test/fake_test.dart',
]);
final List<String> logPhaseMessages = logger.messages.where((String m) => m.startsWith('Runtime for phase ')).toList();
expect(logPhaseMessages, isEmpty);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
Logger: () => logger,
});
testUsingContext('Pipes different args when running Integration Tests', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]);
expect(fakePackageTest.lastArgs, contains('--concurrency=1'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('Overrides concurrency when running Integration Tests', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--concurrency=100',
'integration_test',
]);
expect(fakePackageTest.lastArgs, contains('--concurrency=1'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
group('Detecting Integration Tests', () {
testUsingContext('when integration_test is not passed', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
]);
expect(testCommand.isIntegrationTest, false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('when integration_test is passed', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]);
expect(testCommand.isIntegrationTest, true);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('when relative path to integration test is passed', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test/some_integration_test.dart',
]);
expect(testCommand.isIntegrationTest, true);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('when absolute path to integration test is passed', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'/package/integration_test/some_integration_test.dart',
]);
expect(testCommand.isIntegrationTest, true);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('when absolute unnormalized path to integration test is passed', () async {
final FakePackageTest fakePackageTest = FakePackageTest();
final TestCommand testCommand = TestCommand(testWrapper: fakePackageTest);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'/package/../package/integration_test/some_integration_test.dart',
]);
expect(testCommand.isIntegrationTest, true);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('when both test and integration test are passed', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
expect(() => commandRunner.run(const <String>[
'test',
'--no-pub',
'test/some_test.dart',
'integration_test/some_integration_test.dart',
]), throwsToolExit());
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
});
group('Required artifacts', () {
testUsingContext('for default invocation', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
]);
expect(await testCommand.requiredArtifacts, isEmpty);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('when platform is chrome', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--platform=chrome',
]);
expect(await testCommand.requiredArtifacts, <DevelopmentArtifact>[DevelopmentArtifact.web]);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('when running integration tests', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]);
expect(await testCommand.requiredArtifacts, <DevelopmentArtifact>[
DevelopmentArtifact.universal,
DevelopmentArtifact.androidGenSnapshot,
]);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
});
testUsingContext('Integration tests when no devices are connected', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
expect(() => commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]), throwsToolExit());
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[]),
});
// TODO(jiahaog): Remove this when web is supported. https://github.com/flutter/flutter/issues/66264
testUsingContext('Integration tests when only web devices are connected', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
expect(() => commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]), throwsToolExit());
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral'),
]),
});
testUsingContext('Integration tests set the correct dart-defines', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'integration_test',
]);
expect(
testRunner.lastDebuggingOptionsValue.buildInfo.dartDefines,
contains('INTEGRATION_TEST_SHOULD_REPORT_RESULTS_TO_NATIVE=false'),
);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('Integration tests given flavor', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--flavor',
'dev',
'integration_test',
]);
expect(
testRunner.lastDebuggingOptionsValue.buildInfo.flavor,
contains('dev'),
);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[
FakeDevice('ephemeral', 'ephemeral', type: PlatformType.android),
]),
});
testUsingContext('Builds the asset manifest by default', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
]);
final bool fileExists = await fs.isFile('build/unit_test_assets/AssetManifest.json');
expect(fileExists, true);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[]),
});
testUsingContext("Don't build the asset manifest if --no-test-assets if informed", () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--no-test-assets',
]);
final bool fileExists = await fs.isFile('build/unit_test_assets/AssetManifest.json');
expect(fileExists, false);
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
DeviceManager: () => _FakeDeviceManager(<Device>[]),
});
group('Fatal Logs', () {
testUsingContext("doesn't fail when --fatal-warnings is set and no warning output", () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
try {
await commandRunner.run(const <String>[
'test',
'--no-pub',
'--${FlutterOptions.kFatalWarnings}',
]);
} on Exception {
fail('Unexpected exception thrown');
}
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('fails if --fatal-warnings specified and warnings emitted', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
testLogger.printWarning('Warning: Mild annoyance, Will Robinson!');
expect(commandRunner.run(const <String>[
'test',
'--no-pub',
'--${FlutterOptions.kFatalWarnings}',
]), throwsToolExit(message: 'Logger received warning output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
testUsingContext('fails when --fatal-warnings is set and only errors emitted', () async {
final FakeFlutterTestRunner testRunner = FakeFlutterTestRunner(0);
final TestCommand testCommand = TestCommand(testRunner: testRunner);
final CommandRunner<void> commandRunner = createTestCommandRunner(testCommand);
testLogger.printError('Error: Danger Will Robinson!');
expect(commandRunner.run(const <String>[
'test',
'--no-pub',
'--${FlutterOptions.kFatalWarnings}',
]), throwsToolExit(message: 'Logger received error output during the run, and "--${FlutterOptions.kFatalWarnings}" is enabled.'));
}, overrides: <Type, Generator>{
FileSystem: () => fs,
ProcessManager: () => FakeProcessManager.any(),
});
});
}
class FakeFlutterTestRunner implements FlutterTestRunner {
FakeFlutterTestRunner(this.exitCode, [this.leastRunTime]);
int exitCode;
Duration? leastRunTime;
bool? lastEnableObservatoryValue;
late DebuggingOptions lastDebuggingOptionsValue;
@override
Future<int> runTests(
TestWrapper testWrapper,
List<String> testFiles, {
required DebuggingOptions debuggingOptions,
List<String> names = const <String>[],
List<String> plainNames = const <String>[],
String? tags,
String? excludeTags,
bool enableObservatory = false,
bool ipv6 = false,
bool machine = false,
String? precompiledDillPath,
Map<String, String>? precompiledDillFiles,
bool updateGoldens = false,
TestWatcher? watcher,
required int? concurrency,
String? testAssetDirectory,
FlutterProject? flutterProject,
String? icudtlPath,
Directory? coverageDirectory,
bool web = false,
String? randomSeed,
String? reporter,
String? timeout,
bool runSkipped = false,
int? shardIndex,
int? totalShards,
Device? integrationTestDevice,
String? integrationTestUserIdentifier,
TestTimeRecorder? testTimeRecorder,
}) async {
lastEnableObservatoryValue = enableObservatory;
lastDebuggingOptionsValue = debuggingOptions;
if (leastRunTime != null) {
await Future<void>.delayed(leastRunTime!);
}
return exitCode;
}
}
class FakePackageTest implements TestWrapper {
List<String>? lastArgs;
@override
Future<void> main(List<String> args) async {
lastArgs = args;
}
@override
void registerPlatformPlugin(
Iterable<Runtime> runtimes,
FutureOr<PlatformPlugin> Function() platforms,
) {}
}
class _FakeDeviceManager extends DeviceManager {
_FakeDeviceManager(this._connectedDevices) : super(logger: testLogger);
final List<Device> _connectedDevices;
@override
Future<List<Device>> getAllConnectedDevices() async => _connectedDevices;
@override
List<DeviceDiscovery> get deviceDiscoverers => <DeviceDiscovery>[];
}