How to deactivate or ignore layout overflow messages in Flutter widget tests?

4,929

Solution 1

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.

Solution 2

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.

Solution 3

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

Solution 4

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);
  }
};

Solution 5

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);
    }
  };
}
Share:
4,929
MarcG
Author by

MarcG

Currently living in São Paulo and Rio de Janeiro - Brazil. I hold both Brazilian and European (Polish) passports. Aeronautical-Mechanical Engineer (Technological Institute of Aeronautics ITA, the "Brazilian MIT"). MBA (PUC-RJ) Software Architect and Developer. Previously C++, but now mostly Dart/Flutter (see https://pub.dev/publishers/glasberg.dev/packages), JavaScript (Typescript) and Java. Love TDD, BDD and Clean Code. Also very interested in Usability and Gamification. Excellent communication skills and technical writing. I program since I was 10 yo. Love travelling, astronomy, science and games (playing and making them). Links: https://github.com/marcglasberg https://www.linkedin.com/in/marcglasberg/ https://medium.com/flutter-community/https-medium-com-marcglasberg-async-redux-33ac5e27d5f6 https://medium.com/flutter-community/i18n-extension-flutter-b966f4c65df9 Patents: https://www.google.com/patents/US7917437 https://www.google.com/patents/US7596530 Fluent English and Portuguese, good Spanish, some French. Come visit Rio and rent my place in AirBnB: https://www.airbnb.com/rooms/13830632 [email protected]

Updated on December 13, 2022

Comments

  • MarcG
    MarcG over 1 year

    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?