 
                    The best part of choosing Rspec as your tool for automated testing, is the possibility to describe your expectations with very readable sentences. Today, We will present to you two components of Rspec that can make it even more doable.
Shared Contexts
Shared contexts is a way to stick to the don’t repeat yourself rule. It allows us to reuse some test boilerplate such as let, subject, described_class, and other generalisms, for different sets of tests. Let’s see the example below:
# app/models/bottle.rbclass Bottle < ApplicationRecord MAX_CAPACITY = 330  def full?   current_content >= MAX_CAPACITY  endend
# app/models/bowl.rbclass Bowl < ApplicationRecord  MAX_CAPACITY = 600
  def full?    current_content >= MAX_CAPACITY  endEndLet’s imagine two models, Bottle and Bowl. As containers, they share a common method called full?. Let’s see how we could write our tests using shared_context:
 
# spec/support/shared_contexts/filled.rb RSpec.shared_context 'filled' do   let(:current_capacity) { 50 }   subject { described_class.new(current_capacity: current_capacity) } end # spec/models/bottle_spec.rb RSpec.describe Bottle, type: :model do  describe 'full?' do    context 'when the bottle is' do      context 'not full' do       include_context 'filled'       it 'returns false' do          expect(subject).to be_falsey       end    end      context 'is full' do       include_context 'filled' do        let(:current_capacity) { 330 }       end       it 'returns false' do        expect(subject).to be_falsey      end    end    end   end end# spec/models/bowl_spec.rbRSpec.describe Bowl, type: :model do  describe 'filled?' do   context 'when the bowl is' do    context 'not full' do     include_context 'filled'      it 'returns false' do       expect(subject).to be_falsey     end   end   context 'is full' do     include_context 'filled' do      let(:current_capacity) { 600 }<pre><code class="language-ruby">   end</code></pre>
     it 'returns true' do       expect(subject).to be_truthy     end    end  end endEnd
See? The tests are using the same configuration context and build different objects to run correctly. Easy and clean, no? Perfect but, reading the specs you could say: Ok, but the tests per si seem pretty equal to me and duplicated no? I need to agree with you. The next topic will help us to improve that.
Shared Examples
Shared examples allow us to reuse a bunch of tests for multiple features of our applications. Using the same example above, we could have something like this:
# spec/support/shared_examples/fillable_spec.rbRSpec.shared_examples 'Fillable' do |received_capacity|  describe 'full?' do    context "when the #{described_class.downcase}" is do      context 'not full' do        include_context 'filled'        it 'returns false' do          expect(subject).to be_falsey        end      end
        context 'is full' do        include_context 'filled' do          let(:current_capacity) { received_capacity }        end        it 'returns true' do          expect(subject).to be_truthy        end      end    end  endend# spec/models/bottle_spec.rbRSpec.describe Bottle, type: :model do  it_behaves_like 'Fillable', 330end# spec/models/bowl_spec.rbRSpec.describe Bowl, type: :model do  it_behaves_like 'Fillable', 600end
Clean and tidy code so when you look at it a year from now you’ll be proud. Shared context and examples are great tools to DRY up your code, make it more readable and pleasure to work with it. As with any examples, it’s best practice to be cautious about the complexity of the abstractions when using these tools. If you need to override variables of the context all the time, or over-configure the call to the shared examples, it could indicate you are in search of a different abstraction solution.