How to keep RSpec tests manageable

To learn RoR, I started using the excellent Rails Tutorial . So far so good, although I noticed that RSpec tests quickly turn into confusion. The following is a sample integration test for session_controller.rb. It will only be bigger when I continue.

Is there a logical way to split and break these tests into smaller pieces? How would you do it and based on what criteria? Examples would be most welcome.

Example:

require 'spec_helper' describe "AuthenticationPages" do subject { page } describe "signin" do before { visit signin_path } it { should have_selector('h1', text: 'Sign in') } it { should have_selector('title', text: full_title('Sign in')) } describe "with invalid information" do before { click_button "Sign in" } it { should have_selector('title', text: full_title('Sign in')) } it { should have_selector('div.flash.error', text: 'Invalid') } it { should_not have_link('Profile', href: signout_path ) } it { should_not have_link('Settings', href: edit_user_path) } describe "after visiting another page" do before { click_link "Home" } it { should_not have_selector('div.flash.error') } end end describe "with valid information" do let(:user) { FactoryGirl.create(:user) } before do fill_in "Email", with: user.email fill_in "Password", with: user.password click_button "Sign in" end it { should have_selector('title', text: user.name) } it { should have_link('Profile', href: user_path(user)) } it { should have_link('Settings', href: edit_user_path(user)) } it { should have_link('Users', href: users_path) } it { should have_link('Sign out', href: signout_path) } it { should_not have_link('Sign in', href: signin_path) } describe "visiting the sign up page" do before { visit sign_up_path } it { should_not have_selector('h1', text: 'Sign Up') } it { should_not have_selector('title', text: full_title('Sign Up')) } end describe "submitting to the create action" do before { post users_path(user) } specify { response.should redirect_to(user_path(user)) } end describe "followed by signout" do before { click_link "Sign out" } it { should have_link('Sign in') } end end end describe "authorization" do describe "for non-signed-in users" do let(:user) { FactoryGirl.create(:user) } describe "in the users controller" do describe "visiting the edit page" do before { visit edit_user_path(user) } it { should have_selector('title', text: 'Sign in') } end describe "submitting to the update action" do before { put user_path(user) } specify { response.should redirect_to(signin_path) } end end describe "visiting user index" do before { visit users_path } it { should have_selector('title', text: 'Sign in') } end describe "when attempting to visit a protected page" do before do visit edit_user_path(user) sign_in user end describe "after signing in" do it "should render the desired protected page" do page.should have_selector('title', text: 'Edit user') end describe "when signing in again" do before do visit signin_path sign_in user end it "should render the default (profile) page" do page.should have_selector('title', text: user.name) end end end end end describe "as wrong user" do let(:user) { FactoryGirl.create(:user) } let(:wrong_user) { FactoryGirl.create(:user, email: " wrong@example.com ") } before { sign_in user } describe "visiting users#edit page" do before { visit edit_user_path(wrong_user) } it { should have_selector('title', text: 'Sample App') } end describe "submitting a PUT request to the users#update action" do before { put user_path(wrong_user) } specify { response.should redirect_to(root_path) } end end describe "as non-admin user" do let(:user) { FactoryGirl.create(:user) } let(:non_admin) { FactoryGirl.create(:user) } before { sign_in non_admin } describe "submitting a DELETE request to the Users#destroy action" do before { delete user_path(user) } specify { response.should redirect_to(root_path) } end end end end 
+4
source share
1 answer

Well, after seeing how you already use RSpec with shoulda (is that right?), I think you have achieved a high level of readability and manageability. You can always split this specification into smaller parts, but you have to ask yourself what you need to split the test code for one controller? You have many describe sections that are well versed in structuring tests. If something fails, RSpec will always give you the exact line number so you can go straight to it and fix it.

Regarding extra readability, I notice that you are using blank lines after the describe sections. Some people like to insert blank lines before end statements. I also recommend writing down which block you end with the end statement, for example:

 describe "GET /posts" do #[...] end # GET /posts 

With such structured sections, there is also a good feature in many editors that allows you to compress the code inside these blocks, hiding the code and displaying the end immediately after describe . I believe that you will sort this as you wish. I never thought about extra readability or what was beyond the basics, and I can manage the tests that I wrote completely correctly.

Hope that convinces you that you already have a great way to organize your code. I don’t think that splitting tests aimed at the same functionality / object / goal, it makes sense to just keep it under the lines < 100 or so.

Update

I recently read an article in which DHH states that RSpec is uselessly complex and that test/unit readable and easy to maintain. I thought you might know that.

+4
source

Source: https://habr.com/ru/post/1398099/


All Articles