I encountered the same problem, and was looking for a similar solution.
After discussion on a Github issue I created, I learned a way to set the threshold.
First, create a file somewhere in your test folder (I put it in test/utils
), say local_file_comparator_with_threshold.dart
:
import 'dart:typed_data';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
/// Works just like [LocalFileComparator] but includes a [threshold] that, when
/// exceeded, marks the test as a failure.
class LocalFileComparatorWithThreshold extends LocalFileComparator {
/// Threshold above which tests will be marked as failing.
/// Ranges from 0 to 1, both inclusive.
final double threshold;
LocalFileComparatorWithThreshold(Uri testFile, this.threshold)
: assert(threshold >= 0 && threshold <= 1),
super(testFile);
/// Copy of [LocalFileComparator]'s [compare] method, except for the fact that
/// it checks if the [ComparisonResult.diffPercent] is not greater than
/// [threshold] to decide whether this test is successful or a failure.
@override
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
final result = await GoldenFileComparator.compareLists(
imageBytes,
await getGoldenBytes(golden),
);
if (!result.passed && result.diffPercent <= threshold) {
debugPrint(
'A difference of ${result.diffPercent * 100}% was found, but it is '
'acceptable since it is not greater than the threshold of '
'${threshold * 100}%',
);
return true;
}
if (!result.passed) {
final error = await generateFailureOutput(result, golden, basedir);
throw FlutterError(error);
}
return result.passed;
}
}
And then, you can override your test configuration in flutter_test_config.dart
(you need to put in your project's test
folder, create one if you don't already have one):
import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'utils/local_file_comparator_with_threshold.dart';
/// Customise your threshold here
/// For example, the error threshold here is 0.5%
/// Golden tests will pass if the pixel difference is equal to or below 0.5%
const _kGoldenTestsThreshold = 0.5 / 100;
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
if (goldenFileComparator is LocalFileComparator) {
final testUrl = (goldenFileComparator as LocalFileComparator).basedir;
goldenFileComparator = LocalFileComparatorWithThreshold(
// flutter_test's LocalFileComparator expects the test's URI to be passed
// as an argument, but it only uses it to parse the baseDir in order to
// obtain the directory where the golden tests will be placed.
// As such, we use the default `testUrl`, which is only the `baseDir` and
// append a generically named `test.dart` so that the `baseDir` is
// properly extracted.
Uri.parse('$testUrl/test.dart'),
_kGoldenTestsThreshold,
);
} else {
throw Exception(
'Expected `goldenFileComparator` to be of type `LocalFileComparator`, '
'but it is of type `${goldenFileComparator.runtimeType}`',
);
}
await testMain();
}
After this setup, whenever you run your golden tests in the project, they will pass when the pixel difference is less than or equal to the threshold you set in flutter_test_config.dart
.
await
ing theexpectLater
. The test is reaching the end and passing, and then the exception occurs afterwards. – Oler