チームのルールは自動テストで周知しよう - Rubykaigi参加レポート

キッズリーの開発を担当している倉成です。

先日参加したRubykaigi2018の中でShopifyのJulian Nadeauさんが発表していた『Scaling Teams using Tests for Productivity and Education』がチーム開発をする上でとても参考になったので、今回はその内容を記事にしていきたいと思います。

このセッションではメンバーが本当に必要なことに集中するためにチームのルールはドキュメントで示すのではなく自動テストで周知しようという主張のもと様々な事例が紹介されていました。
開発を行う際、ドキュメント化された様々なルールに常に注意を払い続けるのではなく、ルール違反が発生したときに初めて何が問題か、なぜ問題なのか、どうすれば修正できるのかという具体的な情報を提示することで、認知的負荷の少ない集中した状態で開発を行えるというのが基本的な考え方です。

それでは具体的にShopifyではどのようなルールがあり、それに対してどのような自動テストが構築されていったのか見ていきましょう。発表資料と実際のコードは下記で公開されています。
発表資料: https://jnadeau.ca/presentations/rubykaigi2018/

チームメンバーにルールをどう周知するか?

チーム開発をする中で各々のチームには、開発に関する様々なルールが定められていることでしょう。
例えば

依存ライブラリに関するルール
例: プロジェクトで既にfaradayを使用しているので、類似ライブラリであるhttpartyを追加してはいけない
コーディングスタイルに関するルール
例: ブロックを定義する{ }とコードの間にはスペースを入れなければならない
ヘルパーメソッドに関するルール
例: 全てのテストファイルでtest_helper.rbをincludeしなければならない
ドキュメントに関するルール
例: 全ての公開APIに対してドキュメントを書かなければならない
ファイルの命名規則に関するルール
例: foo.rbに対するユニットテストはfoo_test.rbに書かなければならない

などがあるかもしれません。これらのルールをどうやってメンバーに周知すればよいでしょうか。

まず思いつく方法としてはルールをドキュメントに書き起こす方法です。しかし、全てのルールをドキュメント化したとしても開発者は全てを覚えていられませんし、そもそもドキュメントの存在に気づかないかもしれません。

またプロジェクトに長く携わっている開発者でもソフトウエア全体のアーキテクチャの構想など、より重要な事を考えている時にはこれらの些細なルールのことを忘れてしまうでしょう。

それではルールを忘れた状態で作業してしまったとしてもアプリケーションが壊れてしまうことを防ぐには、どのような手段が取れるでしょうか?。

ユニットテストのように自動化を行う

アプリケーションコードが正しく動作することをユニットテストで検証するように、プロジェクト上の問題も自動テストで検出することができます。

例えば

  • メンテナンススクリプトにテストが対応づいていることを確認する
  • 特定のGemのインストールを禁止する
  • 特定のコーディングスタイルを強制する

については自動テストでの検出が可能です。(自動テストのコードについては発表資料ページにいくつかの例が掲載されています。)

このように自動テストでルール違反の警告を表示することで、ドキュメントを作成するよりも確実にルールの存在に気づくことができます。

適切なエラーメッセージ

自動テストを作成する場合、エラーメッセージには「何が問題か、なぜ問題なのか、どうすれば修正できるのか」を含めることが重要です。

例えばfoo.rbに対応するテストファイルとして本来foo_test.rbを追加すべきところ、誤ってfoos_test.rbを追加してしまったケースを考えましょう。

このとき

(`foo.rb`にはテストファイルが必要です)
We expected file `foo.rb` to have a test.

というメッセージを出しても、ユーザーは「いやいや、テストファイルならさっき追加したじゃないか」と自分の誤りに気づくのに時間がかかってしまうでしょう。

一方、

(`foo.rb`には`foo_test.rb`が必要ですが、見つかりませんでした。`foo_test.rb`を作成してください)
We expected file `foo.rb` to have an associated test at `foo_test.rb`,
but we couldn't find one. Please make a file at `foo_test.rb`.

というメッセージであれば先程よりもミスに気づきやすく、どうしたら問題が修正できるかを容易に理解できます。

JIT教育(Just In Time Education)

自動テストを構築し必要になったときに初めてルールを提示する仕組みはJITコンパイラと同じようにJIT教育(Just In Time Education)と呼ぶことができるでしょう。JIT教育により開発者はすべてのルールを記憶しながら開発するのではなく、問題があった際にエラーの形で気づくことができるため頭の負荷を減らした状態で開発ができるようになります。

新しいメンバーがチームに参加した際にも効果的にチームのルールを教育することができるようになるため、積極的にこの仕組みを構築していくとよいでしょう。

セッションを聞いて

ドキュメントではなく自動テストでルールを周知するという考え方とその実例を示すとても実用性の高いセッションだったと感じています。特に発表の中で紹介されていたテストファイル名のtypoや類似のGemを導入しようとしてしまうことについては自分でも思い当たる節がありました。

また適切なエラーメッセージを出力するという文脈の中でRMagickのエラーログを装飾するBundlerプラグインの紹介があった際、会場から「RMagickのエラーログは分かりづらいよね」「このプラグイン便利」「確かにエラーメッセージの内容には気をつけなければ」という雰囲気を感じ取れたのが印象的でした。
発表者のページには発表資料とともに多くのコード例が紹介されているので、こちらもぜひ訪問してみてください。