Skip to content

Commit

Permalink
[integration_test] Show stack trace of widget test errors on the plat…
Browse files Browse the repository at this point in the history
…form side (flutter#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.
  • Loading branch information
jiahaog authored and Egor committed Nov 20, 2020
1 parent 96462d6 commit 7285fdd
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 31 deletions.
4 changes: 4 additions & 0 deletions packages/integration_test/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.8.1

* Show stack trace of widget test errors on the platform side

## 0.8.0

* Rename plugin to integration_test.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void run(RunNotifier notifier) {
Description d = Description.createTestDescription(testClass, name);
notifier.fireTestStarted(d);
String outcome = results.get(name);
if (outcome.equals("failed")) {
if (!outcome.equals("success")) {
Exception dummyException = new Exception(outcome);
notifier.fireTestFailure(new Failure(d, dummyException));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ - (BOOL)testIntegrationTest:(NSString **)testResult {
NSLog(@"%@ passed.", test);
[passedTests addObject:test];
} else {
NSLog(@"%@ failed.", test);
NSLog(@"%@ failed: %@", test, result);
[failedTests addObject:test];
}
}
Expand Down
8 changes: 5 additions & 3 deletions packages/integration_test/lib/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class Response {
}

_failureDetails.forEach((Failure f) {
list.add(f.toString());
list.add(f.toJson());
});

return list;
Expand Down Expand Up @@ -107,14 +107,16 @@ class Failure {
Failure(this.methodName, this.details);

/// Serializes the object to JSON.
@override
String toString() {
String toJson() {
return json.encode(<String, String>{
'methodName': methodName,
'details': details,
});
}

@override
String toString() => toJson();

/// Decode a JSON string to create a Failure object.
static Failure fromJsonString(String jsonString) {
Map<String, dynamic> failure = json.decode(jsonString);
Expand Down
32 changes: 18 additions & 14 deletions packages/integration_test/lib/integration_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import 'package:flutter/widgets.dart';
import 'common.dart';
import '_extension_io.dart' if (dart.library.html) '_extension_web.dart';

const String _success = 'success';

/// A subclass of [LiveTestWidgetsFlutterBinding] that reports tests results
/// on a channel to adapt them to native instrumentation test format.
class IntegrationTestWidgetsFlutterBinding
Expand All @@ -33,7 +35,14 @@ class IntegrationTestWidgetsFlutterBinding
}
await _channel.invokeMethod<void>(
'allTestsFinished',
<String, dynamic>{'results': results},
<String, dynamic>{
'results': results.map((name, result) {
if (result is Failure) {
return MapEntry(name, result.details);
}
return MapEntry(name, result);
})
},
);
} on MissingPluginException {
print('Warning: integration_test test plugin was not detected.');
Expand All @@ -46,8 +55,7 @@ class IntegrationTestWidgetsFlutterBinding
final TestExceptionReporter oldTestExceptionReporter = reportTestException;
reportTestException =
(FlutterErrorDetails details, String testDescription) {
results[testDescription] = 'failed';
_failureMethodsDetails.add(Failure(testDescription, details.toString()));
results[testDescription] = Failure(testDescription, details.toString());
if (!_allTestsPassed.isCompleted) {
_allTestsPassed.complete(false);
}
Expand Down Expand Up @@ -95,17 +103,11 @@ class IntegrationTestWidgetsFlutterBinding

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

/// Stores failure details.
///
/// Failed test method's names used as key.
final List<Failure> _failureMethodsDetails = List<Failure>();

/// Similar to [WidgetsFlutterBinding.ensureInitialized].
///
/// Returns an instance of the [IntegrationTestWidgetsFlutterBinding], creating and
/// initializing it if necessary.
static WidgetsBinding ensureInitialized() {
print('TESTING123 ensuring init');
if (WidgetsBinding.instance == null) {
IntegrationTestWidgetsFlutterBinding();
}
Expand All @@ -118,10 +120,12 @@ class IntegrationTestWidgetsFlutterBinding

/// Test results that will be populated after the tests have completed.
///
/// Keys are the test descriptions, and values are either `success` or
/// `failed`.
/// Keys are the test descriptions, and values are either [_success] or
/// a [Failure].
@visibleForTesting
Map<String, String> results = <String, String>{};
Map<String, Object> results = <String, Object>{};

List<Failure> get _failures => results.values.whereType<Failure>().toList();

/// The extra data for the reported result.
///
Expand All @@ -143,7 +147,7 @@ class IntegrationTestWidgetsFlutterBinding
'message': allTestsPassed
? Response.allTestsPassed(data: reportData).toJson()
: Response.someTestsFailed(
_failureMethodsDetails,
_failures,
data: reportData,
).toJson(),
};
Expand Down Expand Up @@ -185,6 +189,6 @@ class IntegrationTestWidgetsFlutterBinding
description: description,
timeout: timeout,
);
results[description] ??= 'success';
results[description] ??= _success;
}
}
2 changes: 1 addition & 1 deletion packages/integration_test/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: integration_test
description: Runs tests that use the flutter_test API as integration tests.
version: 0.8.0
version: 0.8.1
homepage: https://github.com/flutter/plugins/tree/master/packages/integration_test

environment:
Expand Down
19 changes: 8 additions & 11 deletions packages/integration_test/test/binding_fail_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter_test/flutter_test.dart';
const String _flutterBin = 'flutter';
const String _integrationResultsPrefix =
'IntegrationTestWidgetsFlutterBinding test results:';
const String _failureExcerpt = 'Expected: <false>\\n Actual: <true>';

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

expect(results, hasLength(2));
expect(
results,
equals({
'failing test 1': 'failed',
'failing test 2': 'failed',
}));
results, containsPair('failing test 1', contains(_failureExcerpt)));
expect(
results, containsPair('failing test 2', contains(_failureExcerpt)));
});

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

expect(
results,
equals({
'passing test': 'success',
'failing test': 'failed',
}));
expect(results, hasLength(2));
expect(results, containsPair('passing test', equals('success')));
expect(results, containsPair('failing test', contains(_failureExcerpt)));
});
});
}
Expand Down

0 comments on commit 7285fdd

Please sign in to comment.