flutterでテストしていて理解を深めたいポイントをまとめています。
今回はpumpAndSettleメソッドについてまとめました。
目次
公式
pumpAndSettle method - WidgetTester class - flutter_test library - Dart API
API docs for the pumpAndSettle method from the WidgetTester class, for the Dart programming language.
概要
pumpAndSettleメソッドとは
- pumpメソッドを繰り返し実行するメソッド
- 特徴
- フレームがスケジュールされていなくても1回は必ず呼ばれる
- 全てのアニメーションが完了を促す
フレームがスケジュールされるとは
- 次回のフレーム処理(UI 更新)をキューに積む状態
「フレームがスケジュールされていない」状態は
これは逆に言えば、
- アニメーションもしていない
- 状態も更新されていない
- ユーザー操作による描画要求もない
という静止状態です。
普通はこの場合、新しいフレームは不要なので何もスケジュールされません。
pumpAndSetteとフレームのスケジュールの関係
- pupmAndSettleはフレームがスケジュールされていなくても一回は呼ばれる
- その後、「もうフレームが必要ない状態になるまで」繰り返す。 → つまり、スケジュールされたフレームがゼロになるまで待つ。
状態更新 (setStateなど) → フレームスケジュール → pumpで描画 → settle判定
何もない静止状態 → (フレームなし) → pumpAndSettleが1回pumpして終了参考例
内容
- ログイン済みかどうかでWidgetを出し分けている(Firebase)
- 未ログインの時に
LogInウィジェットを表示できているかテスト
全体のソースコード
testWidgets('未ログインならLogInを表示', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
authStateProvider.overrideWith((ref) => Stream.value(null)),
],
child: const MaterialApp(home: App()),
),
);
// ビルドが終わるまで呼び続ける
await tester.pumpAndSettle();
expect(find.byType(LogIn), findsOneWidget);
});
pumpAndSettleの使い方
- authStateProviderというUserの状態を監視するProviderをpumpWidgetしている
- 何も定義がないとUIが更新されずLogInウィジェットは見つからない
- pumpWidgetだとDurationをStreamが完了するまでの秒数与えないといけないが不透明でわかりにくい
- pumpAndSettleで描画が終わるまでpumpし続けることでUIの更新が完了する
- その後
expectでLogInメソッドを検知できる
- その後
pumpAndSettle シーケンス図
Tester WidgetTree EventLoop SchedulerBinding
| | | |
| pumpAndSettle() | | |
|-------------------->| | |
| pump() | | |
|-------------------->| | |
| | flush microtasks | |
| |----------------------->| |
| | authStateProviderのStreamイベント処理 |
| |<-----------------------| |
| | setState() | |
| |------------------------| scheduleFrame() |
| | |-------------------------->|
| | | hasScheduledFrame = true
| | |<--------------------------|
| pump 2nd frame | | |
|-------------------->| | |
| | Rebuild UI | |
| |------------------------| |
| | 完了 → フレームなし | |
| | | hasScheduledFrame = false |
| pumpAndSettle終了 | | |
解説
- 最初の
pumppumpAndSettleは必ず最初に 1 回pumpして、保留中のマイクロタスクを flush(全実行)。- この時点で
authStateProviderのStream.value(null)のイベントが処理される。
- マイクロタスク内でフレームスケジュール
Streamの購読処理でsetStateが呼ばれる。setState→SchedulerBinding.scheduleFrame()によりhasScheduledFrame = trueになる。
- 次のフレーム描画
pumpAndSettleが「まだフレームが必要だ」と判断し、次のpumpで UI を再構築。LogInウィジェットがツリーに現れる。
- フレームがなくなって settle
- UI が安定(フレームが不要)になったらループ終了。
- このタイミングで
expect(find.byType(LogIn), findsOneWidget)が通る。
まとめ
- pumpAndSettleは繰り返しフレームを更新
- フレームがスケジュールされている限り実行する
- repeatなどでアニメーションを繰り返す場合は注意
簡単ですが、pumpAndSettleについてまとめてみました。ではまた。



コメント