-
-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Added tests for utils/git #2955
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
Conversation
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 use system git, "init"? We only use backticks when we want the output as a string.
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.
Using system to execute these git commands are failing the tests. git add and commit aren't being executed properly.
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.
What's failing about them? It'd be good to fix that, rather than ignore the failure using backticks.
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 this test title correct? before_commit isn't nil 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.
I've corrected it now.
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.
Nitpick, but how about repo.join("file").to_s instead?
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.
Returns what?
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.
Returns nil
Made the change
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.
Don't see the change 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.
its(:git_path) { is_expected.to be nil }
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.
We can't guarantee this path will always be this exact string - it could also be the Homebrew-installed git, the CLT-provided git, etc. For example, on my system:
expected: "/Applications/Xcode.app/Contents/Developer/usr/bin/git"
got: "/usr/local/bin/git"
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.
So, should I just test if the returned value inlcudes only "git"?
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.
If we can stub it, let's do that - then it'll behave consistently even on systems that don't actually have git.
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.
You're testing the right behaviour, but this one surprises me! I didn't realize this was the case.
|
Looks like we've got one failure: |
|
I get this additional failure locally: |
|
A few failures on Linux: As noted earlier, we can't count on the Xcode path to be there on every system. Linuxbrew uses a different remote. Not sure what's going on here! |
MikeMcQuaid
left a comment
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.
Made a bunch of style comments.
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.
Favour using let over @ instance variables.
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.
(repo/"file").write "blah"
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'll have to explicitly close the file as well if I write open and write separately. Why do you think (repo/"file").write "blah" is a better way?
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.
(repo/"lib").mkpath
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.
system "git", "add", "repo/#{file}" and same with all other calls
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.
What are the reasons for preferring system "git", "add", "repo/#{file}" over system "#{git} add repo/#{file}" ?
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.
Consider setting up the hash1 variable to avoid needing to [0..6] in the test
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.
Use Pathname#/ rather than .join everywhere
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.
Split this and other long lines onto multiple lines.
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.
What are your views about adding a brew style violation for a line length greater than a certain number of characters? @mistydemeo @MikeMcQuaid
I have no clue how it can be done. Just a suggestion.
|
CC @reitermarkus for RSpec form check. |
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.
This test is behaving weird on my system. It passes sometimes and fails at other times.
Basically, git_available? is returning nil and false too at some times.
MikeMcQuaid
left a comment
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.
In general I think it's worth trying to minimise the usage of mocks/stubs here if possible. If not possible: no worries.
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.
system git, "init"
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.
(repo/file).write("blah"). That doesn't require an explicit close because it's handled automatically by Pathname#write.
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 get the following error if I use Pathname#write :
Failure/Error: (repo/file).write("blah")
RuntimeError:
Will not overwrite repo/lib/blah.rb
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.
(repo/file).write("blah"). That doesn't require an explicit close because it's handled automatically by Pathname#write.
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'd still say this form with a previous unlink is probably nicer but feel free to leave as-is and just change the case above.
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.
Don't see the change 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.
I think it may be worth allowing the git shim to be called. What fails if it is?
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 think it may be worth allowing the git shim to be called. What fails if it is?
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.
It returns different path values for different systems. The mocking attempts to avoid that.
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.
@mansimarkaur I think we could just check for ends_with?("git") or similar. That would make this partially an integration test for the shim too, which would be great.
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.
its(:git_path) { is_expected.to be nil }
Library/Homebrew/utils/git.rb
Outdated
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.
This is not the same as before.
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 previous behaviour was wrong. If before_commit is not nil, it did not work correctly.
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.
How exactly was it wrong?
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.
If before_commit is nil, args become "--skip=1" but if before_commit is say, "0..3", then args should be "--skip=0" while previously args became just 0.
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's the correct behaviour. When no commit range is given, it should just skip the latest commit, i.e. --skip=1, otherwise, it should pass the first commit of the commit range to git log, so it will only show commits before that commit (before_commit).
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.
So, then do you think the modifications made are correct? @reitermarkus
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.
No, it should either be "--skip=1", or when there is a commit range, i. e. before_commit = "aabbcc...ddeeff", it should be just "aabbcc", not "--skip=aabbcc".
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 understand it now. I've reverted the change.
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.
Don't use instance variables. Use let(:repo) { … }.
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.
How do you suggest I use let with before(:all) and after(:all) blocks?
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 it have to be before(:all)?
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.
Realised I can do away with the before(:all) block. Hence, removed it. Thanks :)
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.
This isn't needed, since the test isn't OS-specific.
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.
If I mock git_available? to return false and also mock the existence of CoreTap.instance.formula, running safe_system to install git raises an error since git is already installed on my system. What could be the workaround to mock a system that doesn't have brew installed git?
Thanks!
@mistydemeo @MikeMcQuaid @reitermarkus
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.
expect(described_class).to receive(:safe_system).with(HOMEBREW_BREW_FILE, "install", "git").and_return(nil) should work to mock the safe_system call.
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.
If git was installed successfully, safe_system would return true and not nil. How should we check for that since git will be pre-installed and an error will come up?
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.
You can mock it to return true! It doesn't look like anything actually checks the return value of safe_system though - the error handling is in the system call it's wrapping, and since we're skipping that by mocking safe_system it should be okay.
b23b8bb to
c5a6774
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.
(repo/file).write("blah") and skip the touch above.
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.
This gives the following error:
Failure/Error: (repo/file).write("brew")
RuntimeError:
Will not overwrite repo/lib/blah.rb
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.
Have you removed the touch above?
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.
Yes. I have removed the touch. I still get the above mentioned error.
MikeMcQuaid
left a comment
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.
As a general comment: there's still a lot here that's relying on internal instance variables and state. It shouldn't ever be necessary to manually set an instance variable to hit full coverage on tests (and full line coverage rather than branch coverage is the goal). In general the more stuff is relying on internal implementation details in a class the more a simple refactoring of this class with require breaking and rewriting all of the tests. On the flip side, the more stubbing done inside the class the less we're testing the actual functionality. Ideally we want these to be essentially integration tests where we manipulate the inputs and outputs for the functions rather than the internals of the functions themselves.
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 think this gets a bit too far into the implementation details. As @reitermarkus said: we shouldn't need to set instance variables in a test.
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 possible instead to stub the lookup so it fails to find Git rather than overriding an 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.
Thanks for suggesting this, @MikeMcQuaid ! :)
c5a6774 to
06de809
Compare
mistydemeo
left a comment
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 new changes look good to me. I see there are still a couple of comments by @reitermarkus and @MikeMcQuaid which haven't been addressed.
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.
Move this into the it block, since it is only used once.
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.
Move this into the it block, since it is only used once.
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.
Move this into the it block, since it is only used once.
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.
You don't need to touch here given you're immediately writing to 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.
Could put this in one of these dirs to avoid the manual cleanup (and be consistent):
brew/Library/Homebrew/test/spec_helper.rb
Lines 110 to 129 in 2c43e06
| FileUtils.rm_rf [ | |
| TEST_DIRECTORIES.map(&:children), | |
| HOMEBREW_LINKED_KEGS, | |
| HOMEBREW_PINNED_KEGS, | |
| HOMEBREW_PREFIX/".git", | |
| HOMEBREW_PREFIX/"bin", | |
| HOMEBREW_PREFIX/"share", | |
| HOMEBREW_PREFIX/"opt", | |
| HOMEBREW_PREFIX/"Caskroom", | |
| HOMEBREW_LIBRARY/"Taps/caskroom", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bar", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", | |
| HOMEBREW_REPOSITORY/".git", | |
| CoreTap.instance.path/".git", | |
| CoreTap.instance.alias_dir, | |
| CoreTap.instance.path/"formula_renames.json", | |
| ] |
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.
Need to try and figure out a way to not set/get instance variables here. If need be: delete the relevant tests that need them set given we're almost at the end of GSoC. Ideally: just call other methods that end up calling these ones.
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.
Instead of mktmpdir write to an already existing location that's deleted after tests: for example:
brew/Library/Homebrew/test/spec_helper.rb
Lines 110 to 129 in 2c43e06
| FileUtils.rm_rf [ | |
| TEST_DIRECTORIES.map(&:children), | |
| HOMEBREW_LINKED_KEGS, | |
| HOMEBREW_PINNED_KEGS, | |
| HOMEBREW_PREFIX/".git", | |
| HOMEBREW_PREFIX/"bin", | |
| HOMEBREW_PREFIX/"share", | |
| HOMEBREW_PREFIX/"opt", | |
| HOMEBREW_PREFIX/"Caskroom", | |
| HOMEBREW_LIBRARY/"Taps/caskroom", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bar", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", | |
| HOMEBREW_REPOSITORY/".git", | |
| CoreTap.instance.path/".git", | |
| CoreTap.instance.alias_dir, | |
| CoreTap.instance.path/"formula_renames.json", | |
| ] |
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.
Instead of mktmpdir write to an already existing location that's deleted after tests: for example:
brew/Library/Homebrew/test/spec_helper.rb
Lines 110 to 129 in 2c43e06
| FileUtils.rm_rf [ | |
| TEST_DIRECTORIES.map(&:children), | |
| HOMEBREW_LINKED_KEGS, | |
| HOMEBREW_PINNED_KEGS, | |
| HOMEBREW_PREFIX/".git", | |
| HOMEBREW_PREFIX/"bin", | |
| HOMEBREW_PREFIX/"share", | |
| HOMEBREW_PREFIX/"opt", | |
| HOMEBREW_PREFIX/"Caskroom", | |
| HOMEBREW_LIBRARY/"Taps/caskroom", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bar", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", | |
| HOMEBREW_REPOSITORY/".git", | |
| CoreTap.instance.path/".git", | |
| CoreTap.instance.alias_dir, | |
| CoreTap.instance.path/"formula_renames.json", | |
| ] |
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.
Write to an already existing location that's deleted after tests: for example:
brew/Library/Homebrew/test/spec_helper.rb
Lines 110 to 129 in 2c43e06
| FileUtils.rm_rf [ | |
| TEST_DIRECTORIES.map(&:children), | |
| HOMEBREW_LINKED_KEGS, | |
| HOMEBREW_PINNED_KEGS, | |
| HOMEBREW_PREFIX/".git", | |
| HOMEBREW_PREFIX/"bin", | |
| HOMEBREW_PREFIX/"share", | |
| HOMEBREW_PREFIX/"opt", | |
| HOMEBREW_PREFIX/"Caskroom", | |
| HOMEBREW_LIBRARY/"Taps/caskroom", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bar", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-bundle", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-foo", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-services", | |
| HOMEBREW_LIBRARY/"Taps/homebrew/homebrew-shallow", | |
| HOMEBREW_REPOSITORY/".git", | |
| CoreTap.instance.path/".git", | |
| CoreTap.instance.alias_dir, | |
| CoreTap.instance.path/"formula_renames.json", | |
| ] |
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.
Use repo.cd do
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.
Need to try and figure out a way to not set/get instance variables here. If need be: delete the relevant tests that need them set given we're almost at the end of GSoC. Ideally: just call other methods that end up calling these ones.
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.
Need to try and figure out a way to not set/get instance variables here. If need be: delete the relevant tests that need them set given we're almost at the end of GSoC. Ideally: just call other methods that end up calling these ones.
Library/Homebrew/utils/git.rb
Outdated
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.
@reitermarkus This look correct to you?
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.
No, it should still be the relative path. Might be that git show also supports absolute paths, but relative is definitely cleaner.
65d7b48 to
9224444
Compare
|
Please review, @MikeMcQuaid . Thanks! |
|
Looks good to me! Mind updating the commit history for merging? |
4e07853 to
df3be75
Compare
Requested changes have been made
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 are you using an instance variable here? Wasn't this only a workaround for before(:all)? let should work with before(:each).
df3be75 to
784250d
Compare
|
Thanks again @mansimarkaur! |
brew testswith your changes locally?