RSpec 2 Best practices
-
Upload
andrea-reginato -
Category
Technology
-
view
506.484 -
download
0
description
Transcript of RSpec 2 Best practices
Rspec Best Practices
Ruby Social Club Milano
Andrea Reginatotwitter/andreareginato
24 February 2011
I'll not teach RSpec
twitter/andreareginato
The RSpec Book
You have good books and web sites
Rails Test Prescriptions
I'll tell you how I use RSpec
twitter/andreareginato
What I've learned reading bookssome articles on the webbut most important from
my everyday job experience
Just a little introduction
twitter/andreareginato
RSpec is a library that focus on testing the behavior of your
everyday project
Why people do not use it
twitter/andreareginato
Probably the testing practice is the most diffcult forma mentis a
developer have to learn
It will save our life, maybe
twitter/andreareginato
In the long term, you will not check your web page everytime you
make a new feature, but you will check if your test passed
Short descriptions# wrong
# correct
it "should have 422 status code if an unexpected params will be added" do
response.should respond_with 422end
context "when not valid" it { should respond_with 422 }
(over)use contexts # wrong
# correct
it "should have 200 status code if logged in" do response.should respond_with 200end
context "when logged in" do it { should respond_with 200 }end
and use with/when as keys
Describe methods# wrong
# correct
describe "the authenticate method for User logged in" ...
describe "if the user is an admin" do
describe ".authenticate" dodescribe "#admin?"
Single expectation test# wrong
# correct
it "should create a resource" do response.should respond_with_content_type(:json) response.should assign_to(:resource)end
it { should respond_with_content_type(:json) } it { should assign_to(:resource) }
Test the edge cases# sample action
def destroy @resource = Resource.where(:id => params[:id]) if @resource @resource.destroy head 204 else render :template => "shared/404", :status => 404, end end
What would you test ?
Test the edge case# correctdescribe "#destroy" do context "when resource is found" do it "should render_with 204" it "should assign @resource" context "when resource is not found" do it "should render with 404" it "should not assign @resource" endend
Is this enough ?
Use the subject# wrong
# correct
it { assigns("message").should match /The resource name is Genoveffa/ }it { assigns("message").should match
/it was born in Billyville/ }it { assigns("message").creator.should match
/Claudiano/ }
subject { assigns("message") }it { should match /The resource name is Genoveffa/ }it { should match /it was born in Billyville/ }its(:creator) { should match /Claudiano/ }
Mock or not to mock# wrong (a really personal point of view)
# correct
1) It's wrong when you never mock and recreate by code a “medium complex” situation and it's time consuming
# simulate authenticated usercontroller.stub!(:authenticate).and_return(true)# simulate current usercontroller.stub(:current_user).and_return(current_user)# simulate not found recordResource.stub(:where).with(created_from: id)
.and_return(false)
2) It's wrong when you mock everything. You have a light system and the big advantage of independence, but you loose part of the control on your application.
Create data when needed# wrong
# correct
You shouldn't use fixtures* loose control on our data* load everything all the time* difficult to find problems
describe "User" describe ".top" do before { 3.times { Factory(:user) } } it { User.top(2).should have(2).item } endend
describe "User" describe ".top" do before { 3.times { Factory(:user) } } it { User.top(2).should have(2).item } endend
Shared examples to DRY# wrongcontext "when own resources" do it "should have it" do resource = Factory("user") do_get format: json assigns(users).should include(resource) endend
context "when does not own resource" do it "should not have it" do not_owned_resource = Factory("unknown") do_get format: json assigns(users).should_not include(not_owned_resource) endend
Shared examples to DRY
# correct (but why?)shared_examples for "a secure resource" do context "when own the resource" do it "should have it" do resource = Factory("user") do_get format: json assigns(users).should include(resource) end end context "when does not own resource" do it "should not have it" do not_owned_resource = Factory("unknown") do_get format: json assigns(users).should_not include(not_owned_resource) end endend
Shared examples to DRY
# correct (apply DRY on tests)describe "#show" do it_should_behave_like "a secure resource" it_should_behave_like "a findable resource" it_should_behave_like "a secure resource" context "when not logged in" do it_should_handle "a not authenticated request" endend
More?
# correct Start using RSpec 2 into your next project
# wrongDo not use RSpec
Thanks
# more info Click here to fnd a public document with a summary of all best practices
[email protected]# contacts
twitter/andreareginato