FlutterのUnitTestレポートを見やすくしたい


訳あって最新版を使っていません(macをCatalinaにアップデートできない==Xcodeの最新版を入れられないので)。
従って、バージョン違いによる不動作などあるかも知れません。お気づきの点があったら是非コメント下さい。

$ flutter --version
Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 27321ebbad (4 months ago) • 2019-12-10 18:15:01 -0800
Engine • revision 2994f7e1e6
Tools • Dart 2.7.0

Flutterテストの標準出力

flutter testでそのまま出力すると、こんなレポートがコンソールに流れます。

00:08 +26: ... MainPageのテスト CalendarWidgetのチェック
00:08 +26 -1: /workspace/flutter/Recorder/test/data/Record_test.dart:
Recordクラス static関数テスト 強制FailTest [E]
  Expected: false
    Actual: <true>

  package:test_api                                   expect
  package:flutter_test/src/widget_tester.dart 234:3  expect
  data/Record_test.dart 15:7                  main.<fn>.<fn>
00:09 +34 -1: ... MainPageのテスト Widgetのチェック
00:09 +35 -1: ... MainPageのテスト Widgetのチェック
00:09 +35 -1: ... MainPageのテスト フッターのチェック
00:09 +36 -1: ... MainPageのテスト フッターのチェック
 00:09 +36 -1: ... MainPageのテスト セルのタップで入力画面に遷移
00:10 +36 -1: ... MainPageのテスト セルのタップで入力画面に遷移
00:10 +37 -1: ... MainPageのテスト セルのタップで入力画面に遷移
00:10 +37 -1: Some tests failed. 

が、どうやらテストファイル毎に別スレッドで実行されているらしく、出力される順番がなんだかグチャグチャです。
そしてそのせいか、テスト名がおかしなことになっています。
とりあえず、実行したテストの数は合っているようですし、失敗数や成功数も分かりますが・・・

これでは、本当に失敗しているテストの名前が合っているか、確認が必要です。
非常に見づらい!

ということで、人間の目で見やすいテストレポートを出せないか探してみました。

jsonで出力する

実は、デフォルトで、json形式で吐いてくれるオプションがあります。

$ flutter test --machine

です。

そのままだと、コンソールにjsonをひたすら吐かれるので、まあ一応、リダイレクトでファイルに出すのが良いでしょうね。

$ flutter test --machine > machine.log

jsonファイルなんで、JsonViewerとかブラウザに拡張機能などを入れていれば、一応読めなくはないです。でも、失敗したテストを探すのは大変そうです。

コンソール上で分かりやすく出力する

dart_dot_reporterというパッケージと使うと、--machineオプションで出したjsonを元に、コンソールに成功テストと失敗テストの数を分かりやすく出してくれます。

1.インストール

Installingのタブにあるとおりにインストールしましょう。

$ flutter pub global activate dart_dot_reporter

これだけ。

2.使う

まず--machineオプションでjsonを出力して、それをツールに渡します。

$ flutter test --machine > machine.log || echo 'Tests done.'
flutter pub global run dart_dot_reporter machine.log

結果はこんな感じになります。

色も付いて、エラーになったテスト関数も分かって、なかなか良いです。

--show-messageオプションを付けると、もう少し詳しく出してくれます。

とりあえず個人で開発していて失敗テストの有無、その関数名が分かれば良い程度だったら、十分使えそうです。

xmlで出力する

CIで回すことを考えると、Junitのようなxmlレポートが欲しいことがあるでしょう。

そんなときは、junitreportというパッケージが使えます。

1.インストール

まずDartパッケージをインストールします。

$ flutter pub get
$ flutter pub global activate junitreport

ここで、二つ目のコマンドの時に、何やら次のようなメッセージが出るかと思います。

Warning: Pub installs executables into /develop/flutter/.pub-cache/bin, which is not on your path.
You can fix that by adding this to your shell's config file (.bashrc, .bash_profile, etc.):

  export PATH="$PATH":"/develop/flutter/.pub-cache/bin"

pathの詳細はflutterのSDKを実際にインストールしている場所によって変わりますが、要するに、PATHを追加しろと言っています。
ので、素直に追加して上げましょう。
なお、これだけでは足りなくて、次も足した方が良いようです。
<flutter SDKのインストールpath>/bin/cache/dart-sdk/bin

.bash_profileはこうなりました。(※当方Macです)

export PATH=$PATH:/develop/flutter/bin
export PATH=$PATH:/develop/flutter/bin/cache/dart-sdk/bin
export PATH=$PATH:/develop/flutter/.pub-cache/bin

ターミナルを再起動するか、sourceコマンドで反映させて下さいね。

2.使う

このパッケージも、--machineオプションで出したjsonを使います。

flutter test --machine | tojunit --output <Your output file>.xml

これでxmlを書き出してくれます。
xmlファイルを解析してテスト結果を表示してくれるCIツールならば、これがあれば十分ですね。

htmlで書き出す

CIツールがxml形式のテスト結果のビューページを表示してくれない場合(Github ActionsとかGithub Actionsとか)、人間の目にもっと見やすいhtml形式が欲しい物ですね。
出来ればGradleが出してくれるようなのが慣れていていいですが、取り敢えず多くは望まないことにします。

junit2htmlというのを使ってみます。

1.インストール

ソースコードを落としてきてPythonを実行するのでも良いですが、Macなのでpipを使ってインストールすることにします。

$ sudo pip install junit2html

2.使う

$ junit2html JUNIT_XML_FILE [NEW_HTML_FILE]

[JUNIT_XML_FILE]には、junitreportで出力したxmlファイルを指定します。
出力されたhtmlは、こんな感じです。

※すみません、完全に個人の趣味で作っているアプリで、恥ずかしいのでいろいろ推測されそうなパッケージ名ぼかしてます(汗)

失敗テストを探すのはちょっと大変ですが、一応人間の目で見やすくなりました。
失敗テストはこんな風な表示です。

junit xmlをhtmlに変換するツールは探せば他にもありそうなので、お好みな物を探してみるのもいいでしょうね。とはいえ、xunit-viewerくらいしか見つけられなかったですが。

テストスクリプトにする

dart_dot_reporterとhtmlへの出力を合わせ技で全部やってみようと思います。
この場合、スクリプトにしておかないといちいちコマンド打つのは大変です。

ルート直下にtest.shというファイルを作成して、次のようにしました。

test.sh
#!/bin/sh

mkdir -p ./test-reports/ 2>/dev/null

flutter test --machine > machine.log
cat machine.log | tojunit --output ./test-reports/TEST-results.xml
echo 'Tests done.'
flutter pub global run dart_dot_reporter machine.log
junit2html ./test-reports/TEST-results.xml ./test-reports/index.html

これで、スクリプトを実行すればflutterのUnitTest/WidgetTestを実行して、コンソールとhtmlファイルにレポートを出力できるようになりました。

感想

Gradleって優秀だなあ・・・個人的には、html形式のテストレポートでは、Gradleが吐き出すのが一番見やすいと思ってます。次がJenkins。htmlファイルを吐いてくれるわけじゃないですが、結果ページが見やすいですよね。

さて、CIツールどこに登録しようかな。
軽く調べた感じだと、Flutterに対応しているのはBitriseだけっぽい?

まあ、LinuxやmacOSのイメージ上でコマンドレベルで全部インストールしてやっていけばCircleCIでもGithub Actionsでも出来ないこと無いんでしょうけど^^;

CDまで考えると、Bitriseが一番良さそうではありますが、フリープランだと実行時間が10分制限あるし(Androidのエミュレーターテストまで入れるとゆうに超える)、それ以上のプランだとそこそこお金がかかるので、広告入れたとしても多分ペイできない・・・ぶつぶつ・・・

参考

Flutter Test Reports : Current state of art
https://medium.com/ideas-by-idean/flutter-test-reports-in-cis-current-state-of-art-8968b0c8dd4a