はじめに
FlutterでWidget Testをする場合、生成したWidget内で「どのWidgetが」「いくつあるのか(ないのか)」をexpectで確かめる。
この 「どのWidgetが」 に当たる部分をFinderで指定する。
例えば、これは公式のWidget Testのドキュメントに書いてあるコードなんだけど、
final titleFinder = find.text('T');
final messageFinder = find.text('M');
expect(titleFinder, findsOneWidget);
expect(messageFinder, findsOneWidget);
'T'と表示しているTextや、'M'と表示しているTextが、生成したWidgetに1つ含まれているかを確認している。
このFinderには結構種類かあって、使い分けることで色んなWidgetをスマートに取得することができる。
この記事では、そんなFlutterのWidget TestにおけるFinderについてまとめるよ。
find.text()
指定した文字列を含むText・EditText・RichTextを探す。
使い方
Text('Pikachu');
expect(find.text('Pikachu'), findsOneWidget);
find.textContaining()
指定したPatternにマッチしたText・EditText・RichTextを探す。
正規表現とかを渡して、柔軟にWidgetを探すことができる。
使い方
Text('Pikachu');
expect(find.textContaining(RegExp(r'^Pika.*')), findsOneWidget);
find.widgetWithText()
指定した文字列を持つ、指定した型のWidgetを探す。
厳密に探せるので使いやすい。
使い方
PokemonName(
child: Text('Pikachu'),
);
expect(find.widgetWithText(PokemonName, 'Pikachu'), findsOneWidget);
find.image()
指定したimageを含むImage・FadeInImageを探す。
使い方
Image.asset('images/pikachu.png');
expect(find.image(Image.asset('images/pikachu.png').image), findsOneWidget);
find.byKey()
指定したKeyを持つWidgetを探す。
使い道が幅広くて便利。
使い方
Text('Pikachu', key: Key('Pikachu'));
expect(find.byKey(Key('Pikachu')), findsOneWidget);
find.bySubtype()
指定した型のサブクラスのWidgetを探す。
あんま使わなそう。
使い方
abstract class Pokemon extends StatelessWidget {}
class Pikachu extends Pokemon {}
Pikachu();
expect(find.bySubType<Pokemon>(), findsOneWidget);
find.byType()
指定した型のWidgetを探す。
条件でWidgetを出し分けてる時なんかに使える。
使い方
Pikachu();
expect(find.byType(Pikachu), findsOneWidget);
find.byIcon()
指定したiconを持つIconを探す。
もともと入ってるIconsを多用している場合には便利かもしれない。
使い方
Icon(Icons.add);
expect(find.byIcon(Icons.add), findsOneWidget);
find.widgetWithIcon()
指定したIconを持つ、指定した型のWidgetを探す。
使い方
Button(
child: Icon(Icons.add)
)
expect(find.widgetWithIcon(Button, Icons.add), findsOneWidget);
find.widgetWithImage()
指定したImageを持つ、指定した型のWidgetを探す。
使い方
Pokemon(
Image.asset('images/pikachu.png'),
);
expect(find.widgetWithImage(Pokemon, Image.asset('images/pikachu.png').image), findsOneWidget);
find.byElementType()
指定したElementの型を持つWidgetを探す。
Elementが何かはここでは触れないよ。
Pikachu();
expect(find.byElementType(Pikachu), findsOneWidget);
find.byWidget()
指定したWidgetを持つWidgetを探す。
同一インスタンスのWidgetを探すので、childに渡したWidgetが表示されてるかどうか確認するために使うんだと思う。
使い方
final nameText = Text('Pikachu');
PokemonName(child: nameText);
expect(find.byWidget(nameText), findsOneWidget);
find.byWidgetPredicate()
自分で指定した条件に合うWidgetを探す。
めちゃくちゃカスタマイズ性能高い。
使い方
Pikachu();
expect(
find.byWidgetPredicate((widget) {
return widget is Pokemon;
}),
findsOneWidget,
);
find.byTooltip()
指定した文字列を含んだTooltipを持つWidgetを探す。
使い方
FloatingActionButton(
onPressed() {},
tooltip: 'pikachu',
);
expect(find.byTooltip('Pikachu'), findsOneWidget);
find.byElementPredicate()
find.byWidgetPredicateのElement版。
※サンプル書くの辛かったので割愛。
find.descendant()
ofで渡したWidgetの子Widgetで、matchingに合うWidgetを探す。
使い方
PokemonList(
child: Pikachu();
);
expect(
find.descendant(
of: find.byType(PokemonList),
matching: find.byType(Pikachu),
),
findsOneWidget,
);
find.ancestor()
ofで渡したWidgetの親Widgetで、matchingに合うWidgetを探す。
使い方
PokemonList(
child: Pikachu();
);
expect(
find.ancestor(
of: find.byType(Pikachu),
matching: find.byType(PokemonList),
),
findsOneWidget,
);
find.bySemanticsLabel()
指定した文字列を含んだsemanticsLabelを持つWidgetを探す。
使い方
Image.asset('images/pikachu.png', semanticLabel: 'Pikachu');
expect(
find.bySemanticsLabel('Pikachu', findsOneWidget)
);
まとめ
- Finderをいい感じに使い分けることで、スマートにWidgetを取得することができるよ。
- 実際使用するFinderには偏りがあるので、よく使うやつを覚えておくといいと思う。
- 色々使ってみて覚えていくといい感じ。
終わり。