iOS アプリ開発とユニットテスト

はじめに

こんにちは。iOS エンジニアの@nkmrhです。

本稿では、現在実践している iOS アプリ開発ユニットテストの Tips をご紹介します。

ユニットテストについてご興味のある方はこちらの記事(iOS/Androidチーム合同でユニットテストクロスレビューを行っている話)もおすすめです。

本稿でお伝えしたいことは下記の2点です。

  1. テストコードをプロダクションコードと同等に扱う
  2. コードカバレッジを Pull Request に表示する

テストコードをプロダクションコードと同等に扱う

Xcode から iOS アプリのプロジェクトを新規作成すると、ユニットテストのコードは Project/ProjectTests ディレクトリがデフォルトで作成され、テストコードとプロダクションコードのディレクトリが分かれる構成になります。

ですが、私たちのプロジェクトではテストコードをプロダクションコードと同じディレクトリに配置しています。この背景には、輪読会で読んだ「レガシーコード改善ガイド」にこの Tips が書かれており、良さそうだったので実践してみることにした、というものがあります。

はじめはこの配置に多少の違和感はありましたが、徐々に慣れてくるとプロダクションコードのすぐ下にテストコードがあることで開発体験が向上しました。

具体的には、テストコードを目につくようにしておくと、テストコードとプロダクションコードの行き来が楽になり、テストケースを書くのはもちろんのこと、テストケースを読んで振る舞いを確認したりする効率が良くなったと感じています。また、コードレビューする側もテストがない事に気づきやすい・確認がしやすいというメリットがありました。

これにより、テストコードを書く = プロダクションコードを書いているという認識がチームに浸透しています。

但し、テストコードがプロダクションのビルドターゲットに含まれないように、TargetMembership の管理に注意が必要です。私たちのプロジェクトでは XcodeGen を利用しているためディレクトリ単位ではなく、ファイル名の Suffix でターゲット指定を分けるようにしています。

f:id:nkmrh:20210326152927p:plain ※ViewModelとViewModelTestsを同一ディレクトリに配置しています

コードカバレッジを Pull Request に表示する

上記のディレクトリ構成により、自然とロジックに対してユニットテストを書けるようになりましたが、たまにテストを書き忘れてしまうこともあります。それを防ぐ為に Pull Request を対象に変更・追加されたファイルに対してコードカバレッジを表示するようにしています。

以下に具体的なツールの設定方法をご紹介します。

設定方法

コードカバレッジの表示には danger-xcov を利用します。Gemfiledanger-xcov を追加します。

Gemfile

gem 'danger-xcov'

Dangerfile に下記を追加します。これにより Pull Request にコードカバレッジが表示されます。minimum_coverage_percentage を設定すると、指定した値を下回ると Danger に怒られるようにすることも可能です。

Dangerfile

xcov.report(
   scheme: 'YourXcodeSchemeName',
   workspace: 'path/to/workspace.xcworkspace',
   source_directory: 'SourceDirectory',
   only_project_targets: true,
   minimum_coverage_percentage: 70.0
)

.xcovignore に無視したいファイルを指定します。主にロジックの書かれていない、Viewやコード生成されたソースコードを除外します。

.xcovignore

- .*View.swift
- .*Row.swift
- .*Button.swift
- .*Card.swift
- Generated

以上で Pull Request を作成し CI で Danger を実行すると、下記画像のようにコメントでコードカバレッジが表示されます。

f:id:nkmrh:20210326152956p:plain ※コメントでコードカバレッジが表示されている様子

このように表示することで、カバレッジが低いクラスに対しテストケースを追加する動機付けを作ることができます。私はカバレッジが低いクラスを見つけた場合はテストケースを追加するか、別途 issue を作成し後日テストケースを追加するようにしています。

f:id:nkmrh:20210326153028p:plain ※カバレッジが低いクラスに対してテストを追加している様子

まとめ

上記の工夫は小さなことですが、ユニットテストを書く上でモチベーション向上や効率の面で効果的だと感じています。

その一方で、コードカバレッジはテストケースの品質とは無関係であるため、コードカバレッジが高いからといっても必ずしもコードの品質が高いことを保証できるわけではありません。そのため、今後はテストケースの品質向上の為にカバレッジレポートを題材にチームで議論をしてみたいと考えています。

おわりに

iOS チームではより良いプロダクト開発を目指して、このように様々な取り組みを継続的に行っています。こちらの記事を読まれて Quipper に興味をお持ちいただいた皆様、ぜひ Quipper に遊びに来ませんか? 以下 Wantedly ページよりお気軽にご連絡ください! https://www.wantedly.com/companies/quipper/projects