対象者
- Flutterの非同期処理やストリームのテストに関心があるエンジニア
- プロジェクトでFlutterを採用しており、ストリームテストの知識を深めたいと考えている人
- 技術的なスキル向上を目指している学習意欲の高い開発者
はじめに
Flutterを使ってアプリ開発を行っているあなた。非同期処理やStreamの動作に対して不安を感じていませんか?この記事では、DartでStreamの動作を確認できるようになるべく、Streamのテストに関する基礎を分かりやすく解説し、あなたの疑問を解消します。
この記事を読むことで、Streamのテストに関する全体像がつかめ、自信を持ってテストを実装できるようになります。
Streamテストの基礎
ベース
シンプルなストリームのテスト。
Stream.fromIterable: イテラブルからストリームを作成emitsInOrder: ストリームが順番に要素を放出することを確認
final stream = Stream.fromIterable([
'Ready.',
'Set',
'Go!',
]);
expect(
stream,
emitsInOrder([
'Ready.',
'Set',
'Go!',
]),
);
いろんなMatcher
異なるMatcherを使ったストリームのテスト。
startsWith: 文字列が特定の文字で始まるかを確認emitsAnyOf: いずれかの要素を放出することを確認emitsDone: ストリームの終了を確認
final stream = Stream.fromIterable([
'Ready.',
'Set',
'Go!',
]);
expect(
stream,
emitsInOrder([
'Ready.',
startsWith('S'),
emitsAnyOf(['Go!', 'False Start!']),
emitsDone,
]),
);
addを使ったテスト
StreamControllerを使用して手動でストリームに値を追加するテスト。
StreamController: 手動でストリームに値を追加add: ストリームに値を追加emitsInOrder: 順番に要素を放出することを確認
final stream = StreamController<int>();
stream.add(1);
stream.add(2);
stream.close();
expect(
stream.stream,
emitsInOrder([1, 2, emitsDone]),
);
expect を前にもかける
expectをストリームに値を追加する前に使用するテスト。
StreamController: 手動でストリームに値を追加expect: テストの期待値を設定
final stream = StreamController<int>();
expect(
stream.stream,
emitsInOrder([1, 2, emitsDone]),
);
stream.add(1);
stream.add(2);
stream.close();
expectLater
expectLaterを使用して遅延ストリームのテストを行う。
StreamController: 手動でストリームに値を追加expectLater: 非同期でストリームの期待値を設定
expectに変えても動作する。違いが分からん(後で検証するよ、という意思表示かな)
final stream = StreamController<int>();
Future<void> addWithDelay(int value) async {
Future.delayed(const Duration(milliseconds: 10)).then((_) {
stream.add(value);
});
}
expectLater(
stream.stream,
emitsInOrder([1, 2, emitsDone]),
);
addWithDelay(1);
addWithDelay(2);
// close するまえに、データを入れるため
await Future.delayed(const Duration(milliseconds: 10));
stream.close();
処理の遅い処理 listenを使ってみる
listenを使って遅延ストリームの処理をテストする。
StreamController: 手動でストリームに値を追加listen: ストリームの要素をリッスンして処理Completer: 非同期処理の完了を待つためのオブジェクト
final stream = StreamController<int>();
Future<void> addWithDelay(int value) async {
Future.delayed(const Duration(milliseconds: 10)).then((_) {
stream.add(value);
});
}
var completer = Completer<int>();
stream.stream.listen((int data) {
completer.complete(data);
});
addWithDelay(1);
expect(await completer.future, 1);
completer = Completer<int>();
addWithDelay(2);
expect(await completer.future, 2);
stream.close();
Q&A
Q1: expectとexpectLaterの違いは何ですか?
expectは通常の同期的なテストに使用され、expectLaterは非同期処理を伴うテストで使用されます。今回の例ではどちらも同じように動作しますが、非同期処理を扱う際にはexpectLaterを使うのが一般的です。
Q2: emitsInOrderとは何ですか?
emitsInOrderは、ストリームが特定の順序で要素を放出することを確認するMatcherです。複数の要素を順番に放出するストリームの動作をテストするのに便利です。
Q3: StreamControllerとは何ですか?
StreamControllerは、手動でストリームにデータを追加できるコントローラーです。ストリームにデータを追加したり、ストリームを閉じたりするために使用します。
参考
まとめ
本記事では、Flutterでのストリームのテスト方法について紹介しました。基本的なストリームの操作から、さまざまなMatcherを使用したテスト方法、遅延処理を伴うストリームのテスト方法について学びました。これらの知識を活用して、非同期処理を含むアプリケーションのテストを効果的に行いましょう。