As a developer, I constantly look for improving my code. Also in terms of tests. For me, it’s important to keep tests clean in order to add new tests to be a pleasure, not a drudgery.
First time I stumbled across the shared context when I was looking for something that can help me to extract some constantly repeated variables in tests. The shared context was exactly what I was looking for.
What do we test?
Assume we have to write a few policy objects:
# lib/policies/user_settings_policy.rb
class UserSettingsPolicy
def can_show?
user.admin? || user.id == resource.id
end
private
attr_reader :user, :resource
def initialize(user, resource)
@user = user
@resource = resource
end
end
To test the policy object we need an admin user and a user who is the owner of a resource.
It’s time for the shared context
I’ve created the shared directory inside of the spec catalogue:
# spec/shared/users.rb
RSpec.shared_context :users do
let(:user_id) { SecureRandom.uuid }
let(:user) do
Models::User.new(
id: user_id,
first_name: 'Nick',
last_name: 'Owen',
email: '[email protected]'
)
end
let(:admin_id) { SecureRandom.uuid }
let(:admin) do
Models::User.new(
id: admin_id,
first_name: 'Jack',
last_name: 'Jones',
email: '[email protected]',
role: :admin
)
end
end
Load the shared context in the spec_helper.rb file:
Dir[File.expand_path('shared/**/*.rb', __dir__)].each { |f| require f }
Now the spec file is clearer:
# spec/policies/user_settings_policy_spec.rb
RSpec.describe UserSettingsPolicy do
include_context :users
let (:resource) { Models::UserSettings.new(user_id: user_id) }
describe '#can_show?' do
context 'when a user has an admin role' do
subject { described_class.new(admin, resource) }
it 'returns true' do
expect(subject.can_show?).to be_truthy
end
end
end
end
Summary
The shared context is a good place to put variables that we use in more than one spec file. If you need you can also put mocks in your context. I really encourage you to write small shared contexts in order to easily include just what you need and keep the proper naming of context files.