Animation controller test (#88251)

Co-authored-by: Alexander Dahlberg <alexander.dahlberg@sigma.se>

Fixes test/animation/animation_controller_test.dart in #85160

Problem:
The test 'animateTo can deal with duration == Duration.Zero' was failing with the following error:

Expected: <0>
Actual: <5>
Expected no animation.
package:test_api expect
package:flutter_test/src/widget_tester.dart 484:3 expect
test/animation/animation_controller_test.dart 511:5 main.

Following line finds 5 transientCallbacks scheduled, while expecting zero, if shuffled with seed 123:

expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.');

This is caused by some other test leaving transientCallbacks scheduled.

Fix:
By disposing the AnimationController after each test, the transientCallbacks get cleaned up.
I chose to dispose all controllers in every test, to make sure there is no risk of leaks.
This commit is contained in:
Swiftaxe 2021-08-16 18:28:11 +02:00 committed by GitHub
parent 06be7e5392
commit fe337dcaf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,12 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(gspencergoog): Remove this tag once this test's state leaks/test
// dependencies have been fixed.
// https://github.com/flutter/flutter/issues/85160
// Fails with "flutter test --test-randomize-ordering-seed=123"
@Tags(<String>['no-shuffle'])
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
@ -57,6 +51,7 @@ void main() {
expect(didDismiss, isTrue);
controller.stop();
controller.dispose();
});
test('Receives status callbacks for forward and reverse', () {
@ -118,6 +113,7 @@ void main() {
expect(valueLog, equals(<AnimationStatus>[]));
controller.stop();
controller.dispose();
});
test('Forward and reverse from values', () {
@ -144,6 +140,7 @@ void main() {
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.dismissed, AnimationStatus.forward ]));
expect(valueLog, equals(<double>[ 0.0 ]));
expect(controller.value, equals(0.0));
controller.dispose();
});
test('Forward and reverse with different durations', () {
@ -207,6 +204,7 @@ void main() {
tick(const Duration(milliseconds: 310));
expect(controller.value, moreOrLessEquals(0.0));
controller.stop();
controller.dispose();
});
test('Forward only from value', () {
@ -226,6 +224,7 @@ void main() {
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward ]));
expect(valueLog, equals(<double>[ 0.2 ]));
expect(controller.value, equals(0.2));
controller.dispose();
});
test('Can fling to upper and lower bounds', () {
@ -256,6 +255,8 @@ void main() {
tick(const Duration(seconds: 6));
expect(largeRangeController.value, -30.0);
largeRangeController.stop();
controller.dispose();
largeRangeController.dispose();
});
test('Custom springDescription can be applied', () {
@ -279,6 +280,8 @@ void main() {
tick(const Duration(milliseconds: 50));
expect(customSpringController.value < controller.value, true);
controller.dispose();
customSpringController.dispose();
});
test('lastElapsedDuration control test', () {
@ -292,6 +295,7 @@ void main() {
tick(const Duration(milliseconds: 40));
expect(controller.lastElapsedDuration, equals(const Duration(milliseconds: 20)));
controller.stop();
controller.dispose();
});
test('toString control test', () {
@ -311,6 +315,7 @@ void main() {
tick(const Duration(milliseconds: 50));
expect(controller, hasOneLineDescription);
controller.stop();
controller.dispose();
});
test('velocity test - linear', () {
@ -354,6 +359,7 @@ void main() {
expect(controller.velocity, 0.0);
controller.stop();
controller.dispose();
});
test('Disposed AnimationController toString works', () {
@ -407,6 +413,7 @@ void main() {
);
expect(() { controller.repeat(); }, throwsFlutterError);
expect(() { controller.repeat(period: null); }, throwsFlutterError);
controller.dispose();
});
test('Do not animate if already at target', () {
@ -421,6 +428,7 @@ void main() {
controller.animateTo(0.5, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ]));
expect(controller.value, equals(0.5));
controller.dispose();
});
test('Do not animate to upperBound if already at upperBound', () {
@ -437,6 +445,7 @@ void main() {
controller.animateTo(1.0, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ]));
expect(controller.value, equals(1.0));
controller.dispose();
});
test('Do not animate to lowerBound if already at lowerBound', () {
@ -453,6 +462,7 @@ void main() {
controller.animateTo(0.0, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.completed ]));
expect(controller.value, equals(0.0));
controller.dispose();
});
test('Do not animate if already at target mid-flight (forward)', () {
@ -475,6 +485,7 @@ void main() {
controller.animateTo(currentValue, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
expect(controller.value, currentValue);
controller.dispose();
});
test('Do not animate if already at target mid-flight (reverse)', () {
@ -497,6 +508,7 @@ void main() {
controller.animateTo(currentValue, duration: const Duration(milliseconds: 100));
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.reverse, AnimationStatus.completed ]));
expect(controller.value, currentValue);
controller.dispose();
});
test('animateTo can deal with duration == Duration.zero', () {
@ -510,6 +522,7 @@ void main() {
controller.animateTo(1.0, duration: Duration.zero);
expect(SchedulerBinding.instance!.transientCallbackCount, equals(0), reason: 'Expected no animation.');
expect(controller.value, 1.0);
controller.dispose();
});
test('resetting animation works at all phases', () {
@ -563,6 +576,7 @@ void main() {
expect(controller.value, 0.0);
expect(controller.status, AnimationStatus.dismissed);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed, AnimationStatus.dismissed ]));
controller.dispose();
});
test('setting value directly sets correct status', () {
@ -591,6 +605,7 @@ void main() {
controller.value = 0.0;
expect(controller.value, 0.0);
expect(controller.status, AnimationStatus.dismissed);
controller.dispose();
});
test('animateTo sets correct status', () {
@ -637,6 +652,7 @@ void main() {
expect(controller.value, 0.0);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
statusLog.clear();
controller.dispose();
});
test('after a reverse call animateTo sets correct status', () {
@ -665,6 +681,7 @@ void main() {
expect(controller.value, 0.5);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
statusLog.clear();
controller.dispose();
});
test('after a forward call animateTo sets correct status', () {
@ -693,6 +710,7 @@ void main() {
expect(controller.value, 0.5);
expect(statusLog, equals(<AnimationStatus>[ AnimationStatus.forward, AnimationStatus.completed ]));
statusLog.clear();
controller.dispose();
});
test(
@ -743,6 +761,7 @@ void main() {
tick(Duration.zero);
tick(const Duration(milliseconds: 150));
expect(controller.value, 0.0);
controller.dispose();
},
);
@ -785,6 +804,7 @@ void main() {
tick(Duration.zero);
tick(const Duration(milliseconds: 125));
expect(controller.value, 1.0);
controller.dispose();
},
);
@ -795,6 +815,8 @@ void main() {
final AnimationController repeating = AnimationController.unbounded(vsync: const TestVSync());
expect(repeating.animationBehavior, AnimationBehavior.preserve);
controller.dispose();
repeating.dispose();
});
test('AnimationBehavior.preserve runs at normal speed when animatingTo', () {
@ -820,6 +842,7 @@ void main() {
expect(controller.value, 1.0);
expect(controller.status, AnimationStatus.completed);
debugSemanticsDisableAnimations = false;
controller.dispose();
});
test('AnimationBehavior.normal runs at 20x speed when animatingTo', () {
@ -845,6 +868,7 @@ void main() {
expect(controller.value, 1.0);
expect(controller.status, AnimationStatus.completed);
debugSemanticsDisableAnimations = null;
controller.dispose();
});
test('AnimationBehavior.normal runs "faster" than AnimationBehavior.preserve', () {
@ -864,6 +888,8 @@ void main() {
// We don't assert a specific faction that normal animation.
expect(controller.value < fastController.value, true);
debugSemanticsDisableAnimations = null;
controller.dispose();
fastController.dispose();
});
});
@ -895,6 +921,7 @@ void main() {
tick(Duration.zero);
tick(const Duration(seconds: 2));
expect(statuses, <AnimationStatus>[AnimationStatus.forward]);
controller.dispose();
});
test('Simulations run forward even after a reverse run', () {
@ -915,6 +942,7 @@ void main() {
tick(Duration.zero);
tick(const Duration(seconds: 2));
expect(statuses, <AnimationStatus>[AnimationStatus.forward]);
controller.dispose();
});
test('Repeating animation with reverse: true report as forward and reverse', () {
@ -933,6 +961,7 @@ void main() {
statuses.clear();
tick(const Duration(seconds: 1));
expect(statuses, <AnimationStatus>[AnimationStatus.reverse]);
controller.dispose();
});
test('AnimateBack can runs successfully with just "reverseDuration" property set', () {