CircleCI 2.0 + fastlane + Slather でコードカバレッジの変化を Slack に通知する
yutu
こんにちは、スタディサプリオープンキャンパスの iOS アプリを担当している平井です。
iOS アプリ開発界隈ではテストや CI/CD に関する話題が盛り上がっています。せっかく書いたテストをもっと有効に活用したい方も多いはず。有効活用する方法の1つとして、コードカバレッジの変化を観察することが挙げられます。コードカバレッジが下がったらリジェクト...とまでいかなくても、変化を知ることだけでもメリットがあります。
iOS アプリ開発でも Codecov や Coveralls と連携することで簡単に実現できます。しかし、これらのサービスはプライベートリポジトリは有料であるため、なかなか利用できない方も多いのではないようでしょうか。
というわけでこの記事では、これらのサービスを利用せずに CircleCI 2.0 + fastlane + Slather でコードカバレッジの変化を Slack に通知する方法をご紹介します。
本記事では以下の環境を前提に説明します。
- Xcode
9.2
- CircleCI
2.0
- fastlane
2.69.2
- Slather
2.4.4
適当なテストが書かれた Xcode プロジェクトも準備してください。
Xcode でコードカバレッジを計測できるようにする
Xcode ではコードカバレッジを計測できる機能が用意されています。この機能は Edit scheme... > Test > Gather coverage data にチェックを入れるだけで有効にできます。
cmd + U でテストを実行すると Xcode 上でコードカバレッジが確認できます。
また、fastlane でテストを実行するときに Scheme を参照するので、Manage Schemes... より 対象の Scheme の Shared にチェックを入れましょう。
fastlane と Slather をインストールする
コマンドラインでテストを実行するために、fastlane と Slather をインストールします。fastlane は利用されている方も多いと思いますが、Slather はあまり馴染みがないかもしれません。
Slather は Xcode 独自のコードカバレッジレポートから別形式のレポートを生成する gem です。生成できるレポート形式は Cobertura や HTML などがあります。
CircleCI でコードカバレッジレポートを確認するため Slather を利用します。早速、 Gemfile を準備しましょう。
source 'https://rubygems.org'
gem 'fastlane'
gem 'slather'
Gemfile の準備ができたら、以下のコマンドを実行して fastlane と Slather をインストールしておきましょう。
$ bundle install --path=vendor/bundle
続いて Fastfile を用意します。ありがたいことに fastlane には slather を実行するためのアクションがすでに用意されています。
fastlane_version "2.69.2"
default_platform :ios
platform :ios do
desc "Runs all the tests"
lane :test do
scan(
scheme: "[Your Xcode Scheme]",
device: "iPhone 8 Plus",
code_coverage: true,
clean: true
)
slather(
proj: "[Your Xcode Project].xcodeproj",
scheme: "[Your Xcode Scheme]"
)
end
end
利用しているアクションの仕様は以下で確認できます。
手元で動作を確認してみましょう。
$ bundle exec fastlane ios test
以下のように表示されれば成功です。
[19:44:35]: ---------------------
[19:44:35]: --- Step: slather ---
[19:44:35]: ---------------------
[19:44:36]: $ slather coverage --scheme [Your Xcode Scheme] [Your Xcode Project].xcodeproj
[19:44:37]: ▸ Slathering...
[19:44:38]: ▸ [Your Xcode Scheme]/Xxx.swift: 3 of 3 lines (100.00%)
[19:44:38]: ▸ [Your Xcode Scheme]/Yyy.swift: 3 of 3 lines (100.00%)
[19:44:38]: ▸ Test Coverage: 100.00%
[19:44:38]: ▸ Slathered
CircleCI でテストを実行する
CircleCI でテストを実行できるようにします。以下のように CircleCI の設定ファイルを記述しましょう。
version: 2
jobs:
test:
macos:
xcode: "9.2.0"
working_directory: ~/project
shell: /bin/bash --login -eo pipefail
steps:
- checkout:
path: ~/project
- run:
name: Set Ruby Version
command: echo "ruby-2.4" > ~/.ruby-version
- restore_cache:
key: v0-gems-{{ checksum "Gemfile.lock" }}
path: vendor/bundle
- run:
name: Bundle install
command: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle
environment:
BUNDLE_JOBS: 4
BUNDLE_RETRY: 3
- save_cache:
key: v0-gems-{{ checksum "Gemfile.lock" }}
paths: vendor/bundle
- run:
name: Run tests
command: bundle exec fastlane ios test
workflows:
version: 2
build:
jobs:
- test
設定ファイルについては Configuration Reference - CircleCI を参照してください。
このファイルを含めて push すると、CircleCI 2.0 上で bundle exec fastlane ios test
が実行されます。以下のように表示されれば成功です。
コードカバレッジの変化をSlackで通知する
ここまでで CircleCI のジョブごとにテストレポートを確認できるようになりました。CircleCI ではジョブごとにテストレポートなどの生成物を保存できます。このことを利用して、前回のジョブとのコードカバレッジの差分を抽出し、その変化を Slack で通知するようにしたいと思います。
まず、Slack の通知先を設定するために Slack の Webhook URL を取得します。CircleCI App の Add COnfiguration をクリックします。
通知先のチャネルを選び Add CircleCI Integration をクリックします。
Webhook URL が表示されるのでコピーしておきましょう。
次に CircleCI API 用のトークンを取得します。このトークンは前回のコードカバレッジレポートを取得するために必要です。Project Settings > API Permissions に移動して Create Token をクリックします。
Build Artifacts
を選択し、適当なラベルをつけて Add Token をクリックします。
生成されたトークンをコピーしておきましょう。
続いて CircleCI の環境変数を追加します。環境変数の追加は Project Settings > Environment Variables で行います。追加する環境変数は以下のとおりです。
Name | Value |
---|---|
SLACK_ENDPOINT | 生成した Slack の Webhook URL |
CIRCLE_TOKEN | 生成した CircleCI API 用のトークン |
COVERAGE_FILE | cobertura.xml |
環境変数追加後は以下のように表示されます。
最後にテスト実行完了後に前回のコードカバレッジレポートと比較する処理を追加します。ここで、 @u-minor さんの CircleCIで計測したカバレッジ変化をSlackに晒す - Qiita で紹介されている神スクリプトを利用します。 Fastfile と .circleci/config.yml を以下のように変更しましょう。
fastlane_version "2.69.2"
default_platform :ios
platform :ios do
desc "Runs all the tests"
lane :test do
scan(
scheme: "[Your Xcode Scheme]",
device: "iPhone 8 Plus",
code_coverage: true,
clean: true
)
slather(
proj: "[Your Xcode Project].xcodeproj",
scheme: "[Your Xcode Scheme]",
source_directory: "./[Your Xcode Project Dir]",
output_directory: "./fastlane/test_output/slather",
cobertura_xml: true
)
end
desc "Notify Slack about changes in code coverage"
lane :coverage do
commit = last_git_commit
circleci2_coverage_slack = "https://gist.githubusercontent.com/u-minor/20c7876b9bc4b875d9c73b59f2a4365f/raw/68be9dd0db31ff98ceb91cc580875905e895890e/circleci2-coverage-slack"
sh("curl -s -L #{circleci2_coverage_slack} | COMMIT_AUTHOR=\"#{commit[:author]}\" COMMIT_LOG=\"#{commit[:message]}\" bash -s")
end
end
version: 2
jobs:
test:
macos:
xcode: "9.2.0"
working_directory: ~/project
shell: /bin/bash --login -eo pipefail
steps:
- checkout:
path: ~/project
- run:
name: Set Ruby Version
command: echo "ruby-2.4" > ~/.ruby-version
- restore_cache:
key: v0-gems-{{ checksum "Gemfile.lock" }}
path: vendor/bundle
- run:
name: Bundle install
command: bundle check --path=vendor/bundle || bundle install --path=vendor/bundle
environment:
BUNDLE_JOBS: 4
BUNDLE_RETRY: 3
- save_cache:
key: v0-gems-{{ checksum "Gemfile.lock" }}
paths: vendor/bundle
- run:
name: Run tests
command: bundle exec fastlane ios test
- store_artifacts:
path: fastlane/test_output
- run:
name: Slack
command: bundle exec fastlane ios coverage
workflows:
version: 2
build:
jobs:
- test
この変更を push すると、CircleCI の Artifacts に cobertura.xml が生成されます。
このジョブを再度実行してみましょう。以下のように通知が届けば成功です。
まとめ
CircleCIで計測したカバレッジ変化をSlackに晒す - Qiita で紹介されている神スクリプトのおかげで、 Codecov や Coveralls を利用しなくてもコードカバレッジの変化を知ることができるようになりました。
@u-minor さん、本当にありがとうございます!
iOS アプリ開発でも是非お試しください!