RSpecを2ヶ月くらい使って気づいた事と分からない事

RSpec勉強会 @ 万葉

7 Mar 2011 @irohiroki

去年までShoulda

Thoughtbotェ…

The future of Shoulda
ジョジョーーー!!!!!俺はShouldaを捨てるぞーーー!!!!!

2ヶ月くらい使って気づいた事

【前提】exampleの構成要素

気づいた事(1)

とりあえずいくつかベタにexample書いて、

重複するところをdescribeやcontextでくくり出せばいいや

これを

it "tells its age" do
  u = Factory(:user, :birthday => '2002-08-10')
  u.age.should eq(8)
end

it "tells its eto" do
  u = Factory(:user, :birthday => '2002-08-10')
  u.eto.should eq('uma')
end

こうする

describe "a user born in 2002" do
  let(:u){ Factory(:user, :birthday => '2002-08-10') }

  it "tells its age" do
    u.age.should eq(8)
  end

  it "tells its eto" do
    u.eto.should eq('uma')
  end
end

actionもくくり出しちゃっていいんだ

it "returns response code 400" do
  get :show, 'key' => 'bogus'
  response.code.should eq('400')
end

it "returns an empty body" do
  get :show, 'key' => 'bogus'
  response.body.should be_blank
end

context "when called with a bogus key" do
  before { get :show, 'key' => 'bogus' }

  it "returns response code 400" do
    response.code.should eq('400')
  end

  it "returns an empty body" do
    response.body.should be_blank
  end
end

くくり出し方は自由

ちなみにdescribeとcontextは同じもの

alias_method :context, :describe
describe User do
  context "with a friend" do

気づいた事(2)

before :all と after :all

複数のexampleで使う静的なfixtureを作る/消すのに便利ですね

気づいた事(3)

外側のbeforeから順に実行される、

describe User do
  before { # 1st }

  context "in a big context" do
    before { # 2nd }

    context "in a specific context" do
      before { # 3rd }

ところが内側でletした値は外側のbeforeで使える

ということは

describe "GET show" do
  before { get :show, :id => id }

  context "with the right id" do
    let(:id){ 1 }
    it { # expects success }
  end

  context "with a wrong id" do
    let(:id){ 99 }
    it { # expects failure }
  end
end

同じbeforeで別の前提条件を作れる

気づいた事(4)

let / let! / インスタンス変数

気づいた事(5)

subjectのためにdescribe切ってもいいかも

subjectとは

テストのターゲット

subjectが適切だと、"itの後の文字列"がいらなくなる

context "when called with a bogus key" do
  before { get :show, 'key' => 'bogus' }

  it "returns response code 400" do
    response.code.should eq('400')
  end

  it "returns an empty body" do
    response.body.should be_blank
  end
end
context "when called with a bogus key" do
  before { get :show, 'key' => 'bogus' }
  subject { response }

  its(:code){ should eq('400') }

  its(:body){ should be_blank }
end

テストしたいものをsubjectにいれる

assert_equalの第2引数に当たるものとか

assert_equal 'expect', @actual

そのためにdescribeを切る

context "when called with a bogus key" do
  before { get :show, 'key' => 'bogus' }

  it { # other example }

  describe "response" do
    subject { response }

    its(:code){ should eq('400') }

    its(:body){ should be_blank }
  end
end

(議論ありそう)

微妙な例

describe "getting friend" do
  before { u.get_friend(me) }

  it "counts me as a friend" do
    u.should have(1).friends
  end

  it "counts u as a friend" do
    me.should have(1).friends
  end
end
describe "getting friend" do
  before { u.get_friend(me) }

  describe "u" do
    subject { u }
    it { should have(1).friends }
  end

  describe "me" do
    subject { me }
    it { should have(1).friends }
  end
end

分からない事(1)

expect{ subject }.toェ…

itで書けないんですか?

おわり

ありがとうございました。