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

Commit f8341ef

Browse files
authored
[integration_test] Show stack trace of widget test errors on the platform side (#2967)
* [integration_test] Show stack trace of widget test errors on the platform side We keep things simple for now, because this might change once we have a proper test reporter.
1 parent 4a727fa commit f8341ef

File tree

7 files changed

+38
-31
lines changed

7 files changed

+38
-31
lines changed

packages/integration_test/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.8.1
2+
3+
* Show stack trace of widget test errors on the platform side
4+
15
## 0.8.0
26

37
* Rename plugin to integration_test.

packages/integration_test/android/src/main/java/dev/flutter/plugins/integration_test/FlutterTestRunner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public void run(RunNotifier notifier) {
7777
Description d = Description.createTestDescription(testClass, name);
7878
notifier.fireTestStarted(d);
7979
String outcome = results.get(name);
80-
if (outcome.equals("failed")) {
80+
if (!outcome.equals("success")) {
8181
Exception dummyException = new Exception(outcome);
8282
notifier.fireTestFailure(new Failure(d, dummyException));
8383
}

packages/integration_test/ios/Classes/IntegrationTestIosTest.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ - (BOOL)testIntegrationTest:(NSString **)testResult {
2626
NSLog(@"%@ passed.", test);
2727
[passedTests addObject:test];
2828
} else {
29-
NSLog(@"%@ failed.", test);
29+
NSLog(@"%@ failed: %@", test, result);
3030
[failedTests addObject:test];
3131
}
3232
}

packages/integration_test/lib/common.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class Response {
7878
}
7979

8080
_failureDetails.forEach((Failure f) {
81-
list.add(f.toString());
81+
list.add(f.toJson());
8282
});
8383

8484
return list;
@@ -107,14 +107,16 @@ class Failure {
107107
Failure(this.methodName, this.details);
108108

109109
/// Serializes the object to JSON.
110-
@override
111-
String toString() {
110+
String toJson() {
112111
return json.encode(<String, String>{
113112
'methodName': methodName,
114113
'details': details,
115114
});
116115
}
117116

117+
@override
118+
String toString() => toJson();
119+
118120
/// Decode a JSON string to create a Failure object.
119121
static Failure fromJsonString(String jsonString) {
120122
Map<String, dynamic> failure = json.decode(jsonString);

packages/integration_test/lib/integration_test.dart

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import 'package:flutter/widgets.dart';
1313
import 'common.dart';
1414
import '_extension_io.dart' if (dart.library.html) '_extension_web.dart';
1515

16+
const String _success = 'success';
17+
1618
/// A subclass of [LiveTestWidgetsFlutterBinding] that reports tests results
1719
/// on a channel to adapt them to native instrumentation test format.
1820
class IntegrationTestWidgetsFlutterBinding
@@ -33,7 +35,14 @@ class IntegrationTestWidgetsFlutterBinding
3335
}
3436
await _channel.invokeMethod<void>(
3537
'allTestsFinished',
36-
<String, dynamic>{'results': results},
38+
<String, dynamic>{
39+
'results': results.map((name, result) {
40+
if (result is Failure) {
41+
return MapEntry(name, result.details);
42+
}
43+
return MapEntry(name, result);
44+
})
45+
},
3746
);
3847
} on MissingPluginException {
3948
print('Warning: integration_test test plugin was not detected.');
@@ -46,8 +55,7 @@ class IntegrationTestWidgetsFlutterBinding
4655
final TestExceptionReporter oldTestExceptionReporter = reportTestException;
4756
reportTestException =
4857
(FlutterErrorDetails details, String testDescription) {
49-
results[testDescription] = 'failed';
50-
_failureMethodsDetails.add(Failure(testDescription, details.toString()));
58+
results[testDescription] = Failure(testDescription, details.toString());
5159
if (!_allTestsPassed.isCompleted) {
5260
_allTestsPassed.complete(false);
5361
}
@@ -95,17 +103,11 @@ class IntegrationTestWidgetsFlutterBinding
95103

96104
final Completer<bool> _allTestsPassed = Completer<bool>();
97105

98-
/// Stores failure details.
99-
///
100-
/// Failed test method's names used as key.
101-
final List<Failure> _failureMethodsDetails = List<Failure>();
102-
103106
/// Similar to [WidgetsFlutterBinding.ensureInitialized].
104107
///
105108
/// Returns an instance of the [IntegrationTestWidgetsFlutterBinding], creating and
106109
/// initializing it if necessary.
107110
static WidgetsBinding ensureInitialized() {
108-
print('TESTING123 ensuring init');
109111
if (WidgetsBinding.instance == null) {
110112
IntegrationTestWidgetsFlutterBinding();
111113
}
@@ -118,10 +120,12 @@ class IntegrationTestWidgetsFlutterBinding
118120

119121
/// Test results that will be populated after the tests have completed.
120122
///
121-
/// Keys are the test descriptions, and values are either `success` or
122-
/// `failed`.
123+
/// Keys are the test descriptions, and values are either [_success] or
124+
/// a [Failure].
123125
@visibleForTesting
124-
Map<String, String> results = <String, String>{};
126+
Map<String, Object> results = <String, Object>{};
127+
128+
List<Failure> get _failures => results.values.whereType<Failure>().toList();
125129

126130
/// The extra data for the reported result.
127131
///
@@ -143,7 +147,7 @@ class IntegrationTestWidgetsFlutterBinding
143147
'message': allTestsPassed
144148
? Response.allTestsPassed(data: reportData).toJson()
145149
: Response.someTestsFailed(
146-
_failureMethodsDetails,
150+
_failures,
147151
data: reportData,
148152
).toJson(),
149153
};
@@ -185,6 +189,6 @@ class IntegrationTestWidgetsFlutterBinding
185189
description: description,
186190
timeout: timeout,
187191
);
188-
results[description] ??= 'success';
192+
results[description] ??= _success;
189193
}
190194
}

packages/integration_test/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: integration_test
22
description: Runs tests that use the flutter_test API as integration tests.
3-
version: 0.8.0
3+
version: 0.8.1
44
homepage: https://github.com/flutter/plugins/tree/master/packages/integration_test
55

66
environment:

packages/integration_test/test/binding_fail_test.dart

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:flutter_test/flutter_test.dart';
88
const String _flutterBin = 'flutter';
99
const String _integrationResultsPrefix =
1010
'IntegrationTestWidgetsFlutterBinding test results:';
11+
const String _failureExcerpt = 'Expected: <false>\\n Actual: <true>';
1112

1213
void main() async {
1314
group('Integration binding result', () {
@@ -27,24 +28,20 @@ void main() async {
2728
final Map<String, dynamic> results =
2829
await _runTest('test/data/fail_test_script.dart');
2930

31+
expect(results, hasLength(2));
3032
expect(
31-
results,
32-
equals({
33-
'failing test 1': 'failed',
34-
'failing test 2': 'failed',
35-
}));
33+
results, containsPair('failing test 1', contains(_failureExcerpt)));
34+
expect(
35+
results, containsPair('failing test 2', contains(_failureExcerpt)));
3636
});
3737

3838
test('when one test passes, then another fails', () async {
3939
final Map<String, dynamic> results =
4040
await _runTest('test/data/pass_then_fail_test_script.dart');
4141

42-
expect(
43-
results,
44-
equals({
45-
'passing test': 'success',
46-
'failing test': 'failed',
47-
}));
42+
expect(results, hasLength(2));
43+
expect(results, containsPair('passing test', equals('success')));
44+
expect(results, containsPair('failing test', contains(_failureExcerpt)));
4845
});
4946
});
5047
}

0 commit comments

Comments
 (0)