FullStack Labs

Please Upgrade Your Browser.

Unfortunately, Internet Explorer is an outdated browser and we do not currently support it. To have the best browsing experience, please upgrade to Microsoft Edge, Google Chrome or Safari.
Upgrade
Welcome to FullStack Labs. We use cookies to enable better features on our website. Cookies help us tailor content to your interests and locations and provide many other benefits of the site. For more information, please see our Cookies Policy and Privacy Policy.

Testing in Rails: RSpec Tips and Tricks

Expert advice on how to write good RSpec tests

Written by 
,
Testing in Rails: RSpec Tips and Tricks
blog post background
Recent Posts
Six Ways to Handle Concurrency in the JVM
Is there value in learning Vanilla JavaScript?
How to be efficient in remote design work in multicultural teams

Table of contents

What makes a good RSpec test?

RSpec is a testing framework written in Ruby to test Ruby code. To get started using RSpec with Rails, add it to the Gemfile.

	
group :development, :test do
  gem 'rspec-rails'
end
	

Next finish setting it up by running bundle install  in your project directory and then

	
rails generate rspec:install
	

It is easy to test for expected results, but how do you test for the unexpected? Good tests should include all edge cases, including best and worst-case scenarios; they should also be streamlined, very readable, and have redundancies eliminated.  

Readability

Readability is as much about containment as it is eliminating obfuscation, intentional or otherwise. 

Use contexts with scenarios to isolate possible edge cases. 

	
describe '#package_status' do
  context 'when package is delivered' do
    # it should send notice to customer
    # it should mark order as completed
  end 
  
  context 'when package is pending' do
  end

  context 'when package is shipped' do
    # it should send notice to customer
  end
end
	

Keep the waters from getting muddied when testing different methods; prepend `.` when testing class and `#` when testing instance. 

	
describe '#package_status' do
end

describe '.complete_orders' do
end
	

Ideally, you’ll keep each test as distinct and separate as possible so running down each one takes less work and makes for a more efficient process. 

Don’t Repeat Yourself: DRY up your tests

When you find yourself writing the same setup for multiple tests, put it in a shared context. Again, efficiency is the name of the game. Keeping tests as focused as possible will save time and effort. 

	
RSpec.shared_context 'pet_setup', shared_context: :metadata do
   let(:cat) { FactoryBot.create(:cat, name: ‘Mittens’, age: 10) }
   let(:dog) { FactoryBot.create(:dog, name: ‘Spot’, age: 2) }
   let(:fish) { FactoryBot.create(:fish, name: ‘Nemo’, age: 100) }
end
	

Shared examples are beneficial when testing the behavior of different types.

	
shared_examples 'pet_attributes' do |name, age|
  it 'returns its name' do
    expect(subject.name) to eq(name)
  end
  
  it 'returns an age' do
    expect(subject.age) to eq(age)
  end
end

describe '#pet_behavior' do
  include_context 'pet_setup'
  context 'when pet is a dog' do
    subject { dog }
    it_behaves_like 'pet_attributes', 'Spot', 2
  end

  context 'when pet is a fish' do
    subject { fish }
    it_behaves_like 'pet_attributes', 'Nemo', 100
  end
end
	

Speed up your Tests

Long test running times can be painful. If you’re keeping your tests separated and eliminating redundancies, you’ll want to zero in on any taking longer than they should. 

To see your top 10 slowest tests, append --profile to your rspec command.

	
bundle exec rspec spec/models/dog_spec.rb --profile
	

In controller tests, you can reduce network requests by using before blocks and modifying the parameters in each context.

	
describe '#post' do
  let(:user) { authorized_user }
  let(:order_params) { user_id: user.id, cart: shopping_cart }
  before do
    post 'orders' params: order_params
  end
  
  context 'when user is authorized' do
      it 'returns a successful response'
      it 'returns a 200'
      it 'fires off a notification'
  end
  
  context 'when user is not authorized' do
    let(:user) { unauthorized_user }
    It 'returns a flash message'
    It 'redirects user to a sign up page'
  end
end
	

Resources to learn more about using RSpec with Ruby

https://relishapp.com/rspec

https://github.com/rspec/rspec-rails

https://pragprog.com/book/rspec3/effective-testing-with-rspec-3

Conclusion

Using techniques like what is listed above, we have had the opportunity to address clients’ concerns and they love it! If you are interested in joining our team, please visit our Careers page.

Written by
People having a meeting on a glass room.
Join Our Team
We are looking for developers committed to writing the best code and deploying flawless apps in a small team setting.
view careers
Desktop screens shown as slices from a top angle.
Case Studies
It's not only about results, it's also about how we helped our clients get there and achieve their goals.
view case studies
Phone with an app screen on it.
Our Playbook
Our step-by-step process for designing, developing, and maintaining exceptional custom software solutions.
VIEW OUR playbook
FullStack Labs Icon

Let's Talk!

We’d love to learn more about your project.
Engagements start at $75,000.

company name
name
email
phone
Type of project
How did you hear about us?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.