Reputation: 1491
I was watching a codeschool screencast on using RSpec and it had the following lines:
describe Game do
describe '#call' do
let(:description) do |example|
example.description
end
context 'when the choices are different' do
subject(:game) { described_class.new }
it 'rock beats scissors' do |example|
expect(subject.call('rock', 'scissors')).to eq(description)
end
end
end
end
I don't quite see how example
argument gets into the 'let' block? Is that a Ruby thing or RSpec magic? Thanks.
Upvotes: 1
Views: 78
Reputation: 28285
See this line in the rspec-core
source:
# Simplified version of the code:
def let(name, &block)
# ...
if block.arity == 1
define_method(name) { super(RSpec.current_example, &nil) }
# ...
end
Because let
is re-evaluated for each test, it can be re-defined to include knowledge of the current test context.
Also worth noting is that RSpec.current_example
is thread-safe:
def self.current_example
RSpec::Support.thread_local_data[:current_example]
end
This means even if you are running parallel tests, each let
block will always be able to re-evaluate the current example correctly.
Upvotes: 2