mirror of
https://github.com/flutter/flutter
synced 2024-10-12 19:23:02 +00:00
Committing test progress.
This commit is contained in:
parent
4f29c31048
commit
9e3e44ee3d
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2018 The Chromium 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 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
@ -13,7 +14,7 @@ import 'package:test_api/test_api.dart' as test_package show TestFailure;
|
|||
|
||||
import 'package:flutter_goldens_client/client.dart';
|
||||
export 'package:flutter_goldens_client/client.dart';
|
||||
//TODO(katelovett): Tests [flutter_goldens_test.dart] and inline documentation
|
||||
//TODO(katelovett): Tests
|
||||
const String _kFlutterRootKey = 'FLUTTER_ROOT';
|
||||
|
||||
/// Main method that can be used in a `flutter_test_config.dart` file to set
|
||||
|
@ -80,6 +81,9 @@ class FlutterGoldenFileComparator implements GoldenFileComparator {
|
|||
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
|
||||
final bool authorized = await _skiaClient.auth(fs.directory(basedir));
|
||||
final File goldenFile = _getGoldenFile(golden);
|
||||
if(!goldenFile.existsSync()) {
|
||||
throw test_package.TestFailure('Could not be compared against non-existent file: "$golden"');
|
||||
}
|
||||
|
||||
if (!authorized)
|
||||
throw test_package.TestFailure('Could not authorize golctl.');
|
||||
|
@ -96,5 +100,4 @@ class FlutterGoldenFileComparator implements GoldenFileComparator {
|
|||
File _getGoldenFile(Uri uri) {
|
||||
return fs.directory(basedir).childFile(fs.file(uri).path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,49 +14,44 @@ import 'package:platform/platform.dart';
|
|||
import 'package:process/process.dart';
|
||||
|
||||
const String _kFlutterRoot = '/flutter';
|
||||
const String _kRepositoryRoot = '$_kFlutterRoot/bin/cache/pkg/goldens';
|
||||
const String _kVersionFile = '$_kFlutterRoot/bin/internal/goldens.version';
|
||||
const String _kGoldensVersion = '123456abcdef';
|
||||
const String _kGoldenRoot = '$_kFlutterRoot/bin/cache/pkg/goldens';
|
||||
//const String _kVersionFile = '$_kFlutterRoot/bin/internal/goldens.version';
|
||||
//const String _kGoldensVersion = '123456abcdef';
|
||||
|
||||
void main() {
|
||||
MemoryFileSystem fs;
|
||||
FakePlatform platform;
|
||||
MockProcessManager process;
|
||||
Directory flutter;
|
||||
Directory golden;
|
||||
|
||||
setUp(() {
|
||||
setUp(() async {
|
||||
fs = MemoryFileSystem();
|
||||
platform = FakePlatform(environment: <String, String>{'FLUTTER_ROOT': _kFlutterRoot});
|
||||
process = MockProcessManager();
|
||||
fs.directory(_kFlutterRoot).createSync(recursive: true);
|
||||
fs.directory(_kRepositoryRoot).createSync(recursive: true);
|
||||
fs.file(_kVersionFile).createSync(recursive: true);
|
||||
fs.file(_kVersionFile).writeAsStringSync(_kGoldensVersion);
|
||||
flutter = await fs.directory(_kFlutterRoot).create(recursive: true);
|
||||
golden = await fs.directory(_kGoldenRoot).create(recursive: true);
|
||||
//fs.file(_kVersionFile).createSync(recursive: true);
|
||||
//fs.file(_kVersionFile).writeAsStringSync(_kGoldensVersion);
|
||||
});
|
||||
|
||||
group('GoldensClient', () {
|
||||
GoldensClient goldens;
|
||||
group('SkiaGoldClient', () {
|
||||
SkiaGoldClient skiaGold;
|
||||
|
||||
setUp(() {
|
||||
goldens = GoldensClient(
|
||||
skiaGold = SkiaGoldClient(
|
||||
fs: fs,
|
||||
platform: platform,
|
||||
process: process,
|
||||
);
|
||||
});
|
||||
|
||||
group('prepare', () {
|
||||
test('performs minimal work if versions match', () async {
|
||||
when(process.run(any, workingDirectory: anyNamed('workingDirectory')))
|
||||
.thenAnswer((_) => Future<io.ProcessResult>.value(io.ProcessResult(123, 0, _kGoldensVersion, '')));
|
||||
await goldens.prepare();
|
||||
group('auth', () {
|
||||
|
||||
});
|
||||
|
||||
group('imgtest', () {
|
||||
|
||||
// Verify that we only spawned `git rev-parse HEAD`
|
||||
final VerificationResult verifyProcessRun =
|
||||
verify(process.run(captureAny, workingDirectory: captureAnyNamed('workingDirectory')));
|
||||
verifyProcessRun.called(1);
|
||||
expect(verifyProcessRun.captured.first, <String>['git', 'rev-parse', 'HEAD']);
|
||||
expect(verifyProcessRun.captured.last, _kRepositoryRoot);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -74,21 +69,34 @@ void main() {
|
|||
|
||||
group('fromDefaultComparator', () {
|
||||
test('calculates the basedir correctly', () async {
|
||||
final MockGoldensClient goldens = MockGoldensClient();
|
||||
final MockLocalFileComparator defaultComparator = MockLocalFileComparator();
|
||||
final Directory flutterRoot = fs.directory('/foo')..createSync(recursive: true);
|
||||
final Directory goldensRoot = flutterRoot.childDirectory('bar')..createSync(recursive: true);
|
||||
when(goldens.fs).thenReturn(fs);
|
||||
when(goldens.flutterRoot).thenReturn(flutterRoot);
|
||||
when(goldens.repositoryRoot).thenReturn(goldensRoot);
|
||||
when(defaultComparator.basedir).thenReturn(flutterRoot.childDirectory('baz').uri);
|
||||
comparator = await FlutterGoldenFileComparator.fromDefaultComparator(
|
||||
goldens: goldens, defaultComparator: defaultComparator);
|
||||
expect(comparator.basedir, fs.directory('/foo/bar/baz').uri);
|
||||
// final MockSkiaGoldClient skiaGold = MockSkiaGoldClient();
|
||||
// final MockLocalFileComparator defaultComparator = MockLocalFileComparator();
|
||||
// final Directory flutterRoot = fs.directory('/foo')..createSync(recursive: true);
|
||||
// final Directory skiaGoldRoot = flutterRoot.childDirectory('bar')..createSync(recursive: true);
|
||||
// when(skiaGold.fs).thenReturn(fs);
|
||||
// when(skiaGold.flutterRoot).thenReturn(flutterRoot);
|
||||
// when(skiaGold.repositoryRoot).thenReturn(skiaGoldRoot);
|
||||
// when(defaultComparator.basedir).thenReturn(flutterRoot.childDirectory('baz').uri);
|
||||
// comparator = await FlutterGoldenFileComparator.fromDefaultComparator(
|
||||
// goldens: goldens, defaultComparator: defaultComparator);
|
||||
// expect(comparator.basedir, fs.directory('/foo/bar/baz').uri);
|
||||
});
|
||||
});
|
||||
|
||||
group('compare', () {
|
||||
|
||||
test('throws if goldctl has not been authorized', () async {
|
||||
// Create file
|
||||
final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
|
||||
..createSync(recursive: true);
|
||||
try {
|
||||
await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
|
||||
fail('TestFailure expected but not thrown');
|
||||
} on TestFailure catch (error) {
|
||||
expect(error.message, contains('Could not authorize goldctl.'));
|
||||
}
|
||||
});
|
||||
|
||||
test('throws if golden file is not found', () async {
|
||||
try {
|
||||
await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
|
||||
|
@ -98,21 +106,21 @@ void main() {
|
|||
}
|
||||
});
|
||||
|
||||
test('returns false if golden bytes do not match', () async {
|
||||
final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
|
||||
..createSync(recursive: true);
|
||||
goldenFile.writeAsBytesSync(<int>[4, 5, 6], flush: true);
|
||||
final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
|
||||
expect(result, isFalse);
|
||||
});
|
||||
// test('returns false if skia gold test fails', () async {
|
||||
// final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
|
||||
// ..createSync(recursive: true);
|
||||
// goldenFile.writeAsBytesSync(<int>[4, 5, 6], flush: true);
|
||||
// final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
|
||||
// expect(result, isFalse);
|
||||
// });
|
||||
|
||||
test('returns true if golden bytes match', () async {
|
||||
final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
|
||||
..createSync(recursive: true);
|
||||
goldenFile.writeAsBytesSync(<int>[1, 2, 3], flush: true);
|
||||
final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
|
||||
expect(result, isTrue);
|
||||
});
|
||||
// test('returns true if skia gold test passes', () async {
|
||||
// final File goldenFile = fs.file('/path/to/flutter/bin/cache/goldens/test/foo/bar/test.png')
|
||||
// ..createSync(recursive: true);
|
||||
// goldenFile.writeAsBytesSync(<int>[1, 2, 3], flush: true);
|
||||
// final bool result = await comparator.compare(Uint8List.fromList(<int>[1, 2, 3]), Uri.parse('test.png'));
|
||||
// expect(result, isTrue);
|
||||
// });
|
||||
});
|
||||
|
||||
group('update', () {
|
||||
|
@ -136,5 +144,5 @@ void main() {
|
|||
}
|
||||
|
||||
class MockProcessManager extends Mock implements ProcessManager {}
|
||||
class MockGoldensClient extends Mock implements GoldensClient {}
|
||||
class MockSkiaGoldClient extends Mock implements SkiaGoldClient {}
|
||||
class MockLocalFileComparator extends Mock implements LocalFileComparator {}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright 2018 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//TODO(katelovett): Change to Skia Gold Client
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' as convert;
|
||||
import 'dart:io' as io;
|
||||
|
@ -14,7 +14,7 @@ import 'package:process/process.dart';
|
|||
// If you are here trying to figure out how to use golden files in the Flutter
|
||||
// repo itself, consider reading this wiki page:
|
||||
// https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package%3Aflutter
|
||||
//TODO(katelovett): Tests [flutter_goldens_test.dart] and inline documentation
|
||||
//TODO(katelovett): Tests
|
||||
const String _kFlutterRootKey = 'FLUTTER_ROOT';
|
||||
const String _kGoldctlKey = 'GOLDCTL';
|
||||
const String _kServiceAccountKey = 'GOLD_SERVICE_ACCOUNT';
|
||||
|
@ -31,7 +31,7 @@ class SkiaGoldClient {
|
|||
|
||||
/// The file system to use for storing local files for running imgtests.
|
||||
///
|
||||
/// This is usefule in tests, where a local file system (the default) can be
|
||||
/// This is useful in tests, where a local file system (the default) can be
|
||||
/// replaced by a memory file system.
|
||||
final FileSystem fs;
|
||||
|
||||
|
@ -41,11 +41,11 @@ class SkiaGoldClient {
|
|||
/// replaced by a mock platform instance.
|
||||
final Platform platform;
|
||||
|
||||
/// A controller for launching subprocesses.
|
||||
/// A controller for launching sub-processes.
|
||||
///
|
||||
/// This is useful in tests, where the real process manager (the default) can
|
||||
/// be replaced by a mock process manager that doesn't really create
|
||||
/// subprocesses.
|
||||
/// sub-processes.
|
||||
final ProcessManager process;
|
||||
|
||||
Directory _workDirectory;
|
||||
|
@ -70,7 +70,7 @@ class SkiaGoldClient {
|
|||
/// The local [Directory] where the Flutter repository is hosted.
|
||||
///
|
||||
/// Uses the [fs] file system.
|
||||
Directory get _flutterRoot => fs.directory(platform.environment[_kFlutterRootKey]);
|
||||
Directory get flutterRoot => fs.directory(platform.environment[_kFlutterRootKey]);
|
||||
|
||||
/// Prepares the local work space for golden file testing and initializes the
|
||||
/// goldctl authorization for executing tests.
|
||||
|
@ -145,12 +145,12 @@ class SkiaGoldClient {
|
|||
}
|
||||
|
||||
Future<String> _getCommitHash() async {
|
||||
if (!_flutterRoot.existsSync()) {
|
||||
if (!flutterRoot.existsSync()) {
|
||||
return null;
|
||||
} else {
|
||||
final io.ProcessResult revParse = await process.run(
|
||||
<String>['git', 'rev-parse', 'HEAD'],
|
||||
workingDirectory: _flutterRoot.path,
|
||||
workingDirectory: flutterRoot.path,
|
||||
);
|
||||
return revParse.exitCode == 0 ? revParse.stdout.trim() : null;
|
||||
}
|
||||
|
|
|
@ -384,6 +384,88 @@ void main() {
|
|||
});
|
||||
});
|
||||
|
||||
group('matchesSkiaGoldFile', () {
|
||||
_FakeComparator comparator;
|
||||
|
||||
Widget boilerplate(Widget child) {
|
||||
return Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
comparator = _FakeComparator();
|
||||
goldenFileComparator = comparator;
|
||||
});
|
||||
|
||||
group('matches', () {
|
||||
testWidgets('if comparator succeeds', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(boilerplate(const Text('hello')));
|
||||
final Finder finder = find.byType(Text);
|
||||
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
|
||||
expect(comparator.invocation, _ComparatorInvocation.compare);
|
||||
expect(comparator.imageBytes, null);
|
||||
expect(comparator.golden, Uri.parse('foo.png'));
|
||||
});
|
||||
});
|
||||
|
||||
group('does not match', () {
|
||||
testWidgets('if comparator returns false', (WidgetTester tester) async {
|
||||
comparator.behavior = _ComparatorBehavior.returnFalse;
|
||||
await tester.pumpWidget(boilerplate(const Text('hello')));
|
||||
final Finder finder = find.byType(Text);
|
||||
try {
|
||||
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
|
||||
fail('TestFailure expected but not thrown');
|
||||
} on TestFailure catch (error) {
|
||||
expect(comparator.invocation, _ComparatorInvocation.compare);
|
||||
expect(error.message, contains('does not match'));
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('if comparator throws', (WidgetTester tester) async {
|
||||
comparator.behavior = _ComparatorBehavior.throwTestFailure;
|
||||
await tester.pumpWidget(boilerplate(const Text('hello')));
|
||||
final Finder finder = find.byType(Text);
|
||||
try {
|
||||
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
|
||||
fail('TestFailure expected but not thrown');
|
||||
} on TestFailure catch (error) {
|
||||
expect(comparator.invocation, _ComparatorInvocation.compare);
|
||||
expect(error.message, contains('fake message'));
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets('if finder finds no widgets', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(boilerplate(Container()));
|
||||
final Finder finder = find.byType(Text);
|
||||
try {
|
||||
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
|
||||
fail('TestFailure expected but not thrown');
|
||||
} on TestFailure catch (error) {
|
||||
expect(comparator.invocation, isNull);
|
||||
expect(error.message, contains('no widget was found'));
|
||||
}
|
||||
});
|
||||
|
||||
testWidgets(
|
||||
'if finder finds multiple widgets', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(boilerplate(Column(
|
||||
children: const <Widget>[Text('hello'), Text('world')],
|
||||
)));
|
||||
final Finder finder = find.byType(Text);
|
||||
try {
|
||||
await expectLater(finder, matchesSkiaGoldFile('foo.png'));
|
||||
fail('TestFailure expected but not thrown');
|
||||
} on TestFailure catch (error) {
|
||||
expect(comparator.invocation, isNull);
|
||||
expect(error.message, contains('too many widgets'));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('matchesSemanticsData', () {
|
||||
testWidgets('matches SemanticsData', (WidgetTester tester) async {
|
||||
final SemanticsHandle handle = tester.ensureSemantics();
|
||||
|
|
Loading…
Reference in a new issue