RSpecでit / example / specifyはどのように使い分けるのか？〜日本語で書くならexampleって本当？〜

## はじめに

最近ときどき「RSpecで`it`/`example`/`specify`をどのように使い分けたら良いのか」という話題を見かけるので個人的な私見を書いてみます。

## 使い分けに何か決まりはあるのか？ → 技術上の決まりは何もありません

`it`/`example`/`specify`は技術的にはまったく同じメソッドです。なので、`it`を`example`や`specify`に置き換えても問題なく動きます。

```ruby 
# itを使う
it 'adds numbers' do 
  expect(1 + 1).to eq 2
end

# itの代わりにexampleを使う
example 'adds numbers' do 
  expect(1 + 1).to eq 2
end

# itの代わりにspecifyを使う
specify 'adds numbers' do 
  expect(1 + 1).to eq 2
end
```

日本語と英語で使い分けが必要、なんてこともありません。

```ruby 
# itを使う
it '数値を加算する' do 
  expect(1 + 1).to eq 2
end

# itの代わりにexampleを使う
example '数値を加算する' do 
  expect(1 + 1).to eq 2
end

# itの代わりにspecifyを使う
specify '数値を加算する' do 
  expect(1 + 1).to eq 2
end
```

## Q. じゃあなんで同じメソッドが3つもあるの？

これはテストコードを英文として読みやすくするためだと思います。

`it`/`example`/`specify`を英文らしく読めるように使い分けるなら、次のような文例が作れそうです。

- `it "adds numbers"` = それ（it）は数値を加算する
- `example "addition of numbers"` = 「数値の加算」の例（example）
- `specify "one plus one equals two"` = 「1足す1は2であること」を示す（specify）


なので、冒頭で提示したコード例は、次のように書いた方が、技術的な差異は無くとも **英文としては** ベターかもしれません。

```ruby 
it 'adds numbers' do 
  expect(1 + 1).to eq 2
end

example 'addition of numbers' do 
  expect(1 + 1).to eq 2
end

specify 'one plus one equals two' do 
  expect(1 + 1).to eq 2
end
```

### 参考情報：RSpecの本にはどのように書いてあるか？
洋書になりますが、「Effective Testing with RSpec 3」という本があります。本の筆者は当時のRSpecのメンテナさん（Myron Marston氏）です。この本の中では`example`と`specify`の用例として次のようなコードが載っていました。

```ruby 
# Quoted from Effective Testing with RSpec 3 
# 「Effective Testing with RSpec 3」から引用
RSpec.describe PhoneNumberParser, 'parses phone numbers' do
  example 'in xxx-xxx-xxxx form'
  example 'in (xxx) xxx-xxxx form'
end

RSpec.describe 'Deprecations' do
  specify 'MyGem.config is deprecated in favor of MyGem.configure'
  specify 'MyGem.run is deprecated in favor of MyGem.start'
end
```

たしかにこんなふうになっていると、テストコードを次のように英文っぽく読むことができますね。

- `example 'in xxx-xxx-xxxx form'` = xxx-xxx-xxxx形式の例（example）
- `specify 'MyGem.config is deprecated in favor of MyGem.configure'` = 「"MyGem.config"は非推奨なので、代わりに"MyGem.configure"を使うこと」を示す（specify）

https://pragprog.com/titles/rspec3/effective-testing-with-rspec-3/

## Q. itは英語で書き、exampleは日本語で書く、って習ったんですけど？

これはあまり根拠のない話なので気にしない方がいいと思います。

すでに述べたように、技術的には何の制約もないので、`it`と`example`で英語と日本語を使い分けなくてもRSpecは問題なく動きます。

違いがあるとすれば、「英文として見たときの違和感をどれだけ減らせるか」の観点かもしれません。

RSpecの`it`は主語を表すitなので、英文として考えるならその次に動詞（addsやisなど）が来なければなりません。

しかし、

```ruby 
it '数値を加算する' do
```

のようになっていると、"it + 日本語の文章"という意味不明な英文が出来上がってしまいます。

もちろん、この問題はexampleやspecifyを使っても完全には解消されないのですが、itに比べると若干違和感を減らせるかもしれません。

```ruby 
# 「数値を加算する」例（example）と読めなくもない
example '数値を加算する' do

# 「数値を加算する」ことを示す（specify）と読めなくもない
specify '数値を加算する' do
```

「itは英語で書き、exampleは日本語で書く」という話はたぶんこういうところから出てきたんじゃないかな〜と個人的に考えています。

もちろん、チーム内のコーディングルールとして「itは英語で書き、exampleは日本語で書く」というルールを設定するならそれはそれでOKです。ですが、RSpecの決まり事としてはそのようなルールはどこにも存在しません。

仮に「itは英語で書き、exampleは日本語で書く」というルールがあったとて、

```ruby 
example '数値を加算する' do
```

は、結局英文としては破綻しているので、それなら

```ruby 
it '数値を加算する' do
```

と書いても大差ないし、あまり気にする意味はないと僕は思います。

そもそもの話ですが、RSpecの作者はたぶん「英文としてちゃんと読めるかどうか」ということしか気にしていなくて、日本語で書いたときにどうなるかなんて、ほとんど考えていないんじゃないでしょうか。。。

### 参考情報：もしかしてここが震源地？

僕が昔Qiitaに書いたRSpecの入門記事にも、`it`/`example`/`specify`の使い分けについて次のような説明を書きました。

> （まあ `it '1 + 1 は 2 になること'` よりも `specify '1 + 1 は 2 になること'` や `example '1 + 1 は 2 になること'` の方が若干自然かもしれませんが・・・）

この記事は多くのRSpec初心者さんに読まれているので、もしかするとこの説明が変に強化されて「itは英語で書き、exampleは日本語で書く」みたいな話になってしまったのでは？という気がしなくもないです😅

https://qiita.com/jnchito/items/42193d066bd61c740612

## おまけ：日本人にも優しい、日本語フレンドリーなRSpecを書いてみよう
先ほど「RSpecの作者はたぶん「英文としてちゃんと読めるかどうか」ということしか気にしていない」と書きましたが、実は`describe`や`it`を日本語に置き換える方法があります。

以下のコード例を見てください。

```ruby 
RSpec.configure do |config|
  config.alias_example_group_to :次の仕様を記述する
  config.alias_example_to :次のような振る舞いを持つこと
end

次の仕様を記述する "四則演算" do
  次のような振る舞いを持つこと "1足す1は2である" do
    expect(1 + 1).to eq 2
  end
end
```

このコードではexample group（`describe`や`context`）のエイリアスとして`次の仕様を記述する`というメソッドを、example（`it`/`example`/`specify`）のエイリアスとして`次のような振る舞いを持つこと`というメソッドをそれぞれ定義しています。

そのため、RSpecのコードを

```ruby
次の仕様を記述する "四則演算" do
```

や、

```ruby 
次のような振る舞いを持つこと "1足す1は2である" do
```

のように書くことができます。

もちろん、このコードは実際に動かすことも可能です。

```
$ rspec sample_spec.rb --format documentation

四則演算
  1足す1は2である

Finished in 0.00121 seconds (files took 0.06884 seconds to load)
1 example, 0 failures
```

`spec_helper.rb`の中でエイリアスメソッドを定義すれば、こんなふうに「日本語フレンドリー」なRSpecを書くことも可能です・・・って、こんなことをする人はたぶんいないと思いますがw

## まとめ
というわけで、この記事ではRSpecにおける`it`/`example`/`specify`の使い分けについてあれこれ語ってみました。
使い分けがわからなくて困っていた人の参考になれば幸いです😄

### PR：RailsでRSpecを書きたいなら「Everyday Rails - RSpecによるRailsテスト入門」をどうぞ！
「`it`/`example`/`specify`の使い分け以前に、Railsでどうやってテストを書いたらいいかわかりません！」というRSpec初心者さんは、「Everyday Rails - RSpecによるRailsテスト入門」をどうぞ。2022年のアップデートでサンプルアプリケーションがRails 7.0にバージョンアップしています。

https://leanpub.com/everydayrailsrspec-jp/

Rails 7.0対応以外にもさまざまなアップデートがあります。2022年版の詳しいアップデート内容は以下のブログ記事を参照してください。

https://blog.jnito.com/entry/2022/01/17/115109