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

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

```console
$ 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`でそのまま出力すると、こんなレポートがコンソールに流れます。

```console
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をひたすら吐かれるので、まあ一応、リダイレクトでファイルに出すのが良いでしょうね。

```console
$ flutter test --machine > machine.log
```

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

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

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

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

```console
$ flutter pub global activate dart_dot_reporter
```

これだけ。

## 2.使う

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

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

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

|![dart_dot_reporter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/c45eab85-04e8-8500-78bb-bd467df42797.png)|
|:--|

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

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

|![show-message.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/4f12c686-5dfa-fc68-e82e-5c428ee3e2f4.png)|
|:--|

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

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

そんなときは、[junitreport](https://pub.dev/packages/junitreport)というパッケージが使えます。

## 1.インストール

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

```console
$ flutter pub get
$ flutter pub global activate junitreport
```

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

```console
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です)

```bash:
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を使います。

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

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

# htmlで書き出す

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

[junit2html](https://github.com/inorton/junit2html)というのを使ってみます。

# 1.インストール

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

```console
$ sudo pip install junit2html
```

## 2.使う

```console
$ junit2html JUNIT_XML_FILE [NEW_HTML_FILE]
```

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

|![junit2html.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/7b653952-f9e1-2faa-a5c8-ee9168a4de57.png)|
|:--|

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

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

|![html_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103886/6f204ede-84e4-7b78-c8c7-db9f2b987566.png)|
|:--|

junit xmlをhtmlに変換するツールは探せば他にもありそうなので、お好みな物を探してみるのもいいでしょうね。とはいえ、[xunit-viewer](https://github.com/lukejpreston/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](https://devcenter.bitrise.io/jp/getting-started/getting-started-with-flutter-apps/)だけっぽい？

まあ、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