海外記事翻訳シリーズ 【第 1 回】 RSpec ベストプラクティス
初稿:2011-01-31
訳者: 桑田誠
この連載について
この連載では、海外の良質な記事やブログを翻訳して紹介します。
第 1 回目は、Jared Carrollさんのブログ記事「RSpec Best Practice」です。
RSpec ベストプラクティス
RSpec は、振舞駆動の設計プロセス (behaviour driven design process) において、人間にとって読みやすい仕様を書くための優れたツールです。RSpec で書かれた仕様が、アプリケーション開発における方向と検証を行います。本記事では私たちが気づいた、エレガントで保守しやすい仕様を書くためのプラクティスを紹介します。
まず、何をしてるのかを #describe で説明しましょう
定義するつもりのメソッドごとに、#describe を使うことから始めましょう。このとき引数にはメソッド名を指定します。クラスメソッドには名前の頭に「.」をつけ、インスタンスメソッドには頭に「#」をつけましょう。これは Ruby の標準的なドキュメントプラクティスに則っており、spec ランナーによる出力が読みやすくなります。
次に、#context (コンテキスト) をはっきりさせましょう
メソッドの実行パスごとに、#context を書きましょう。与えられたコンテキストのもとでの〔訳注: つまり実行パスごとの〕メソッドの挙動を逐語的に指定します。
たとえば、次のメソッドには 2 つの実行パスがあります。
対応するスペックでは 2 つのコンテキストを作成します。
各 #context の引数における「given」の使い方に注意してください。「given」はメソッドに与えられる入力値を説明します。ほかに使える単語としては「when」があります。こちらは条件によって挙動が変わるときのコンテキストを表現するのに使えます。
このスタイルに従えば、複数の #context を入れ子にすることで、より深い実行パスを明確に定義できます。
#it でのエクスペクテーションはひとつだけにしましょう
サンプル (example) 1 つにつき 1 つのエクスペクテーション (expectation) だけを記述するように努力してください。そうすればスペックの可読性が向上します。
次のスペックはひとつのサンプルのなかにあまり関連していないエクスペクテーションが混じっています。
以下のようにエクスペクテーションを複数のサンプルに分解することで、挙動を明確に定義できますし、サンプルの保守もより簡単になります。
サンプルの説明は挙動を表す現在時制の動詞で始めてください。
最後に、サンプルの説明を「should」で始めないようにしましょう。「should」を使うのは冗長ですし、結果としてスペックの出力が読みづらくなります。可読性が向上すると思うなら「the」や「a」や「an」は積極的にサンプルの説明に使っていきましょう。
明示的にすることを心がけましょう
「#it」や「#its」や「#specify」はタイプ量を減らすことができますが、可読性が犠牲になってしまいます。それらを使った場合、サンプルの中身を読まないと、それが何を意味しているのかを把握できなくなります。
次の例を使ってドキュメントフォーマッタ出力を比べてみましょう。
明示的に振舞いを記述した場合は次のようになります。
前者の場合、そっけなくてコードっぽい感じで出力され、「should」が何度も登場して冗長です。
後者の場合、スペックが非常に明確で読みやすく出力されます。
スペックを実行して読みやすさを確認しましょう
スペックを実行する際には常に「-format」オプションに「documentation」をつけるようにしましょう (RSpec 1.x では「-format」オプションは「nestable」と「specdoc」です)。
出力が明瞭な会話のようになるまで、サンプルの名前を変更し続けましょう。
適切なマッチャを使いましょう
RSpec は役に立つマッチャを数多く揃えています。これらを使うと、スペックが話しことばにより近くなります (訳注: ここでの話しことばとは英語のことです)。
私たちが好んで使うマッチャを紹介します。使う前と使った後での違いは次のようになります。
ドキュメントを参照したり周りの人に聞いたりしてください。
フォーマット
すべてのブロックで、’do..end’ スタイルのブロックを使いましょう。このとき、たとえ 1 行のエクスペクテーションでも複数行のブロックを使います。可読性をより向上させるために、すべてのブロック間に空行を 1 行入れます。また、トップレベルの #describe では最初と最後に 1 行の空行を入れましょう。
比較してみます。
分かりやすく構造化したコードは次のようになります。
複数の開発者がいるチームでは、一貫したフォーマットスタイルを維持するのは難しいことではありますが、各チームメイトのスタイルを視覚的にパースするのを修得するために費やされる時間を節約できるので、やる価値はあります。
まとめ
本記事では、誰にとっても読みやすくて分かりやすい仕様を書くことに関するプラクティスを紹介しました。目標は、実行してパスするだけでなく、その出力結果がアプリケーションを完全に定義しているようなスペックを書くことです。ひとつひとつの小さなステップの積み重ねが、ゴールに向かうことを助けてくれます。私たちはもっと良い方法を引き続き学んでいるところです。あなたの RSpec ベストプラクティスはどのようなものでしょうか?
訳者について
桑田誠。RSpecより「alias eq assert_equal」のほうが好き。