The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
RSpec 2 Best practices
1. Rspec Best Practices
Ruby Social Club Milano
24 February 2011
Andrea Reginato
twitter/andreareginato
2. I'll not teach RSpec
You have good books and web sites
The RSpec Book
Rails Test Prescriptions
twitter/andreareginato
3. I'll tell you how I use RSpec
What I've learned reading books
some articles on the web
but most important from
my everyday job experience
twitter/andreareginato
4. Just a little introduction
RSpec is a library that focus on
testing the behavior of your
everyday project
twitter/andreareginato
5. Why people do not use it
Probably the testing practice is the
most diffcult forma mentis a
developer have to learn
twitter/andreareginato
6. It will save our life, maybe
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
twitter/andreareginato
7. Short descriptions
# wrong
it "should have 422 status code if an
unexpected params will be added" do
response.should respond_with 422
end
# correct
context "when not valid"
it { should respond_with 422 }
8. (over)use contexts
and use with/when as keys
# wrong
it "should have 200 status code if
logged in" do
response.should respond_with 200
end
# correct
context "when logged in" do
it { should respond_with 200 }
end
9. Describe methods
# wrong
describe "the authenticate method for
User logged in" ...
describe "if the user is an admin" do
# correct
describe ".authenticate" do
describe "#admin?"
10. Single expectation test
# wrong
it "should create a resource" do
response.should respond_with_content_type(:json)
response.should assign_to(:resource)
end
# correct
it { should respond_with_content_type(:json) }
it { should assign_to(:resource) }
11. 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 ?
12. Test the edge case
# correct
describe "#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"
end
end
Is this enough ?
13. Use the subject
# wrong
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/ }
# correct
subject { assigns("message") }
it { should match /The resource name is Genoveffa/ }
it { should match /it was born in Billyville/ }
its(:creator) { should match /Claudiano/ }
14. Mock or not to mock
# wrong (a really personal point of view)
1) It's wrong when you never mock and recreate by code
a “medium complex” situation and it's time consuming
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.
# correct
# simulate authenticated user
controller.stub!(:authenticate).and_return(true)
# simulate current user
controller.stub(:current_user).and_return(current_user)
# simulate not found record
Resource.stub(:where).with(created_from: id)
.and_return(false)
15. Create data when needed
# wrong
You shouldn't use fixtures
* loose control on our data
* load everything all the time
* difficult to find problems
# correct
describe "User"
describe ".top" do
before { 3.times { Factory(:user) } }
it { User.top(2).should have(2).item }
end
end
16. Shared examples to DRY
# wrong
context "when own resources" 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
end
17. 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
end
end
18. 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"
end
end
19. More?
# wrong
Do not use RSpec
# correct
Start using RSpec 2 into your next project
20. Thanks
# more info
Click here to fnd a public document with a
summary of all best practices
# contacts
andrea.reginato@gmail.com
twitter/andreareginato