-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cachable: make sure to clear caches between tests #16746
cachable: make sure to clear caches between tests #16746
Conversation
This adds a registry for all modules and classes that cachable is included in. The registry allows us to programmatically clear all caches in between tests so that we don't forget to do that when adding a new class or refactoring code. The goal here is to reduce the number of flaky tests in the future.
Library/Homebrew/api/formula.rb
Outdated
|
||
class << self |
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.
Might as well use private_class_method
and move everything to def self.*
here.
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 be done in a follow-up PR though.
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.
I didn't think that'd work but it seems fine. Good idea!
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.
Sorry, I got confused. Yeah, I'll update that too.
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.
Might not be worth killing the git blame though. I'll do it anyway and see if anyone cares.
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.
Addressed in bea2dc6
Library/Homebrew/extend/cachable.rb
Outdated
# Collect all classes that mix in Cachable so that those caches can be cleared in-between tests. | ||
if ENV["HOMEBREW_TESTS"] | ||
def self.included(klass) | ||
raise ArgumentError, "Don't use Cachable with singleton classes" if klass.singleton_class? |
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.
Why does this need to be special-cased/forbidden?
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 we not call klass.extend(self)
in here, or is that a different scope?
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.
I don't think there is a method to get the original class from the singleton class. Forcing classes to extend this module instead of including it in the singleton class avoids that problem and is functionally equivalent.
Library/Homebrew/extend/cachable.rb
Outdated
@@ -11,4 +11,43 @@ def cache | |||
def clear_cache | |||
cache.clear | |||
end | |||
|
|||
# Collect all classes that mix in Cachable so that those caches can be cleared in-between tests. | |||
if ENV["HOMEBREW_TESTS"] |
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.
I wonder, could we implement this as a test helper with allow(Cachable).to receive(:extended)
?
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.
I don't think so. It needs to be set up before other classes start mixing in this module. I thought of another way of doing this where we load a separate file in test/support/extend/
with these cachable methods before loading global.rb
and then we can be sure that this only gets loaded in the test environment.
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.
See 5cc1c85
I'm marking this as ready for review since it no longer changes any of the same files as #16671 and should be useful whatever we decide to do there. |
Now we only include the cachable registry when running tests. We basically just load it first and add a bunch of methods to it before loading the rest of the formula files when we require global.rb. I added a check to make sure this require order is preserved. I also made a bunch of methods private, stop excluding classes that inherit from casks since it's unnecessary and add more docs.
These were changed to extend to make it easier to determine where the classes come to in the extended callback but that means that the file is somewhat inconsistent. On the one hand we're using class methods and on the other we're extend self. This cleans that up but now the diff is atrocious and the blame is even worse. Oh well...
909828c
to
bea2dc6
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.
Good idea, thanks again @apainintheneck!
@@ -202,16 +204,7 @@ | |||
config.around do |example| | |||
Homebrew.raise_deprecation_exceptions = true | |||
|
|||
Formulary.clear_cache | |||
Tap.each(&:clear_cache) |
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.
@apainintheneck, this needs to stay.
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.
Is it really necessary to clear taps at the instance level if we're already clearing Tap
, CoreTap
and CoreCaskTap
at the class level? I guess .clear_cache
doesn't clear the core tap instances, right?
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.
That is the @instance
instance variable.
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.
The core taps exist outside of the normal cache busting cycle so they need to clear explicitly at the instance level. Just to be sure we should clear all of them each time. This essentially reverts part of the change in this PR. - #16746
brew style
with your changes locally?brew typecheck
with your changes locally?brew tests
with your changes locally?We've been seeing some difficult to debug test failures recently related to not clearing some caches between tests. Normally we use the
Cachable
mixin to facilitate caching in classes and modules. I thought it'd be nice to automatically clear those caches between tests without having to create a list manually of all of the classes and modules that use this mixin.This adds a registry for all modules and classes that cachable is included in. The registry allows us to programmatically clear all caches in between tests so that we don't forget to do that when adding a new class or refactoring code. The goal here is to reduce the number of flaky tests in the future. We only fill this registry
whenin the testing environment.HOMEBREW_TESTS
is setMarking draft to wait for discussion in #16671 since this will depend on that.