【Flutter】Finderまとめ【Widget Test】

# はじめに

FlutterでWidget Testをする場合、生成したWidget内で「どのWidgetが」「いくつあるのか(ないのか)」をexpectで確かめる。
この **「どのWidgetが」** に当たる部分をFinderで指定する。

例えば、これは公式のWidget Testのドキュメントに書いてあるコードなんだけど、

```dart
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を探す。

### 使い方

```dart
Text('Pikachu');

expect(find.text('Pikachu'), findsOneWidget);
```

## find.textContaining()

指定したPatternにマッチしたText・EditText・RichTextを探す。
正規表現とかを渡して、柔軟にWidgetを探すことができる。

### 使い方

```dart
Text('Pikachu');

expect(find.textContaining(RegExp(r'^Pika.*')), findsOneWidget);
```

## find.widgetWithText()

指定した文字列を持つ、指定した型のWidgetを探す。
厳密に探せるので使いやすい。

### 使い方

```dart
PokemonName(
    child: Text('Pikachu'),
);

expect(find.widgetWithText(PokemonName, 'Pikachu'), findsOneWidget);
```

## find.image()

指定したimageを含むImage・FadeInImageを探す。

### 使い方

```dart
Image.asset('images/pikachu.png');

expect(find.image(Image.asset('images/pikachu.png').image), findsOneWidget);
```

## find.byKey()

指定したKeyを持つWidgetを探す。
使い道が幅広くて便利。

### 使い方

```dart
Text('Pikachu', key: Key('Pikachu'));

expect(find.byKey(Key('Pikachu')), findsOneWidget);
```

## find.bySubtype()

指定した型のサブクラスのWidgetを探す。
あんま使わなそう。

### 使い方

```dart
abstract class Pokemon extends StatelessWidget {}

class Pikachu extends Pokemon {}

Pikachu();

expect(find.bySubType<Pokemon>(), findsOneWidget);
```
## find.byType()

指定した型のWidgetを探す。
条件でWidgetを出し分けてる時なんかに使える。

### 使い方

```dart
Pikachu();

expect(find.byType(Pikachu), findsOneWidget);
```

## find.byIcon()

指定したiconを持つIconを探す。
もともと入ってるIconsを多用している場合には便利かもしれない。

### 使い方

```dart
Icon(Icons.add);

expect(find.byIcon(Icons.add), findsOneWidget);
```

## find.widgetWithIcon()

指定したIconを持つ、指定した型のWidgetを探す。

### 使い方

```dart
Button(
    child: Icon(Icons.add)
)

expect(find.widgetWithIcon(Button, Icons.add), findsOneWidget);
```

## find.widgetWithImage()

指定したImageを持つ、指定した型のWidgetを探す。

### 使い方

```dart
Pokemon(
    Image.asset('images/pikachu.png'),
);

expect(find.widgetWithImage(Pokemon, Image.asset('images/pikachu.png').image), findsOneWidget);
```

## find.byElementType()

指定したElementの型を持つWidgetを探す。
Elementが何かはここでは触れないよ。

```dart
Pikachu();

expect(find.byElementType(Pikachu), findsOneWidget);
```

## find.byWidget()

指定したWidgetを持つWidgetを探す。
同一インスタンスのWidgetを探すので、childに渡したWidgetが表示されてるかどうか確認するために使うんだと思う。

### 使い方

```dart
final nameText = Text('Pikachu');
PokemonName(child: nameText);

expect(find.byWidget(nameText), findsOneWidget);
```

## find.byWidgetPredicate()

自分で指定した条件に合うWidgetを探す。
めちゃくちゃカスタマイズ性能高い。

### 使い方

```dart
Pikachu();

expect(
    find.byWidgetPredicate((widget) {
        return widget is Pokemon;
    }),
    findsOneWidget,
);
```

## find.byTooltip()

指定した文字列を含んだTooltipを持つWidgetを探す。

### 使い方

```dart
FloatingActionButton(
    onPressed() {},
    tooltip: 'pikachu',
);

expect(find.byTooltip('Pikachu'), findsOneWidget);
```

## find.byElementPredicate()

find.byWidgetPredicateのElement版。
※サンプル書くの辛かったので割愛。

## find.descendant()

ofで渡したWidgetの子Widgetで、matchingに合うWidgetを探す。

### 使い方

```dart
PokemonList(
    child: Pikachu();
);

expect(
    find.descendant(
        of: find.byType(PokemonList),
        matching: find.byType(Pikachu),
    ),
    findsOneWidget,
);
```

## find.ancestor()

ofで渡したWidgetの親Widgetで、matchingに合うWidgetを探す。

### 使い方

```dart
PokemonList(
    child: Pikachu();
);

expect(
    find.ancestor(
        of: find.byType(Pikachu),
        matching: find.byType(PokemonList),
    ),
    findsOneWidget,
);
```

## find.bySemanticsLabel()

指定した文字列を含んだsemanticsLabelを持つWidgetを探す。

### 使い方

```dart
Image.asset('images/pikachu.png', semanticLabel: 'Pikachu');

expect(
    find.bySemanticsLabel('Pikachu', findsOneWidget)
);
```

# まとめ

- Finderをいい感じに使い分けることで、スマートにWidgetを取得することができるよ。
- 実際使用するFinderには偏りがあるので、よく使うやつを覚えておくといいと思う。
- 色々使ってみて覚えていくといい感じ。

終わり。