• トップ
  • ブログ一覧
  • 【Flutter】長押しでドラッグ可能になるWidgetのWidgetTest
  • 【Flutter】長押しでドラッグ可能になるWidgetのWidgetTest

    広告メディア事業部広告メディア事業部
    2022.09.29

    IT技術

    はじめに

    FlutterのWidgetTesterにはlongPress のようなメソッドや、drag などのドラッグ用のメソッドが用意されているのですが、長押しでドラッグ可能になってから動かすlongPressDrag のようなものはメソッドは用意されていません。

    そこで、DraggableのWidgetTestを参考に長押しをしたあとにドラッグ可能になるWidgetのWidgetTestを書いてみたメモを残そうと思います。

    同じようなテストを書こうと思った方の参考になれば幸いです。

    開発環境

    開発環境は下記のとおりです。

    Flutter3.3.2

    使用パッケージ

    0.5.0
    2.0.0-dev.9
    mockito
    5.3.1
    build_runner
    2.2.1

    テスト実装

    テスト対象Widget

    今回「長押しでドラッグ可能になるWidget」として並び替えができるreorderablesパッケージのReorderableColumn ReorderableWidget を使ったWidgetのテストを書いてみます。

    対象のWidgetのファイルは下記の通りです。

    1import 'package:flutter/material.dart';
    2import 'package:flutter_riverpod/flutter_riverpod.dart';
    3import 'package:reorderables/reorderables.dart';
    4
    5final draggableListProvider = Provider<DraggableListController>((ref) {
    6  return const DraggableListController();
    7});
    8
    9class DraggableListController {
    10  const DraggableListController();
    11
    12  void onReorder(int oldIndex, int newIndex) {
    13    print('oldIndex: $oldIndex');
    14    print('newIndex: $newIndex');
    15  }
    16}
    17
    18class DraggableList extends ConsumerWidget {
    19  const DraggableList({super.key});
    20
    21  @override
    22  Widget build(BuildContext context, WidgetRef ref) {
    23    return ReorderableColumn(
    24      onReorder: (oldIndex, newIndex) {
    25        ref.read(draggableListProvider).onReorder(oldIndex, newIndex);
    26      },
    27      children: List.generate(10, (index) {
    28        return ReorderableWidget(
    29          key: Key(index.toString()),
    30          reorderable: true,
    31          child: Text(index.toString()),
    32        );
    33      }),
    34    );
    35  }
    36}

    余談ですが、今回は並び替えたときに任意の処理が正しく実行されることを確認したいので、DraggableListController というクラスを用意し、Provider の値をテスト時にオーバーライドできるようにしています。

    Widget Test

    それでは、上記のWidgetのテストを書いていきます。

    テストで確認したいことは「並び替えを行った場合 並び替え時の処理が実行されること」なので、「0というテキストが表示されているWidgetを9というテキストが表示されている箇所まで移動したら、任意の処理が実行されること」が確認できればよさそうです。

    今回のメインである長押ししてドラッグする動きをテストで表す方法ですが、テスト用のジェスチャーを生成するstartGesture というメソッドを使います。

    具体的には、

    1    // ジェスチャーの開始地点を決定
    2    final firstLocation = tester.getCenter(find.text('0'));
    3    final gesture = await tester.startGesture(firstLocation);
    4
    5    // ドラッグ可能になるまで待機
    6    await tester.pump(const Duration(seconds: 1));
    7
    8    // 対象の箇所まで開始地点から移動
    9    await gesture.moveTo(tester.getCenter(find.text('9')));
    10    await tester.pump();

    という形で書くことで長押しドラッグが実現できます。

    以下、テストコード全体です。

    1import 'package:flutter/material.dart';
    2import 'package:flutter_riverpod/flutter_riverpod.dart';
    3import 'package:flutter_test/flutter_test.dart';
    4import 'package:long_press_draggable_widget_test_sample/draggable_list.dart';
    5import 'package:mockito/annotations.dart';
    6import 'package:mockito/mockito.dart';
    7
    8import 'widget_test.mocks.dart';
    9
    10@GenerateMocks([
    11  DraggableListController,
    12])
    13void main() {
    14  testWidgets('並び替えを行った場合 並び替え時の処理が実行されること', (WidgetTester tester) async {
    15    final controller = MockDraggableListController();
    16    await tester.pumpWidget(
    17      ProviderScope(
    18        overrides: [
    19          draggableListProvider.overrideWithValue(controller),
    20        ],
    21        child: const MaterialApp(
    22          home: Scaffold(
    23            body: DraggableList(),
    24          ),
    25        ),
    26      ),
    27    );
    28
    29    // ジェスチャーの開始地点を決定
    30    final firstLocation = tester.getCenter(find.text('0'));
    31    final gesture = await tester.startGesture(firstLocation);
    32
    33    // ドラッグ可能になるまで待機
    34    await tester.pump(const Duration(seconds: 1));
    35
    36    // 対象の箇所まで開始地点から移動
    37    await gesture.moveTo(tester.getCenter(find.text('9')));
    38    await tester.pump();
    39
    40    // ジェスチャーを解除
    41    await gesture.up();
    42    await tester.pump();
    43
    44    // 並び替え処理が呼び出されたことを確認
    45    verify(controller.onReorder(0, 9)).called(1);
    46  });
    47}

    まとめ

    今回は長押しでドラッグ可能になるWidgetのWidgetTestを書いてみました。

    Flutterリポジトリ内のテストコードを見ていると勉強になることも多いので、これからもちょこちょこ覗いてみようと思います!

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!社長と一杯しながらお話しする機会もご用意しております。そのほかカジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    広告メディア事業部

    広告メディア事業部

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background