-
-
Notifications
You must be signed in to change notification settings - Fork 103
Stash methods that get and set thread local variables to allow the user to mock them #606
Conversation
Can you please add a spec that would fail before your changes? |
@ioquatix we fixed a side issue of not being able to mock get_instance_variable. Does it still work for your uses? |
lib/rspec/support.rb
Outdated
Thread.current.thread_variable_get(:__rspec) || Thread.current.thread_variable_set(:__rspec, {}) | ||
end | ||
@thread_variable_get = Thread.instance_method(:thread_variable_get) | ||
@thread_variable_set = Thread.instance_method(:thread_variable_set) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically we've used a constant for these sort of stashing.
@thread_variable_set = Thread.instance_method(:thread_variable_set) | |
THREAD_SET = Thread.instance_method(:thread_variable_set) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typically we've used a constant for these sort of stashing.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please make sure you’ve pushed it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I forgot to stage the changes before amending and pushing.
I would argue that you shouldn't really be mocking the internals of thread, its not something you own, and this implementation still wouldn't allow you to mock |
@pirj I stopped using RSpec so I don't have any strong opinion about it. However, I still think it would be better to use |
c699dec
to
222b618
Compare
Done. Not sure how I missed that. |
222b618
to
444a160
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, however have you measured the performance overhead?
444a160
to
e6e3147
Compare
I pushed some performance optimization (using require 'benchmark'
require 'rspec'
out = StringIO.new
puts Benchmark::CAPTION
puts(Benchmark.measure do
RSpec.describe do
1000000.times do
it do
end
end
end
RSpec::Core::Runner.run([], out, out)
end)
out.seek(0)
puts out.readlines[-3..-2] Before this PR:
After this PR:
From these results, it’s only very slightly slower. However, the test conditions were not perfect (light background activity, power saving enabled). EDIT: These measurements were done on Ruby 3.3.1. |
…er to mock them Fixes #605.
e6e3147
to
6fa443f
Compare
To do some proper benchmarking, I should follow that and that. However, currently I don’t have a suitable machine available for that. |
Nice work, I assume pre-bind_call is more than trivially slower? |
The up to 10% slowdown on Ruby 2.6 described in my previous comment was this PR compared to the main branch. However, I’m not sure how much of the slowdown comes from the lack of I can do more benchmarks as soon as I can free some machine to do them without background load (which could be a few days). How detailed should it be? Does it even make sense to benchmark on end-of-life Ruby versions? |
I would personally not implement a feature like this if the performance was significantly impacted. There are many users of RSpec - probably millions of invocations per day. How many of them want even 1-2% slower execution because of this feature? |
Fixes rspec/rspec#103.
Alternative to #581 to fix #580