未熟学生エンジニアのブログ

Tetsuの個人開発ブログ

FlutterやWeb周り全般、チーム開発について書くブログ

Flutter Webのテストコードを書く際のトラブルシューティング集

$ flutter test --platform chrome$ flutter test でFlutter web用のテストをする際のトラブルシューティングとして、自分が遭遇・解決したものをまとめました。

FlutterやFirebaseの公式IssueやStack Overflowに散らばっている情報を色々試してみてうまくいったものを書いていますが、環境によっては動かないものもあるかもしれません。まだまだFlutter webの開発は大変だと感じていますが、Issueを追うのは勉強になりますね。

環境

  • Flutter channel dev 1.20.0-2.0.pre
  • PC: macOS 10.15.5
  • CI: subosito/flutter-action@v1 (最後にworkflowファイルあり)

1. --platform chrome を使う場合のエラー

Unable to find modules for some sources

Please check the following imports: import 'generated_plugin_registrant.dart'; from flutter_novel|lib/main_web_entrypoint.dart at 5:1

もう少し詳細なエラー出力

Unable to find modules for some sources, this is usually the result of either a
bad import, a missing dependency in a package (or possibly a dev_dependency
needs to move to a real dependency), or a build failure (if importing a
generated file).

Please check the following imports:

import 'generated_plugin_registrant.dart'; from flutter_novel|lib/main_web_entrypoint.dart at 5:1

Failed after 45.5s
Failed to compile tests
##[error]Process completed with exit code 1.

原因

lib/generated_plugin_registrant.dart は、以下の例のように自動生成されるようです。

//
// Generated file. Do not edit.
//

// ignore: unused_import
import 'dart:ui';

import 'package:url_launcher_web/url_launcher_web.dart';

import 'package:flutter_web_plugins/flutter_web_plugins.dart';

// ignore: public_member_api_docs
void registerPlugins(PluginRegistry registry) {
  UrlLauncherPlugin.registerWith(registry.registrarFor(UrlLauncherPlugin));
  registry.registerMessageHandler();
}

しかし、エラーになる場合は、このファイルの中身が開発環境でビルドした場合とCIでビルドした場合で異なることがあるようです。開発環境でのテストが通る場合は、これが原因です。

その理由は、Flutterプロジェクトを作る際のデフォルトの.gitignore では lib/generated_plugin_registrant.dart は ignore対象となっており、開発環境のファイルをCIで使っていないためです。ない場合は自動生成されるはずです。

.gitignore(一部)

# Web related
lib/generated_plugin_registrant.dart

解決法

開発環境でビルドした場合とCIでビルドした場合で異ならないように、これを ignore対象から外し、lib/generated_plugin_registrant.dart をコミットします。

.gitignoreの一部

# Web related
# lib/generated_plugin_registrant.dart
$ git add lib/generated_plugin_registrant.dart
$ git commit -m "<任意のコミットメッセージ>"
$ git push 

2. --platform chrome を使わない場合のエラー

No such file or directory import 'package:analyzer/dart/analysis/results.dart';

または、

No such file or directory import 'package:analyzer/dart/analysis/utilities.dart';

もう少し詳細なエラー出力

/opt/hostedtoolcache/flutter/1.20.0-0.0.pre-dev/x64/packages/_flutter_web_build_script/lib/build_script.dart:9:8: Error: Error when reading '/b/s/w/ir/k/archive/flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-0.39.8/lib/dart/analysis/results.dart': No such file or directory
import 'package:analyzer/dart/analysis/results.dart';
       ^
/opt/hostedtoolcache/flutter/1.20.0-0.0.pre-dev/x64/packages/_flutter_web_build_script/lib/build_script.dart:10:8: Error: Error when reading '/b/s/w/ir/k/archive/flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-0.39.8/lib/dart/analysis/utilities.dart': No such file or directory
import 'package:analyzer/dart/analysis/utilities.dart';

原因

原因はよくわからなかったです。パッケージのバージョンの問題?のようですが・・

参考: Swapping Flutter SDKs via IDE doesn't work with web builds. · Issue #2012 · Dart-Code/Dart-Code · GitHub

解決策

$ flutter update-packages を実行すると動きます。

3. Firebase関連

top_level.dart:1:8: Error: Not found: 'dart:html' import 'dart:html';

Error: Not found: 'dart:js' export 'dart:js' show allowInterop, allowInteropCaptureThis;

もう少し詳細なエラー出力

/opt/hostedtoolcache/flutter/1.20.0-2.0.pre-dev/x64/.pub-cache/hosted/pub.dartlang.org/firebase-7.3.0/lib/src/top_level.dart:1:8: Error: Not found: 'dart:html'
import 'dart:html';
       ^
/opt/hostedtoolcache/flutter/1.20.0-2.0.pre-dev/x64/.pub-cache/hosted/pub.dartlang.org/js-0.6.2/lib/js.dart:8:1: Error: Not found: 'dart:js'
export 'dart:js' show allowInterop, allowInteropCaptureThis;

原因と解決策

firebaseなどをpubspec.yamlに書いてmobile版をビルドする際に、dart:html系のエラーが出るらしいです。参考: Add Firebase to Flutter mobile and web | by Praharsh Bhatt | Multiverse Software | Medium

Flutter webだけで使えるようなパッケージを使うテストでは、必ず $ flutter test --platform chrome を使いましょう。$ flutter test --platform chrome test/x_test.dart$ flutter test --platform chrome test/foo_directory のように、特定のファイルやフォルダだけを対象にすることもできます。以下のように、フォルダによって--platform chromeをつけるテストとつけないテストを分けて両方実行するようにすると良いと思います。

$ flutter test --platform chrome test/web
$ flutter test --coverage test/not_web

おまけ:自分が使っているGitHub Actions 用 workflow

name: Flutter CI

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  my-job:
    name: Flutter analyze and test
    runs-on: macos-10.15
    steps:
    - uses: actions/checkout@v1
    - uses: actions/setup-java@v1
      with:
        java-version: '12.x'
    - uses: subosito/flutter-action@v1
      with:
        flutter-version: '1.20.0-2.0.pre'
        channel: 'dev'

    - name: Flutter analyze and test
      run: |
        flutter update-packages
        flutter pub get
        flutter analyze
        flutter test --platform chrome test/web
        flutter test --coverage test/not_web 

My Twitter

https://twitter.com/tetsufe_twitter.com