以前こちら(TODOアプリで比較するAndroid(MVVM)とFlutter(Provider)の違い)の記事で紹介した、TODOアプリの単体テストを書いてみました。
やってみてわかったことを共有します。ここはこうすれば解決する!とかこうした方がいい!とかあればコメントくださると嬉しいです。
筆者のレベル
- Flutterの実務経験なし(やり始めて半年未満)
- 普段はSIerでインフラエンジニア
- インフラ周りといってもオンプレミスしかしらない・・・
やったこと
以前私が書いたTODOAppSample-Flutterで単体テストを行いました。
全コードはこちら
基本的には以下の公式ドキュメントにやり方が書いてありますのでご参照ください。
An introduction to unit testing
必要な準備
pubspec.yaml
に以下のようにflutter_test
が追加されている必要があります。
また、私は以下のような環境で実施しました。
OS:Windows 10 Pro 1909
IDE:Android Studio 4.1.1
コード
テストコードですが、プロジェクトルートのtestフォルダの下に、テストしたいdartファイルの名前に_test
とつけたファイルを作成してその中に書きます。
基本的な単体テストは簡単にかけて、以下のようになります。
import 'package:flutter_test/flutter_test.dart';
import 'package:todo_app_sample_flutter/data/todo_item.dart';
void main() {
group("TodoItemのゲッターのテスト", () {
final TodoItem todoItem = TodoItem(
id: 0,
title: 'title',
body: 'body',
createdAt: DateTime(2020, 1, 1),
updatedAt: DateTime(2020, 1, 1),
isDone: true,
);
test('idのテスト', () {
expect(todoItem.getId, 0);
});
flutter_test.dart
とテスト対象のdartファイルをimportします。
main()
の中にtest()
関数を書き、その中で期待する値をexpect(<テスト対象が出力する値>,<期待される結果>)
のように書きます。
test()
が一つのテストケースに対応している感じです。
各test()
をgroup()
でグループ化することもできます。
テスト実行
実行するには以下のようにテストファイル上で右クリックし、実行⇒**test in ~~~** をクリックします。
テストが流れて結果が画面下部に表示されます。
緑のチェックマークがついていればテストにpassしているということになります。
テストに失敗すると、エラーと共に以下のように出力されます。
上記の例では期待される結果の日付をわざと変えました。
Expected
とActual
が違うということを示してくれます。
結論
この記事のために書いたテストは非常に簡単にかけました。なぜならTodoItemはデータを格納しているだけのエンティティの役割しかないからです。
しかし、他のクラスに対してテストを書こうとすると途端に書けないことに気づきました。
他のclassに対してもテストを行おうとしましたが、私が書いたコードではテストできません。
class TodoItemRepository {
static String table = 'todo_item';
static DatabaseProvider instance = DatabaseProvider.instance;
DBのインスタンスを内部で生成してしまっているため、mockに置き換えられないためです。
こういうことを起こさないために、インスタンスの生成時にDBのインスタンスを外から渡してあげればよいようです。
個人開発している分にはコアとなるビジネスロジックだけ依存関係に注意しながらコーディングしておいて、テストしやすいようにしておくのが良いと思いました。
そのうちテスタブルなコードに書き換えてまた記事にしようと思います。
2021/02/15 追記
記事にしました!【Flutter】Providerで最低限のDIを行ってテスタブルなコードにリファクタリングする
2021/4/9 追記
こちらの記事に関する発表を行いました。
以下が発表スライドです。