| // 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 'package:dds/src/dap/protocol_generated.dart'; |
| import 'package:file/file.dart'; |
| import 'package:flutter_tools/src/cache.dart'; |
| |
| import '../../src/common.dart'; |
| import '../test_data/integration_tests_project.dart'; |
| import '../test_data/tests_project.dart'; |
| import '../test_utils.dart'; |
| import 'test_client.dart'; |
| import 'test_support.dart'; |
| |
| void main() { |
| late Directory tempDir; |
| late DapTestSession dap; |
| late DapTestClient client; |
| late TestsProject project; |
| |
| setUpAll(() { |
| Cache.flutterRoot = getFlutterRoot(); |
| }); |
| |
| setUp(() async { |
| tempDir = createResolvedTempDirectorySync('flutter_test_adapter_test.'); |
| dap = await DapTestSession.setUp(additionalArgs: <String>['--test']); |
| client = dap.client; |
| }); |
| |
| tearDown(() async { |
| await dap.tearDown(); |
| tryToDelete(tempDir); |
| }); |
| |
| void standardTests({List<String>? toolArgs}) { |
| test('can run in debug mode', () async { |
| // Collect output and test events while running the script. |
| final TestEvents outputEvents = await client.collectTestOutput( |
| launch: () => client.launch( |
| program: project.testFilePath, |
| cwd: project.dir.path, |
| toolArgs: toolArgs, |
| ), |
| ); |
| |
| // Check the printed output shows that the run finished, and it's exit |
| // code (which is 1 due to the failing test). |
| final String output = outputEvents.output.map((OutputEventBody e) => e.output).join(); |
| expectLines( |
| output, |
| <Object>[ |
| startsWith('Connecting to VM Service at'), |
| ..._testsProjectExpectedOutput, |
| ], |
| allowExtras: true, // Allow for printed call stack etc. |
| ); |
| |
| _expectStandardTestsProjectResults(outputEvents); |
| }); |
| |
| test('can run in noDebug mode', () async { |
| // Collect output and test events while running the script. |
| final TestEvents outputEvents = await client.collectTestOutput( |
| launch: () => client.launch( |
| program: project.testFilePath, |
| noDebug: true, |
| cwd: project.dir.path, |
| toolArgs: toolArgs, |
| ), |
| ); |
| |
| // Check the printed output shows that the run finished, and it's exit |
| // code (which is 1 due to the failing test). |
| final String output = outputEvents.output.map((OutputEventBody e) => e.output).join(); |
| expectLines( |
| output, |
| _testsProjectExpectedOutput, |
| allowExtras: true, // Allow for printed call stack etc. |
| ); |
| |
| _expectStandardTestsProjectResults(outputEvents); |
| }); |
| |
| test('can run a single test', () async { |
| // Collect output and test events while running the script. |
| final TestEvents outputEvents = await client.collectTestOutput( |
| launch: () => client.launch( |
| program: project.testFilePath, |
| noDebug: true, |
| cwd: project.dir.path, |
| // It's up to the calling IDE to pass the correct args for |
| // 'flutter test' if it wants to run a subset of tests. |
| toolArgs: <String>[ |
| '--plain-name', |
| 'can pass', |
| ...?toolArgs, |
| ], |
| ), |
| ); |
| |
| final List<Object> testsNames = outputEvents.testNotifications |
| .where((Map<String, Object?> e) => e['type'] == 'testStart') |
| .map((Map<String, Object?> e) => (e['test']! as Map<String, Object?>)['name']!) |
| .toList(); |
| |
| expect(testsNames, contains('Flutter tests can pass')); |
| expect(testsNames, isNot(contains('Flutter tests can fail'))); |
| }); |
| } |
| |
| group('widget tests', () { |
| setUp(() async { |
| project = TestsProject(); |
| await project.setUpIn(tempDir); |
| }); |
| |
| standardTests(); |
| }); |
| |
| group('integration tests', () { |
| const List<String> toolArgs = <String>['-d', 'flutter-tester']; |
| |
| setUp(() async { |
| project = IntegrationTestsProject(); |
| await project.setUpIn(tempDir); |
| }); |
| |
| standardTests(toolArgs: toolArgs); |
| }); |
| } |
| |
| /// Matchers for the expected console output of [TestsProject]. |
| final List<Object> _testsProjectExpectedOutput = <Object>[ |
| // First test |
| '✓ Flutter tests can pass', |
| // Second test |
| '══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════', |
| 'The following TestFailure was thrown running a test:', |
| 'Expected: false', |
| ' Actual: <true>', |
| '', |
| 'The test description was: can fail', |
| '', |
| '✖ Flutter tests can fail', |
| // Exit |
| '', |
| 'Exited (1).', |
| ]; |
| |
| /// A helper that verifies a full set of expected test results for the |
| /// [TestsProject] script. |
| void _expectStandardTestsProjectResults(TestEvents events) { |
| // Check we received all expected test events passed through from |
| // package:test. |
| final List<Object> eventNames = events.testNotifications |
| .map((Map<String, Object?> e) => e['type']!) |
| .toList(); |
| |
| // start/done should always be first/last. |
| expect(eventNames.first, equals('start')); |
| expect(eventNames.last, equals('done')); |
| |
| // allSuites should have occurred after start. |
| expect( |
| eventNames, |
| containsAllInOrder(<String>['start', 'allSuites']), |
| ); |
| |
| // Expect two tests, with the failing one emitting an error. |
| expect( |
| eventNames, |
| containsAllInOrder(<String>[ |
| 'testStart', |
| 'testDone', |
| 'testStart', |
| 'error', |
| 'testDone', |
| ]), |
| ); |
| } |