55
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RSpecAdvent Calendar 2015

Day 1

describe の次行に subject を、 context の次行に let を書く

Last updated at Posted at 2015-11-30

というオレオレルールなんですが、わりといい気がするのでご紹介します。

よくわからないと思うので実例で。

実例

狼が村人を噛むと村人は死ぬ。狼がハムスターを噛んでもハムスターは死なない という条件の rspec を、以下のように書きます。

wolf_spec.rb
require 'rails_helper'

RSpec.describe Wolf do
  subject(:wolf){ FactoryGirl.build(:wolf) }
  it { is_expected.to be_valid }
  describe 'bite' do
    subject { wolf.bite(creature) }
    context 'bite villager' do
      let(:creature){ FactoryGirl.build(:villager) }
      it { expect{subject}.to change{creature.reload.living?}.to(false) }
    end
    context 'bite hamster' do
      let(:creature){ FactoryGirl.build(:hamster) }
      it { expect{subject}.not_to change{creature.reload.living?} }
    end
  end  
end

順に上から見て行きましょう。

describe Wolf do
  subject(:wolf){ FactoryGirl.build(:wolf) }

まず、この2行がペアです。 Wolf モデルに関するテストであるという宣言と、実際に wolf のインスタンスを用意する ruby 文とのペアです。 subject に引数を渡しているので、 wolf でも subject でも同じものを参照できます。

次の行。

it { is_expected.to be_valid }

is_expectedexpect(subject) と等価です。実行文そのものがテスト内容を完全に表現しているので、 it にコメントは不要でしょう。

その次の2行を見てみましょう。

  describe 'bite' do
    subject { wolf.bite(creature) }

biteメソッドをテストするよ!という宣言と、実際に wolf の bite メソッドを呼び出す ruby 文とのペアです。
先の subject で引数を渡しているので、 wolf で参照できます。 creature はこの時点では未定義です。

次の2行を御覧ください。

    context 'bite villager' do
      let(:creature){ FactoryGirl.build(:villager) }

villager を bite した時のテストだよ!という宣言と、biteに引数として渡してある creature に villager のインスタンスを実際に渡す ruby 文とのペアです。

次の行はテストの本体になります。

it { expect{subject}.to change{creature.reload.living?}.to(false) }

今回は change マッチャの都合で is_expected が使えませんが、英文として読んだ通りのテストなので、やはり it にコメントは不要でしょう。

まとめ

describe と context の実装は alias なのでどっちを使っても実質同じなのですが、英単語の意味で使い分け、「何をテストするか」を describe, 「どんな状況のテストをするか」を context でまとめると分かりやすい、と言われています。
一方、subject と let も (ほぼ) alias でして、英単語の意味的に使い分けているだけなのですが、 subject は「何をテストするか」の宣言なので、これを describe と対応させ、 context は let で書くようにすると書き方に統一感が生まれ、読みやすい spec になるんでは、という提案でした。

完全にこのルールで全てを書けるわけではなく、describe と let がペアになるケースも実際に私の手元で発生はしていますが、 describeとかcontextのコメントを書いたら、次の行にそのコメントに対応するruby文を書く というルールは確実に可読性を上げるのでオススメです。

55
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
44

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?