旧
describe User do
it "should be instance of User" do
Factory.create(:user).should be_instance_of(User)
end
it "should belongs to Guild" do
Factory.create(:user).guild.should be_instance_of(Guild)
end
describe "#add_exp(experience_point)" do
it "should not raise error" do
lambda{Factory.create(:user).add_exp(10) }.should_not raise_error
end
end
describe "::get_list()" do
it "should be instance of Array" do
User::get_list().should be_instance_of(Array)
end
end
end
新
describe User do
subject { Factory.create(:user) }
it { should be_instance_of(User) }
its(:guild){ should be_instance_of(Guild) }
describe "#add_exp(experience_point)" do
subject { lambda{Factory.create(:user).add_exp(10) } }
it { should_not raise_error }
end
describe "::get_list()" do
subject { User::get_list() }
it { should be_instance_of(Array) }
end
end
新旧を比較すると、新しい方は it メソッドが 1 行で書かれており、音読すれば意味が通じる内容と成っているのがわかると思います。(ex, it should not raise error)
それでは、どのようにして簡潔にしていくか、 4 ステップで見ていきましょう。
1. describe ブロック中の subject を定義する
subject メソッドを使い、この describe ブロックで、一体何の spec を書きたいのかを明確に記述します。
subject を定義することで、各 spec 中で subject を参照出来る様になります。
早速書きなおしてみましょう。
describe User do
subject { Factory.create(:user) } # このブロックは、 User のインスタンスを検証する
it "should be instance of User" do
subject.should be_instance_of(User)
end
it "should belongs to Guild" do
subject.guild.should be_instance_of(Guild)
end
describe "#add_exp(experience_point)" do
# このメソッドの実行結果を検証する
subject { lambda{Factory.create(:user).add_exp(10) } }
it "should not raise error" do
subject.should_not raise_error
end
end
describe "::get_list()" do
# このメソッドの返す値を検証する
subject { User::get_list() }
it "should be instance of Array" do
subject.should be_instance_of(Array)
end
end
end
2. subject は省略できる
ぶっちゃけ、subject がなくても、 it メソッドは適当に解釈してくれます。
もとい。もともと、 it メソッドにおいて暗黙のレシーバーが subject です。
describe User do
subject { Factory.create(:user) }
it "should be instance of User" do
should be_instance_of(User)
end
# ここはアトで。
it "should belongs to Guild" do
Factory.create(:user).guild.should be_instance_of(Guild)
end
describe "#add_exp(experience_point)" do
subject { lambda{Factory.create(:user).add_exp(10) } }
it "should not raise error" do
should_not raise_error
end
end
describe "::get_list()" do
subject { User::get_list() }
it "should be instance of Array" do
should be_instance_of(Array)
end
end
end
3. (単純なら) 記述は省略でき (自動生成でき) る。
RSpec では、-fs オプションを付けることで it メソッドのコメントを表示させることが出来ますが、各 spec 中で、出てくる should が 1 つ程度でしたら、 RSpec 自身によって仕様を自動記述出来ます。
it メソッドでコメントを省略すると、spec 中から無理やり記述が自動生成されます。
さらに、単純な spec なら 1 行程度なので do - end じゃなくて {} 使っても、あんまり見づらくなりませんので、どんどん省略しちゃいましょう。
逆に言えば、自動生成出来る程度の粒度で 1 つの spec を書くべきです。粒度は細かく。量は多めに!
describe User do
subject { Factory.create(:user) }
it { should be_instance_of(User) }
# ここはアトで。
it "should belongs to Guild" do
Factory.create(:user).guild.should be_instance_of(Guild)
end
describe "#add_exp(experience_point)" do
subject { lambda{Factory.create(:user).add_exp(10) } }
it { should_not raise_error }
end
describe "::get_list()" do
subject { User::get_list() }
it { should be_instance_of(Array) }
end
end
4. プロパティや簡単なメソッドとかは its で。
プロパティとか、プロパティっぽく振舞わせるメソッド (正確には、ruby の getter は全部メソッドだけど。。。) は、
it じゃなくて、its を使うと簡潔に書けます。 ただし、あくまでも簡単なプロパティ (の getter) 及びメソッド用です!
subject 自体の spec を書くなら、 it メソッド。subject のプロパティの spec なら its メソッドですな。
書き方は
its(:property_name){ should == true }
見てわかるとおり、
* describe ブロックで定義した subject ブロックの値 と it メソッド内の subject は同じ。
* (describe ブロックで定義した subject ブロックの値).property_name と its メソッド内の subject は同じ。
* property_name メソッドに引数を与えたい? それはムリだから、そういう場合はおとなしく子供の describe ブロックを書こう。
と、なります。
describe User do
subject { Factory.create(:user) }
it { should be_instance_of(User) }
its(:guild){ should be_instance_of(Guild) }
describe "#add_exp(experience_point)" do
subject { lambda{Factory.create(:user).add_exp(10) } }
it { should_not raise_error }
end
describe "::get_list()" do
subject { User::get_list() }
it { should be_instance_of(Array) }
end
end
次は「describe と context」「let」について書くことにします。
0 件のコメント:
コメントを投稿