Тест Flutter Widget не может правильно эмулировать другой размер экрана - PullRequest
0 голосов
/ 18 июня 2020

Перед развертыванием моего приложения Flutter я хотел протестировать его на нескольких размерах экрана, чтобы проверить, есть ли Renderflex overflow для небольших экранов.

Но когда я впервые изменил размер экрана во время тестирования виджета, чтобы он соответствовал На устройстве, которое я использовал во время разработки, я понял, что тест виджета уже выдает Render overflow ошибок, хотя на реальном устройстве таких ошибок не было. Итак, я задал следующие вопросы к несоответствию в размер текста .

На воспроизводимом шаге ниже вы можете ясно видеть, что текст во время текста виджета ПУТЬ БОЛЬШЕ (справа), чем фактический текст на реальном устройстве (слева).

enter image description here

The bigger text size during Widget test causes the RenderFlex error in my app.

Steps to reproduce:

  1. Now connect a real device and run this code with flutter run

lib/main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: TextScaleComparaison(),
    ),
  );
}

class TextScaleComparaison extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final widget = Scaffold(
      body: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints constraints) {
          final width = MediaQuery.of(context).size.width;
          final height = MediaQuery.of(context).size.height;
          final dpr = MediaQuery.of(context).devicePixelRatio;
          final textScale = MediaQuery.of(context).textScaleFactor;
          final vi = MediaQuery.of(context).viewInsets;
          final vip = MediaQuery.of(context).viewPadding;
          final font = DefaultTextStyle.of(context).style.fontFamily;
          print("width is $width and height is $height and dpi is $dpr txtScale is $textScale vi is $vi vip is $vip font is $font");
          return Center(child: Text("This cannot be that long!!"));
        },
      ),
    );
    return widget;
  }
}
  1. Проверьте журналы, и вы должны увидеть информацию на экране устройства:

Для меня Я получил:

I/flutter (27450): width is 411.42857142857144 and height is 797.7142857142857 and dpi is 2.625 txtScale is 1.1 vi is EdgeInsets.zero vip is EdgeInsets(0.0, 24.0, 0.0, 0.0) font is Roboto

Скопируйте экран width и height в и textScale и devicePixelRatio на следующий шаг в приведенном ниже коде.

Отредактируйте приведенный ниже код, чтобы добавить вышеупомянутую настройку, потому что мы хотим смоделировать этот точный размер экрана в тесте.

test/test.dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:my_app/main.dart';
void main() {

  testWidgets(
    "Emulate real screen size",
    (WidgetTester tester) async {
      // Adjust these to match your actual device screen specs
      final width = 414;
      final height = 846;
      tester.binding.window.devicePixelRatioTestValue = (2.625);
      tester.binding.window.textScaleFactorTestValue = (1.1);
      final dpi = tester.binding.window.devicePixelRatio;
      tester.binding.window.physicalSizeTestValue = Size(width * dpi, height * dpi);
      await tester.pumpWidget(
        MediaQuery(
          data: MediaQueryData(),
          child: MaterialApp(
            home: TextScaleComparaison(),
          ),
        ),
      );
      await expectLater(
        find.byType(TextScaleComparaison),
        matchesGoldenFile("text.png"),
      );
    },
  );
}

Выполнить test.dart с flutter test --update-goldens test/test.dart

Это создаст файл png по адресу test/text.png

Проверьте журналы: Для меня он напечатал:

width is 414.0 and height is 846.0 and dpi is 2.625 txtScale is 1.1 vi is EdgeInsets.zero vip is EdgeInsets.zero font is Roboto

Что Я скучаю? Почему текст не может отображаться точно так же, как на реальном устройстве?

Ответы [ 2 ]

4 голосов
/ 19 июня 2020

Это из-за разницы шрифтов, используемых flutter test и flutter run.

Шрифт Flutter по умолчанию Roboto для Android, если вы не меняли его другим шрифтом.

  1. По умолчанию Android: Roboto шрифт и для iOS: San Francisco шрифт
  2. Настроить https://flutter.dev/docs/cookbook/design/fonts

Либо 1) или 2) эти шрифты по умолчанию недоступны для flutter test. В тесте на флаттер намеренно используется шрифт Ahem, который состоит из квадратных блоков, которые вы видите на скриншоте.

Это предварительный просмотр:

enter image description here

Ahem квадрат шрифта намного больше обычного, который вы используете. Следовательно, это вызывает RenderFlex overflow error

Решение

Для достижения почти идеальной эмуляции вашего устройства в flutter test вам необходимо загрузить данные шрифта, а затем загрузить именно тот шрифт, который вы используете. .

Чтобы загрузить шрифт в тесте виджета, вы должны сделать это внутри функции testWidgets или setUp:

final flamante = rootBundle.load('assets/fonts/Flamante-Roma-Medium.ttf');
      await FontLoader('FlamanteRoma')
        ..addFont(flamante)
        ..load();

Затем добавить этот шрифт в ThemeData перед накачкой виджет.

 theme: ThemeData(
              fontFamily: 'FlamanteRoma',
 ),

Окончательный код test.dart:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:example/test/compare_test_size.dart';

void main() {
  testWidgets(
    "Emulate real screen size",
    (WidgetTester tester) async {
      final flamante = rootBundle.load('assets/fonts/Flamante-Roma-Medium.ttf');
      await FontLoader('FlamanteRoma')
        ..addFont(flamante)
        ..load();

      // Adjust these to match your actual device screen specs
      final width = 411.4;
      final height = 797.7;
      tester.binding.window.devicePixelRatioTestValue = (2.625);
      tester.binding.window.textScaleFactorTestValue = (1.1);
      final dpi = tester.binding.window.devicePixelRatio;
      tester.binding.window.physicalSizeTestValue = Size(width * dpi, height * dpi);
      await tester.pumpWidget(
        MediaQuery(
          data: MediaQueryData(),
          child: MaterialApp(
            home: TextScaleComparaison(),
            theme: ThemeData(
              fontFamily: 'FlamanteRoma',
            ),
          ),
        ),
      );
      await expectLater(
        find.byType(TextScaleComparaison),
        matchesGoldenFile("text.png"),
      );
    },
  );
}

Теперь заново сгенерируйте золотой тест и проверьте png. Вы увидите настоящий текст, а не прямоугольники:

test/test.png

enter image description here

И не забудьте добавить тот же шрифт в вашем main.dart

runApp(
    MaterialApp(
      home: TextScaleComparaison(),
      theme: ThemeData(
        fontFamily: 'FlamanteRoma',
      ),
    ),
  );

А также не забудьте обновить pubspec.yaml и запустить flutter pub get

- family: FlamanteRoma
  fonts:
    - asset: assets/fonts/Flamante-Roma-Medium.ttf
0 голосов
/ 24 августа 2020

Как уже упоминал Curly, здесь , вы можете перезаписать tester.binding.window.textScaleFactorTestValue меньшим значением. 0.8 хорошо работал с моими использованными шрифтами, но в зависимости от ваших настроек вы можете использовать даже меньшее значение. Таким образом, вам не нужно ждать загрузки шрифтов в каждом тестовом примере.

...