Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit c0aee37

Browse files
committed
Add a mechanism for testing test results
1 parent 44a5471 commit c0aee37

File tree

6 files changed

+159
-4
lines changed

6 files changed

+159
-4
lines changed

packages/e2e/lib/e2e.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class E2EWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding {
3232
}
3333
await _channel.invokeMethod<void>(
3434
'allTestsFinished',
35-
<String, dynamic>{'results': _results},
35+
<String, dynamic>{'results': results},
3636
);
3737
} on MissingPluginException {
3838
print('Warning: E2E test plugin was not detected.');
@@ -45,7 +45,7 @@ class E2EWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding {
4545
final TestExceptionReporter oldTestExceptionReporter = reportTestException;
4646
reportTestException =
4747
(FlutterErrorDetails details, String testDescription) {
48-
_results[testDescription] = 'failed';
48+
results[testDescription] = 'failed';
4949
_failureMethodsDetails.add(Failure(testDescription, details.toString()));
5050
if (!_allTestsPassed.isCompleted) {
5151
_allTestsPassed.complete(false);
@@ -89,7 +89,12 @@ class E2EWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding {
8989

9090
static const MethodChannel _channel = MethodChannel('plugins.flutter.io/e2e');
9191

92-
static Map<String, String> _results = <String, String>{};
92+
/// Test results that will be populated after the tests have completed.
93+
///
94+
/// Keys are the test descriptions, and values are either `success` or
95+
/// `failed`.
96+
@visibleForTesting
97+
Map<String, String> results = <String, String>{};
9398

9499
/// The extra data for the reported result.
95100
///
@@ -153,6 +158,6 @@ class E2EWidgetsFlutterBinding extends LiveTestWidgetsFlutterBinding {
153158
description: description,
154159
timeout: timeout,
155160
);
156-
_results[description] ??= 'success';
161+
results[description] ??= 'success';
157162
}
158163
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import 'dart:async';
2+
import 'dart:io';
3+
import 'dart:convert';
4+
5+
import 'package:flutter_test/flutter_test.dart';
6+
7+
// Assumes that the flutter command is in `$PATH`.
8+
const String _flutterBin = 'flutter';
9+
const String _e2eResultsPrefix = 'E2EWidgetsFlutterBinding test results:';
10+
11+
void main() async {
12+
group('E2E binding result', () {
13+
test('when multiple tests pass', () async {
14+
final Map<String, dynamic> results =
15+
await _runTest('test/data/pass_test_script.dart');
16+
17+
expect(
18+
results,
19+
equals({
20+
'passing test 1': 'success',
21+
'passing test 2': 'success',
22+
}));
23+
});
24+
25+
test('when multiple tests fail', () async {
26+
final Map<String, dynamic> results =
27+
await _runTest('test/data/fail_test_script.dart');
28+
29+
expect(
30+
results,
31+
equals({
32+
'failing test 1': 'failed',
33+
'failing test 2': 'failed',
34+
}));
35+
});
36+
37+
test('when one test passes, then another fails', () async {
38+
final Map<String, dynamic> results =
39+
await _runTest('test/data/pass_then_fail_test_script.dart');
40+
41+
expect(
42+
results,
43+
equals({
44+
'passing test': 'success',
45+
'failing test': 'failed',
46+
}));
47+
});
48+
});
49+
}
50+
51+
/// Runs a test script and returns the [E2EWidgetsFlutterBinding.result].
52+
///
53+
/// [scriptPath] is relative to the package root.
54+
Future<Map<String, dynamic>> _runTest(String scriptPath) async {
55+
final Process process =
56+
await Process.start(_flutterBin, ['test', '--machine', scriptPath]);
57+
58+
// In the test [tearDownAll] block, the test results are encoded into JSON and
59+
// are printed with the [_e2eResultsPrefix] prefix.
60+
//
61+
// See the following for the test event spec which we parse the printed lines
62+
// out of: https://github.com/dart-lang/test/blob/master/pkgs/test/doc/json_reporter.md
63+
final String testResults = (await process.stdout
64+
.transform(utf8.decoder)
65+
.expand((String text) => text.split('\n'))
66+
.map((String line) {
67+
try {
68+
return jsonDecode(line);
69+
} on FormatException {
70+
// Only interested in test events which are JSON.
71+
}
72+
})
73+
.where((dynamic testEvent) => testEvent != null && testEvent['type'] == 'print')
74+
.map((dynamic printEvent) => printEvent['message'] as String)
75+
.firstWhere(
76+
(String message) => message.startsWith(_e2eResultsPrefix)))
77+
.replaceAll(_e2eResultsPrefix, '');
78+
79+
return jsonDecode(testResults);
80+
}

packages/e2e/test/data/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Files in this directory are not invoked directly by the test command.
2+
3+
They are used as inputs for the other test files outside of this directory, so
4+
that failures can be tested.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'dart:convert';
2+
3+
import 'package:e2e/e2e.dart';
4+
import 'package:flutter_test/flutter_test.dart';
5+
6+
void main() async {
7+
final E2EWidgetsFlutterBinding binding =
8+
E2EWidgetsFlutterBinding.ensureInitialized();
9+
10+
testWidgets('failing test 1', (WidgetTester tester) async {
11+
expect(true, false);
12+
});
13+
14+
testWidgets('failing test 2', (WidgetTester tester) async {
15+
expect(true, false);
16+
});
17+
18+
tearDownAll(() {
19+
print(
20+
'E2EWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
21+
});
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'dart:convert';
2+
3+
import 'package:e2e/e2e.dart';
4+
import 'package:flutter_test/flutter_test.dart';
5+
6+
void main() async {
7+
final E2EWidgetsFlutterBinding binding =
8+
E2EWidgetsFlutterBinding.ensureInitialized();
9+
10+
testWidgets('passing test 1', (WidgetTester tester) async {
11+
expect(true, true);
12+
});
13+
14+
testWidgets('passing test 2', (WidgetTester tester) async {
15+
expect(true, true);
16+
});
17+
18+
tearDownAll(() {
19+
print(
20+
'E2EWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
21+
});
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'dart:convert';
2+
3+
import 'package:e2e/e2e.dart';
4+
import 'package:flutter_test/flutter_test.dart';
5+
6+
void main() async {
7+
final E2EWidgetsFlutterBinding binding =
8+
E2EWidgetsFlutterBinding.ensureInitialized();
9+
10+
testWidgets('passing test', (WidgetTester tester) async {
11+
expect(true, true);
12+
});
13+
14+
testWidgets('failing test', (WidgetTester tester) async {
15+
expect(true, false);
16+
});
17+
18+
tearDownAll(() {
19+
print(
20+
'E2EWidgetsFlutterBinding test results: ${jsonEncode(binding.results)}');
21+
});
22+
}

0 commit comments

Comments
 (0)