最近ポケモンメザスタにハマっている、プロダクト開発チームのまっつん(@pagu_o28)です。
プロダクトの品質向上のために、コードカバレッジもテストコード自体の質も高い状態にしていきたいです。
hacomono のバックエンドは Ruby on Rails で、テストフレームワークは rspec です。今回はバックエンド側のコードカバレッジの測定について書きます。
1. カバレッジレポートを確認できる状態にする
まずは現状の確認をしました。
simplecov を導入済みでしたが、何故かちゃんと計測できていない状態でした。
なぜ計測できていないのかを調査するところからはじめました。
SimpleCovのREADME を確認してみる
よく読んでみると、下記の記述はアプリケーションのコードを require する前に呼んでおくこと!と書いてありました。
require 'simplecov' SimpleCov.start # Previous content of test helper now starts here
アプリケーションのコードを確認してみる
アプリケーションのコードを require した後に SimpleCov.start
を呼んでいました。
そのため README 通りに読み込みの順番を調整したところ、アプリケーションコードが計測対象として上がってきました!
2. CIでカバレッジレポートを生成して確認できる状態にする
ローカル環境で全テストコードを毎回実行してカバレッジレポートを見るようにする、という運用ルールはなかなか厳しいと思います。
ということで次に CI 実行時にカバレッジレポートを出力するようにしたいと思います。
CircleCIでのテスト実行について
hacomonoではバックエンド側(API)のテストは CircleCI で並列実行しています。
コンテナ0, コンテナ1,コンテナ2とそれぞれのコンテナで rspec が実行されカバレッジレポートがコンテナ上に出力されます。
そのため各コンテナのレポートをそれぞれ確認しなければなりません。
また、実行されたテストに基づいてカバレッジレポートが作られるので、コンテナ0番ではAファイルのカバレッジが低いけど、コンテナ1番では高い、みたいな状況が生まれてしまいます。
それを解消するために各コンテナのカバレッジレポートを1つにまとめる必要があります。
SimpleCovにcollateというメソッドが用意されていて、それを使ってまとめることができます。
また、CircleCI側でもジョブ間でファイルを共有する仕組みが用意されているのでそれを利用します。
SimpleCovでテスト結果をまとめるバッチを作成する
SimpleCovを実行してカバレッジレポートが作成されると下記のようなファイル群が出力されます。
この .resultset.json
をマージしていきます。
tree -a -L 1 . ├── .last_run.json ├── .resultset.json <- これ! ├── .resultset.json.lock ├── assets └── index.html
READMEに記載されているコードを参考に複数カバレッジの結果ファイルをマージするバッチを作ります。
https://github.com/simplecov-ruby/simplecov#merging-test-runs-under-different-execution-environments
# @path_pattern はこんな感じ。 "/tmp/simplecov-resultsets/.resultset-*.json" SimpleCov.collate Dir[@path_pattern] do add_group 'Controllers', 'app/controllers' add_group 'Data', 'layer/data' add_group 'Domain', 'layer/domain' add_group 'Helper', 'layer/helper' add_group 'Infra', 'layer/infra' add_group 'Presentation', 'layer/presentation' add_group 'lib', 'lib' coverage_dir Rails.root.join('tmp', 'simplecov_report') end
CircleCI でジョブ間でファイルを共有し結果ファイルを作成する
rspec 実行後に .resultset.json
を名前を変更してコピーしておきます。
その後、 persist_to_workspace
を使ってワークスペースにコピーしたファイルを追加しておきます。
CircleCI で利用可能な定義済の変数についてはこちらです。
https://circleci.com/docs/ja/built-in-environment-variables/
# rspec を実行する - run: ... # rspec 実行後に生成された .resultset.json ファイルを名前を変更してコピーしておいく。 - run: name: copy coverage result command: | mkdir /tmp/simplecov-resultsets cp tmp/coverage/.resultset.json /tmp/simplecov-resultsets/.resultset-${CIRCLE_NODE_INDEX}.json working_directory: api # ワークスペースにファイルを追加する - persist_to_workspace: root: /tmp paths: - simplecov-resultsets
次に先程作成したSimpleCovのレポートをマージするバッチを実行するジョブの設定を書きます。
coverage_report: working_directory: ~/repo resource_class: medium steps: # ワークスペースに追加したファイルをダウンロードする - attach_workspace: at: /tmp # 先程作ったマージするバッチタスクを実行する - run: name: Merge coverage report. command: RAILS_ENV=ci bin/rake mf:coverage_report_merge working_directory: api # ファイルをアップロードする - store_artifacts: path: api/tmp/simplecov_report
これはテストジョブ成功後に実行されるようにしたいので、このような書き方をしておきます。
jobs: - api_test - coverage_report: requires: - api_test
この状態で CI を回します。
するとAPIのテストが成功していて、カバレッジレポート出力も成功します。
CircleCIのARTIFACTSタブにindex.htmlがあるのでそれをクリックします。
SimpleCovのレポート結果の確認画面が開けました!
これでカバレッジレポートが CircleCI 上で確認できるようになりました!
まとめ
CircleCI 上で確認できるようになったのは良いものの、まだ課題もあります。
- 開発者が CircleCI の ARTIFACTS を見に行かなければならない。
- Github の PR で変更したファイルのカバレッジをレポートファイルから探して確認しなければならない。
ということで今後またこういう時間が取れたら Github 上でカバレッジの確認を完結できるような仕組みを作りたいです。
余談ですが、 GitLab では Test coverage visualization のような仕組みがあるようで、良いなーと思いながら作業してました。
参考
https://github.com/simplecov-ruby/simplecov
https://docs.gitlab.com/ee/ci/testing/test_coverage_visualization.html
https://qiita.com/kazutosato/items/1ff33fc86151ca78518f