コンテンツにスキップ

テスト

Testing | Flutter

Flutter ってどうなん?実際に商用アプリ開発で使ってみた感想 #iOS - Qiita

単体テスト

事前準備

flutter_testというパッケージが必要だが、これは Flutter のプロジェクト作成時にデフォルトで入っている。

testディレクトリに*_test.dartを作成する。

test/sample_test.dart
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import 'package:flutter_test/flutter_test.dart';

void main() {
  test("testCase01", () {
    expect(1 + 1, 2);
  });

  test("testCase02", () {
    expect(1 + 1, 3);
  });
}

VSCode でテストコードを開いた状態で F5 キーを押すとテストが実行される。

網羅を確認したい

ブレークポイントを貼り、ステップ実行して確認する。

モックを使用して単体テストしたい

インターフェースを切って差し替え可能にする必要がある。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
abstract class IHttpRequestNotifier extends Notifier<HttpRequest> {
  Future<http.Response> request(String url, RequestMethod method,
      {Map<String, String>? headers,
      String? body,
      Map<String, dynamic>? queryParameters,
      Encoding? encoding});

  bool isRequesting();
}

class HttpRequestNotifier extends IHttpRequestNotifier {
  @override
  HttpRequest build() {
    return const HttpRequest(countOfRequest: 0);
  }
  // ...以下略
}

final httpRequestProvider = NotifierProvider<IHttpRequestNotifier, HttpRequest>(
  () => throw UnimplementedError(),
);

実運用はmain.dartにて実クラスでオーバーライドする。

1
2
3
4
5
6
7
void main() {
  runApp(ProviderScope(overrides: [
    httpRequestProvider.overrideWith(
      () => HttpRequestNotifier(),
    )
  ], child: const MyApp()));
}

テストコードではモックを作ったあと、モックでオーバーライドする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import 'dart:convert';

import 'package:flutter_aws_sandbox/providers/http_request_provider.dart';
import 'package:flutter_aws_sandbox/providers/todo_provider.dart';
import "package:flutter_riverpod/flutter_riverpod.dart";
import 'package:flutter_test/flutter_test.dart';
import "package:http/http.dart" as http;

final sampleGetResponse = jsonEncode([
  {
    "id": "0",
    "title": "title #0",
    "description": "description #0",
    "done": false
  }
]);

class MockHttpRequestNotifier extends IHttpRequestNotifier {
  @override
  HttpRequest build() {
    return const HttpRequest(countOfRequest: 0);
  }

  @override
  Future<http.Response> request(String url, RequestMethod method,
      {Map<String, String>? headers,
      String? body,
      Map<String, dynamic>? queryParameters,
      Encoding? encoding}) async {
    if (url.endsWith("/todos") && method == RequestMethod.get) {
      print("Return json");
      return http.Response(sampleGetResponse, 200);
    }

    final response = http.Response("", 200);
    return response;
  }

  @override
  bool isRequesting() {
    return state.countOfRequest >= 1;
  }
}

final mockHttpRequestProvider =
    NotifierProvider<MockHttpRequestNotifier, HttpRequest>(
  () => MockHttpRequestNotifier(),
);

void main() {
  late ProviderContainer container;

  setUp(() {
    container = ProviderContainer(overrides: [
      httpRequestProvider.overrideWith(() => MockHttpRequestNotifier())
    ]);
  });

  group("methodTest", () {
    test("get", () async {
      List<Todo> expected = jsonDecode(sampleGetResponse)
          .map<Todo>((data) => Todo.fromJson(data))
          .toList();

      await expectLater(
          container.read(todoProvider.future), completion(expected));
    });
  });
}

AsyncProvider(AsyncValue)の値をチェックしたい

Testing your providers | Riverpod

【Flutter】AsyncNotifier をテストする #Mockito - Qiita

以下のような感じで書く。

1
await expectLater(container.read(todoProvider.future), completion(expected));

ウィジェットテスト

統合テスト

integration_testというパッケージが必要だが、これは Flutter のプロジェクト作成時にデフォルトで入っている。