Flutterのテストカバレッジを計測してSlackに投稿するまで
背景
Flutterを触り始めて3ヶ月ぐらい経つのですが、テストカバレッジに関してもそろそろ貢献していきたいと考えてきました。ということで自分が開発に関わっているアプリケーションのテストカバレッジを計測してみたのですが、18%台であまりよくない数字が出てきました。
「え、こんな低かったんだ」と思うのと同時に、私はこの類の数字はメンバーでどんどん共有していった方が開発組織として健全であると共に、すべての開発プロセスの一歩目は計測することだと思っています。
ということでテストカバレッジ改善プロセスの第一歩として、定期的にカバレッジの数字を共有できる仕組みを作ってみた備忘録です。
1. カバレッジ計測
Flutterのテストカバレッジの計測方法自体は簡単で、まず
$ flutter test --coverage
を実行します。すると coverage/lcov.info
というファイルがlocalに生成されます。次にこれをlcov[1]を使ってHTMLに変換します。lcovはHomebrew経由でインストールできます。
$ brew install lcov
// lcov.info -> HTMLへ変換
$ genhtml coverage/lcov.info -o coverage/html
コマンドを実行したディレクトリにcoverage/html/index.htmlが生成されているので、これをブラウザで開くとカバレッジファイルが確認できます。ファイルごとのカバレッジの数字でsortできたりするので色々眺めてみると楽しいです。
2. 改めて要件定義
カバレッジレポートを取得することに成功したので、本題の「定期的にカバレッジの数字を共有できる仕組み」を考えていきます。定期的に共有できる仕組み、といっても色々な方法があると思いますが
- 実装が比較的かんたん
- メンバーも確認しやすい
といえばSlackだなーと思ったので、ここでは 「SlackとGitHubActionsを組み合わせて月曜日の朝9時にカバレッジをポストする」 というのをやってみることにします。
3. カバレッジを取得するスクリプト
まずはカバレッジレポートからカバレッジの数字を取得します。出力してくれるコマンドとかないかなと思ったんですが、ちょっと調べてなさそうだったので[2]力技で引っこ抜くことにしました。カバレッジレポートのHTMLを見てみると
<td class="headerCovTableEntryLo">18.6 %</td>
という形式でカバレッジの数字が格納されているので、これを
$ grep 'headerCovTableEntryLo' coverage/html/index.html | sed 's/[^0-9.]//g'
# => 18.6
で引っこ抜きます(なのでclass属性が変われば当然ですが壊れます🙏)。
4. GitHubActionsでworkflowを組む
あとはSlackにカバレッジを通知するworlkflowを組むだけです。結論以下のようにしています。
name: Flutter Coverage Report
defaults:
run:
working-directory: mobile
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌─────────── hour (0 - 23)
# │ │ ┌───────── day of the month (1 - 31)
# │ │ │ ┌─────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───── day of the week (0 - 6 or SUN-SAT)
- cron: '0 0 * * MON'
jobs:
flutter-coverage-report:
runs-on: ubuntu-latest
timeout-minutes: 20
env:
TZ: Asia/Tokyo
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
sparse-checkout: mobile
ref: develop
- name: Install dart
uses: dart-lang/setup-dart@v1.4
- name: Install fvm
run: dart --version
- name: Check Dart Version
run: dart pub global activate fvm
- name: Setup flutter
run: fvm install
- name: Check Flutter version
run: fvm flutter --version
- name: Install dependencies
run: fvm flutter pub get
- name: Add dotenv
run: |
touch .env
touch .env.dev
- name: Test
run: fvm flutter test --coverage --coverage-path=coverage/lcov.info
- name: Install LCOV
run: sudo apt-get -y install lcov
- name: Generate coverage report
run: genhtml coverage/lcov.info -o coverage/html
- name: Measure test coverage
id: measure-test-coverage
run: echo "coverage_rate=$(grep 'headerCovTableEntryLo' coverage/html/index.html | sed 's/[^0-9.]//g')" >> $GITHUB_OUTPUT
- name: Notify to Slack
uses: slackapi/slack-github-action@v1.24.0
env:
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_INCOMING_WEBHOOK_URL }}
with:
payload: |
{
"attachments": [
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Flutter test coverage rate: `${{ steps.measure-test-coverage.outputs.coverage_rate }}%`"
}
}
]
}
]
}
うまくいくとこんな感じでカバレッジを報告してくれます。
5. アップデート
パッと思いついているのは以下です。時間があるときにまたやってみようと思います。
- 現状は全体のカバレッジしかレポートしていないので、ディレクトリごとのカバレッジに分けて報告してみる。
- カバレッジの数字が悪いファイルtop5も表示してみる。
- HTMLをS3やartifactなどにアップロードしてカバレッジレポートを詳細に確認できるようにする(といっても各人のlocal環境でflutter test --coverageしてもらえればいい気もします)。
- Slackメッセージが少し味気ないので、カバレッジの数字に合わせてメッセージをカスタマイズしてみる。例: 60%で「いい調子!」80%で「すごい!」など。こういう遊び心は大事にしていきたいです。
-
5分ぐらいしか調べてないので、「こんな方法あるで」という方がいたらコメントでやさしく教えてくれるとありがたいです。 ↩︎
Discussion