LoginSignup
32
25

More than 3 years have passed since last update.

Flutterで単体テストを書く

Last updated at Posted at 2020-12-19

以前こちら(TODOアプリで比較するAndroid(MVVM)とFlutter(Provider)の違い)の記事で紹介した、TODOアプリの単体テストを書いてみました。
やってみてわかったことを共有します。ここはこうすれば解決する!とかこうした方がいい!とかあればコメントくださると嬉しいです。

筆者のレベル

  • Flutterの実務経験なし(やり始めて半年未満)
  • 普段はSIerでインフラエンジニア
  • インフラ周りといってもオンプレミスしかしらない・・・

やったこと

以前私が書いたTODOAppSample-Flutterで単体テストを行いました。
全コードはこちら

基本的には以下の公式ドキュメントにやり方が書いてありますのでご参照ください。
An introduction to unit testing

必要な準備

pubspec.yamlに以下のようにflutter_testが追加されている必要があります。
スクリーンショット 2020-12-14 181511.png
また、私は以下のような環境で実施しました。
OS:Windows 10 Pro 1909
IDE:Android Studio 4.1.1

コード

テストコードですが、プロジェクトルートのtestフォルダの下に、テストしたいdartファイルの名前に_testとつけたファイルを作成してその中に書きます。
スクリーンショット 2020-12-14 181959.png

基本的な単体テストは簡単にかけて、以下のようになります。

test.dart

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 ~~~ をクリックします。
スクリーンショット 2020-12-14 183037.png

テストが流れて結果が画面下部に表示されます。
緑のチェックマークがついていればテストにpassしているということになります。
スクリーンショット 2020-12-14 183316.png

テストに失敗すると、エラーと共に以下のように出力されます。
スクリーンショット 2020-12-14 183434.png
上記の例では期待される結果の日付をわざと変えました。
ExpectedActualが違うということを示してくれます。

結論

この記事のために書いたテストは非常に簡単にかけました。なぜならTodoItemはデータを格納しているだけのエンティティの役割しかないからです。
しかし、他のクラスに対してテストを書こうとすると途端に書けないことに気づきました。

他のclassに対してもテストを行おうとしましたが、私が書いたコードではテストできません。

todo_item_repository.dart
class TodoItemRepository {
  static String table = 'todo_item';
  static DatabaseProvider instance = DatabaseProvider.instance;

DBのインスタンスを内部で生成してしまっているため、mockに置き換えられないためです。

こういうことを起こさないために、インスタンスの生成時にDBのインスタンスを外から渡してあげればよいようです。
個人開発している分にはコアとなるビジネスロジックだけ依存関係に注意しながらコーディングしておいて、テストしやすいようにしておくのが良いと思いました。
そのうちテスタブルなコードに書き換えてまた記事にしようと思います。

2021/02/15 追記

記事にしました!【Flutter】Providerで最低限のDIを行ってテスタブルなコードにリファクタリングする

2021/4/9 追記

こちらの記事に関する発表を行いました。
以下が発表スライドです。

32
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
25