Драйвер дротика — флаттера: тестовый элемент нижней навигационной панели

#dart #flutter #flutter-test

#dart #флаттер #тест на флаттер

Вопрос:

как мне протестировать BottomNavigationBarItems с помощью FlutterDriver?

FlutterDriver позволяет получать доступ к виджетам через text, byValueKey, byTooltip и byType.

Но ни один из этих методов не работает для моего приложения по следующим причинам:

  • текст: Приложение локализовано, и мне нужно протестировать приложение на нескольких языках.

  • byValueKey: у BottomNavigationBarItems нет свойств ключа.

  • byTooltip: у BottomNavigationBarItems нет свойств всплывающей подсказки.

  • byType: byType возвращает только первое совпадение типа и не содержит списка (необходим, потому что у меня есть несколько вкладок).

Большое вам спасибо!

Приветствия.

Ответ №1:

Не уверен, нашли ли вы ответ на этот вопрос, но я собираюсь опубликовать здесь решение, которое работает для меня. В принципе, BottomNavigationBar имеет key свойство, которое вам нужно использовать. Как только драйвер Flutter идентифицирует этот ключ, вы можете указать драйверу нажать на любой из его дочерних элементов, т.Е. BottomNavigationBarItem .

На моем экране есть 2, bottomNavigationBarItems как показано ниже, и я определил ключ для их родительского виджета, т.Е. BottomNavigationBar как:

 bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.shifting,
        key: Key('bottom'),
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.ac_unit, color: Colors.green,),
            title: Text('First', style: TextStyle(color: Colors.black),)
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.cast, color: Colors.yellow,),
            title: Text('Second', style: TextStyle(color: Colors.black),)
          )
        ],
      ),
  

введите описание изображения здесь

И я написал тест драйвера флаттера, чтобы коснуться обоих элементов, которые отлично сработали.

 test('bottomnavigationbar test', () async {
      await driver.waitFor(find.byValueKey('bottom'));
      await driver.tap(find.text('First'));
      print('clicked on first');
      await driver.tap(find.text('Second'));
      print('clicked on second too');
    });
  

Результат:

введите описание изображения здесь

Комментарии:

1. Спасибо за ваш ответ. Ваше решение работает, но, к сожалению, не для меня. Мое приложение локализовано и, следовательно, имеет разные тексты в зависимости от вашего языка.

2. @basedgod разве мы не можем использовать key в текстовом виджете? « BottomNavigationBarItem ( значок: Icon ( Icons.settings), заголовок: Текст ( ‘Настройки’, клавиша: const Key (‘настройки’), ),`» кажется, у меня это работает.

3. Да, как и в bsr, у меня сработало наложение клавиши на значок.

4. Похоже, что flutter_driver это больше не рекомендуемый способ: docs.flutter.dev/testing/integration-tests/migration

Ответ №2:

Как упоминалось @bsr и @user12563357 — вы можете использовать клавишу для текстового виджета:

 bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.shifting,
        key: Key('bottom'),
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.ac_unit),
            title: Text('First', key: Key('first'),)
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.cast),
            title: Text('Second', key: Key('second'),)
          )
        ],
      ),
  

и найдите текст, чтобы щелкнуть по элементу панели в test:

 final firstItem = find.byValueKey('first');
await driver.tap(firstItem);
  

кстати: вы также можете найти BottomNavigationBarItem с помощью find.ancestor

 find.ancestor(of: firstItem, matching: find.byType("BottomNavigationBarItem"));
  

но вы не можете нажать на него.

Комментарии:

1. Сработает ли установка клавиши на значок?

Ответ №3:

У вас есть два варианта — с помощью значка или с текстом, получая локализацию из контекста.

Вы можете получить состояние любого вида StatefulWidget.

 final MyWidgetState state = tester.state(find.byType(MyWidget));
  

с помощью этого вы можете получить контекст, а с ним и текущую локализацию.

 final l10n = AppLocalizations.of(state.context);

await tester.tap(find.text(l10n.youTitle));
  

Еще один вариант — получить виджет по значку:

 await tester.tap(find.byIcon(Icons.your_icon));
  

Ответ №4:

 bottomNavigationBar: BottomNavigationBar(
        type: BottomNavigationBarType.shifting,
        key: Key(`bottom`),
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.ac_unit, color: Colors.green,),
            title: InkWell(child:Text(`First`, style: TextStyle(color: Colors.black),key:Key(`First`)),)
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.cast, color: Colors.yellow,),
            title:  InkWell(child:Text(`Second`, style: TextStyle(color: Colors.black),key:Key(`Second`)),)
          )
        ],
      ),


test(`bottomnavigationbar test`, () async {
      await driver.waitFor(find.byValueKey(`bottom`));
      await driver.tap(find.byValueKey(`First`));
      print('clicked on first');
      await driver.tap(find.byValueKey(`Second`));
      print('clicked on second too');
    });
  

Комментарии:

1. Спасибо за ваш ответ, но, пожалуйста, объясните код и как / почему это работает. Просто с помощью кода трудно понять ответ.

2. Добавьте виджет «InkWell» в качестве заголовка для BottomNavigationBarItem и добавьте текст в качестве дочернего элемента для InkWell. Теперь у вас может быть статический английский ключ для виджета InkWell, который не нужно менять в зависимости от локали, и после этого с помощью api «driver.tap (find.byValueKey(‘key’))» вы можете реализовать функциональность BottomNavigationBarItem ontap.