理系学生日記

おまえはいつまで学生気分なのか

GitHub Actionsでテストカバレッジの増減を可視化することによりホーソン効果を狙う

まぁよくやられている話なんだけど。

自動テスト頑張りましょうみたいな話をしても、大体そうですねで終わる。これには色々理由もあって、3分くらい考えても

  • テスト書く時間があったらまずはプロダクションコードの実装を終わらせろや、そうじゃないとリリース遅延するだろうがみたいに怒られる
  • 長期的はリグレッションテストが楽になるよ、アジリティが高まるよってわかっていても、特に新規開発とかで仕様が色々変わる中でテストコードのメンテが負債になる
  • そもそもメンテナブルなテストコードを書くのが大変

みたいな話になる。 それはそれで根深い問題なんだけど、頭痛くなるし辛くなるからそういう難しい話はやめたい。人生は楽しむべきであって、頭痛くなるために生きているのではない。何もしてないのにそもそも頭痛いし。

最近、「あなたのプルリクエストでテストカバレッジがどれだけ増減したんですか」というのを無条件でコメント投稿してやるCIにしました。

狙い

「テストコード書きましょう、なぜならルールだから」みたいなのでテスト書かれないままになるのがあるあるの中で、テストコードを書くことを当たり前にすることが狙い。

背景として、世の中には、wikipedia:ホーソン効果と呼ばれる心理的効果がある。

まぁこれは、行動やパフォーマンスが観察・計測されてますよって示すことにより行動者は自身の行動を改善しようというモチベーションが生まれ、観察者の期待に応えようとする効果と言われるヤツ。 そもそも数値化されてない状態で「頑張りましょう」なんて言われても、生まれながらの防衛本能として忘却を有する人類は確実に忘れる。どうせ観察者見てないし。面倒なことは忘れたいし。きちんと「お前を見ているぞ」というのを示さないといけない。

あと、何となくホーソン効果はポジティブな話に見えるんだけど、お前のおかげでテストカバレッジが上がった(あるいは下がった)、みたいな自分の寄与が他者にわかる形で示されるのも良いと思う。自分がこれだけ向上させました(あるいは悪化させました)みたいなのがすぐ示されるのは、ゲーミフィケーション的な趣がある。

実装

なんか使い勝手が良さそうだったので、vitestを使ってもいないのにvitest-coverage-report-actionを使った。vite.configなかったらwarning出るけど使える。同種のものでvitestに縛られないものがあったら教えて欲しい。

何が良さそうだったかというと、もちろんカバレッジレポートが出力されるのもいいんだけど、そのプルリクエストでカバレッジがどう増減したのかが出力されるのが良い。 これ出されると、うおお俺のせいでカバレッジが大幅に下がっている〜〜〜〜上げなければ〜〜〜〜〜みたいな危機感が芽生える。

カバレッジトレンド GitHub - davelosert/vitest-coverage-report-action: A GitHub Action to report vitest test coverage resultsより引用

どう実装するのか

これ結構面白くて、GitHub ActionsのStrategy matrixを使う。 こんな感じで、Strategy Matrixを使って2つのbranchを対象にしてテストを並列実行し、両branchのcoverage reportを取得する。それを比較すれば良い。頭いい。

name: "Test"
on:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - branch: main
            artifact: main
          - branch: ${{ github.head_ref }}
            artifact: pull-request

    permissions:
      # Required to checkout the code
      contents: read

    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ matrix.branch }}
          ## Set repository to correctly checkout from forks
          repository: ${{ github.event.pull_request.head.repo.full_name }}
    # 以下略

カラクリがわかったので、GitLabでも同種のことができると思う。ちょっと面倒くさそうかな。面倒くさそうだな(CI/CD YAML syntax reference | GitLab)。

最後に