Unverified Commit 52e46056 authored by Todd Volkert's avatar Todd Volkert Committed by GitHub

Golden file fixes (#17299)

1. Make goldenFileComparator getter return `null` if it's set to the
   uninitialized comparator, which matches the behavior of the setter
   (it sets it to the uninitialized comparator if the caller specifies
   `null`).
2. Make the uninitialized comparator return trivial success (and print
   a message) when asked to compare as opposed to throwing. This ensures
   that the comparator will play nicely with live widget bindings
3. Augment documentation
4. Add assert that test doesn't modify the value of `autoUpdateGoldenFiles`
parent aa341be4
......@@ -19,6 +19,7 @@ import 'package:test/test.dart' as test_package;
import 'package:stack_trace/stack_trace.dart' as stack_trace;
import 'package:vector_math/vector_math_64.dart';
import 'goldens.dart';
import 'stack_manipulation.dart';
import 'test_async_utils.dart';
import 'test_text_input.dart';
......@@ -492,6 +493,8 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
runApp(new Container(key: new UniqueKey(), child: _kPreTestMessage)); // Reset the tree to a known state.
await pump();
final bool autoUpdateGoldensBeforeTest = autoUpdateGoldenFiles;
// run the test
await testBody();
asyncBarrier(); // drains the microtasks in `flutter test` mode (when using AutomatedTestWidgetsFlutterBinding)
......@@ -503,6 +506,7 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
runApp(new Container(key: new UniqueKey(), child: _kPostTestMessage)); // Unmount any remaining widgets.
await pump();
invariantTester();
_verifyAutoUpdateGoldensUnset(autoUpdateGoldensBeforeTest);
_verifyInvariants();
}
......@@ -533,6 +537,21 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
));
}
void _verifyAutoUpdateGoldensUnset(bool valueBeforeTest) {
assert(() {
if (autoUpdateGoldenFiles != valueBeforeTest) {
FlutterError.reportError(new FlutterErrorDetails(
exception: new FlutterError(
'The value of autoUpdateGoldenFiles was changed by the test.',
),
stack: StackTrace.current,
library: 'Flutter test framework',
));
}
return true;
}());
}
/// Called by the [testWidgets] function after a test is executed.
void postTest() {
assert(inTest);
......@@ -823,6 +842,12 @@ enum LiveTestWidgetsFlutterBindingFramePolicy {
/// doesn't trigger a paint, since then you could not see anything
/// anyway.)
class LiveTestWidgetsFlutterBinding extends TestWidgetsFlutterBinding {
@override
void initInstances() {
super.initInstances();
assert(!autoUpdateGoldenFiles);
}
@override
bool get inTest => _inTest;
bool _inTest = false;
......
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart' show TestFailure;
......@@ -66,7 +67,9 @@ abstract class GoldenFileComparator {
///
/// * [flutter_test] for more information about how to configure tests at the
/// directory-level.
GoldenFileComparator get goldenFileComparator => _goldenFileComparator;
GoldenFileComparator get goldenFileComparator {
return _goldenFileComparator == const _UninitializedComparator() ? null : _goldenFileComparator;
}
GoldenFileComparator _goldenFileComparator = const _UninitializedComparator();
set goldenFileComparator(GoldenFileComparator comparator) {
_goldenFileComparator = comparator ?? const _UninitializedComparator();
......@@ -87,23 +90,31 @@ set goldenFileComparator(GoldenFileComparator comparator) {
/// * [goldenFileComparator]
bool autoUpdateGoldenFiles = false;
/// Placeholder to signal an unexpected error in the testing framework itself.
/// Placeholder comparator that is set as the value of [goldenFileComparator]
/// when the initialization that happens in the test bootstrap either has not
/// yet happened or has been bypassed.
///
/// The test harness file that gets generated by the Flutter tool when the
/// The test bootstrap file that gets generated by the Flutter tool when the
/// user runs `flutter test` is expected to set [goldenFileComparator] to
/// a valid comparator. From there, the caller may choose to override it by
/// setting the comparator during test initialization (e.g. in `setUpAll()`).
/// But under no circumstances do we expect it to remain uninitialized.
/// a comparator that resolves golden file references relative to the test
/// directory. From there, the caller may choose to override the comparator by
/// setting it to another value during test initialization. The only case
/// where we expect it to remain uninitialized is when the user runs a test
/// via `flutter run`. In this case, the [compare] method will just print a
/// message that it would have otherwise run a real comparison, and it will
/// return trivial success.
class _UninitializedComparator implements GoldenFileComparator {
const _UninitializedComparator();
@override
Future<bool> compare(Uint8List imageBytes, Uri golden) {
throw new StateError('goldenFileComparator has not been initialized');
debugPrint('Golden file comparison requested for "$golden"; skipping...');
return new Future<bool>.value(true);
}
@override
Future<void> update(Uri golden, Uint8List imageBytes) {
// [autoUpdateGoldenFiles] should never be set in a live widget binding.
throw new StateError('goldenFileComparator has not been initialized');
}
}
......
......@@ -251,9 +251,17 @@ Matcher coversSameAreaAs(Path expectedPath, {@required Rect areaToCompare, int s
/// [expectLater] when using this matcher and await the future returned by
/// [expectLater].
///
/// ## Sample code
///
/// ```dart
/// await expectLater(find.text('Save'), matchesGoldenFile('save.png'));
/// ```
///
/// See also:
///
/// * [goldenFileComparator], which acts as the backend for this matcher.
/// * [flutter_test] for a discussion of test configurations, whereby callers
/// may swap out the backend for this matcher.
Matcher matchesGoldenFile(dynamic key) {
if (key is Uri) {
return new _MatchesGoldenFile(key);
......
......@@ -379,6 +379,7 @@ void main() {
expect(comparator.invocation, _ComparatorInvocation.update);
expect(comparator.imageBytes, hasLength(greaterThan(0)));
expect(comparator.golden, Uri.parse('foo.png'));
autoUpdateGoldenFiles = false;
});
});
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment