15

Tests run with the Ahem font, which is too big, and sometimes it overflows, breaking tests. Some tests don't care about overflow anyway, so there should be a way to deactivate them.

I have many tests which run OK in the simulator, but break in tests.

We are forced to prevent overflows for widgets which will never overflow in reality, or else provide fonts for the tests, instead of Ahem, just for the sake of not overflowing the tests. It makes no sense that overflow errors are tested, unless you are doing "overflow error tests".

How do I turn off these errors, or how do I make tests ignore them?

10 Answers 10

13

Based on @RémiRousselet answer, I developed a solution.

FlutterError.onError = _onError_ignoreOverflowErrors;

Function _onError_ignoreOverflowErrors = (
  FlutterErrorDetails details, {
  bool forceReport = false,
}) {
  assert(details != null);
  assert(details.exception != null);
  // ---

  bool ifIsOverflowError = false;

  // Detect overflow error.
  var exception = details.exception;
  if (exception is FlutterError)
    ifIsOverflowError = !exception.diagnostics
        .any((e) => e.value.toString().startsWith("A RenderFlex overflowed by"));

  // Ignore if is overflow error.
  if (ifIsOverflowError)
    print('Overflow error.');

  // Throw others errors.
  else
    FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
};

This function ignores just overflow exceptions.

Sign up to request clarification or add additional context in comments.

2 Comments

TestWidgetsFlutterBinding._runTest() also overrides FlutterError.onError, providing its own implementation that does a lot more than just calling Flutter.dumbToConsole(), so this solution doesn't work.
it worked for me. :) void ignoreOverflowErrors(FlutterErrorDetails details, {bool forceReport = false}) {
10

You cannot disable overflow specifically. But there are a few alternatives:

1 Comment

Yes, as I said we know how to "provide fonts for the tests, instead of Ahem", amd also we know how to change the virtual screen size. We'll test setting FlutterError.onError to null. Never heard of this one.
7

If your problem is caused purely by the Ahem font being a little too big, you can try shrinking all your text using the accessibility textScaleFactor, by wrapping your WidgetUnderTest in a MediaQuery like so:

MediaQuery(
  // Shrink the text avoid overflow caused by large Ahem font.
  data: MediaQueryData(textScaleFactor: 0.5),
  child: WidgetUnderTest(),
);

This should be much faster than loading a different font in your widget test, and doesn't introduce risk of missing errors by messing with FlutterError.onError. However, if your widget doesn't honor textScaleFactor, or if the overflow is caused by some other reason, this won't help.

Please note that this is probably hiding an actual problem. The best solution is to fix or redesign your UI so that it won't overflow even with testScaleFactor: 1.5 in a large font, so users who set their fonts to the largest setting will be able to use your apps.

Comments

5

Slightly improved Eduardo's answer: fixed the detection test, and throwing an actual exception for non-overflow errors, so that widget tests will actually break.

Function onError_ignoreOverflowErrors = (
  FlutterErrorDetails details, {
  bool forceReport = false,
}) {
  assert(details != null);
  assert(details.exception != null);

  var isOverflowError = false;

  // Detect overflow error.
  var exception = details.exception;
  if (exception is FlutterError) {
    isOverflowError = exception.diagnostics.any((e) => e.value.toString().contains("A RenderFlex overflowed by"));
  }

  // Ignore if is overflow error: only report to the console, but do not throw exception as it will
  // cause widget tests to fail.
  if (isOverflowError) {
    FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
  } else {
    FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
    throw (exception);
  }
};

Comments

4

Based on all the helpful answers here, I have published a helper function called disableOverflowError() on package hrk_flutter_test_batteries.

You can use it as follows:

  1. First import the package
flutter pub add dev:hrk_flutter_test_batteries
  1. Add it to all your test cases
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hrk_flutter_test_batteries/hrk_flutter_test_batteries.dart';

void main() {
  group('disableOverflowError()', () {
    // Doesn't work. See test/error/disable_overflow_error_test.dart
    // setUp(() {
    //   disableOverflowError();
    // });

    // Doesn't work. See test/error/disable_overflow_error_test.dart
    // setUpAll(() {
    //   disableOverflowError();
    // });

    // setUpAll(() {
    //   configureHrkLogging();
    //   packageLogger.level = Level.ALL;
    // });

    testWidgets('Included', (tester) async {
      disableOverflowError();
      tester.view.physicalSize = Size(100, tester.view.physicalSize.height);
      addTearDown(() => tester.view.resetPhysicalSize());
      await tester.pumpWidget(const Row(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          SizedBox(width: 110),
        ],
      ));
      expect(tester.takeException(), isNull);
    });

    testWidgets('Not included', (tester) async {
      tester.view.physicalSize = Size(100, tester.view.physicalSize.height);
      addTearDown(() => tester.view.resetPhysicalSize());
      await tester.pumpWidget(const Row(
        textDirection: TextDirection.ltr,
        children: <Widget>[
          SizedBox(width: 110),
        ],
      ));
      expect(tester.takeException(), isFlutterError);
    });
  });
}

Comments

3

If you only have one exception thrown in your test, you can tell your test to expect it, as below.

expect(
      tester
          .takeException()
          .toString()
          .contains('A RenderFlex overflowed by'),
      true,
    );

Comments

2

Thanks for sharing guys, it works just fine!

To anyone who wants to use it in a test:

testWidgets('your test name', (tester) async {
      disableOverflowErrors();
 });

void disableOverflowErrors() {
  //TODO MyScreen throws overflow error. Will be investigate in a different ticket.
  FlutterError.onError = (FlutterErrorDetails details) {
    final exception = details.exception;
    final isOverflowError = exception is FlutterError &&
        !exception.diagnostics.any(
            (e) => e.value.toString().startsWith("A RenderFlex overflowed by"));

    if (isOverflowError) {
      print(details);
    } else {
      FlutterError.presentError(details);
    }
  };
}

Comments

1

if is an overflow on a text widget use attribute softWrap: false, like this

Text(
           'text here',
            softWrap: false,
)

Comments

1

Kind of a centralised way to do it.

  setUpAll(() async {
    FlutterError.onError = (FlutterErrorDetails details) {
      // Detect overflow error
      final exception = details.exception;
      bool isOverFlowError = false;
      if (exception is FlutterError) {
        isOverFlowError = !exception.diagnostics.any((e) => e.value.toString().contains('RenderFlex'));
      }

      if (isOverFlowError) {
        // If the error is an overflow error, then we can safely ignore it
        // because it's not a real error.
        return;
      } else {
        FlutterError.dumpErrorToConsole(details);
      }
    };
  });

Comments

1

An up-to-date answer based on previous ones:

void _onErrorIgnoreOverflowErrors(
  FlutterErrorDetails details, {
  bool forceReport = false,
}) {
  var isOverflowError = false;

  // Detect overflow error.
  final exception = details.exception;
  if (exception is FlutterError) {
    isOverflowError = exception.diagnostics.any((e) => e.value.toString().contains("A RenderFlex overflowed by"));
  }

  // Ignore if is overflow error: only report to the console, but do not throw exception as it will
  // cause widget tests to fail.
  FlutterError.dumpErrorToConsole(details, forceReport: forceReport);
  if (!isOverflowError) throw exception;
}

And use it at the beginning of your test:

// If you want test to fail when there is an overflow error, comment the following line
FlutterError.onError = _onErrorIgnoreOverflowErrors;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.