旧
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 件のコメント:
コメントを投稿