Skip to content

Conversation

@mansimarkaur
Copy link
Contributor

  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same change?
  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes? Here's an example.
  • Have you successfully run brew tests with your changes locally?

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns what?

Copy link
Contributor Author

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

Copy link
Member

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?

Copy link
Member

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 }

Copy link
Contributor

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"

Copy link
Contributor Author

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"?

Copy link
Contributor

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.

Copy link
Contributor

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.

@mistydemeo
Copy link
Contributor

Looks like we've got one failure:

  1) Utils::git_remote_exists when git is available returns true when git remote exists
     Failure/Error: expect(described_class.git_remote_exists(@repo)).to be_truthy
       expected: truthy value
            got: false
     # ./test/utils/git_spec.rb:151:in `block (4 levels) in <top (required)>'
     # ./test/spec_helper.rb:91:in `block (2 levels) in <top (required)>'
     # ./vendor/bundle/ruby/2.0.0/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <top (required)>'

@mistydemeo
Copy link
Contributor

I get this additional failure locally:

  2) Utils::git_available? returns false if git --version command does not succeed
     Failure/Error: expect(described_class.git_available?).to be_falsey

       expected: falsey value
            got: true
     # ./test/utils/git_spec.rb:58:in `block (3 levels) in <top (required)>'
     # ./test/spec_helper.rb:91:in `block (2 levels) in <top (required)>'
     # ./vendor/bundle/ruby/2.0.0/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <top (required)>'

@mistydemeo
Copy link
Contributor

A few failures on Linux:

  1) Utils::git_path when git is available returns path of git
     Failure/Error: expect(described_class.git_path).to eq("/Applications/Xcode.app/Contents/Developer/usr/bin/git")
       expected: "/Applications/Xcode.app/Contents/Developer/usr/bin/git"
            got: "/usr/bin/git"

As noted earlier, we can't count on the Xcode path to be there on every system.

  2) Utils::git_remote_exists when git is available returns true when git remote exists
     Failure/Error: expect(described_class.git_remote_exists("[email protected]:Homebrew/brew")).to be_truthy
       expected: truthy value
            got: false

Linuxbrew uses a different remote.

  3) Utils::git_available? returns true if git --version command succeeds
     Failure/Error: expect(described_class.git_available?).to be_truthy
       expected: truthy value
            got: false

Not sure what's going on here!

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a 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.

Copy link
Member

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(repo/"file").write "blah"

Copy link
Contributor Author

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(repo/"lib").mkpath

Copy link
Member

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

Copy link
Contributor Author

@mansimarkaur mansimarkaur Aug 9, 2017

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}" ?

Copy link
Member

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

Copy link
Member

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

Copy link
Member

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.

Copy link
Contributor Author

@mansimarkaur mansimarkaur Aug 9, 2017

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.

@MikeMcQuaid
Copy link
Member

CC @reitermarkus for RSpec form check.

Copy link
Contributor Author

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.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a 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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

system git, "init"

Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Member

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.

Copy link
Member

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.

Copy link
Member

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?

Copy link
Member

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?

Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Member

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 }

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

@mansimarkaur mansimarkaur Aug 11, 2017

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.

Copy link
Member

@reitermarkus reitermarkus Aug 16, 2017

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).

Copy link
Contributor Author

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

Copy link
Member

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".

Copy link
Contributor Author

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.

Copy link
Member

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) { … }.

Copy link
Contributor Author

@mansimarkaur mansimarkaur Aug 11, 2017

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?

Copy link
Member

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)?

Copy link
Contributor Author

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 :)

Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

@MikeMcQuaid MikeMcQuaid left a 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.

Copy link
Member

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.

Copy link
Member

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?

Copy link
Contributor Author

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 ! :)

@mansimarkaur mansimarkaur changed the title [WIP] Added tests for utils/git Added tests for utils/git Aug 16, 2017
Copy link
Contributor

@mistydemeo mistydemeo left a 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.

Copy link
Member

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.

Copy link
Member

@reitermarkus reitermarkus Aug 20, 2017

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.

Copy link
Member

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.

Copy link
Member

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.

Copy link
Member

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):

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",
]

Copy link
Member

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.

Copy link
Member

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:

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",
]

Copy link
Member

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:

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",
]

Copy link
Member

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:

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",
]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use repo.cd do

Copy link
Member

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.

Copy link
Member

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.

Copy link
Member

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?

Copy link
Member

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.

@mansimarkaur
Copy link
Contributor Author

Please review, @MikeMcQuaid . Thanks!

@mistydemeo
Copy link
Contributor

Looks good to me! Mind updating the commit history for merging?

@mansimarkaur mansimarkaur force-pushed the git_tests branch 2 times, most recently from 4e07853 to df3be75 Compare August 26, 2017 19:48
@mistydemeo mistydemeo dismissed MikeMcQuaid’s stale review August 27, 2017 01:15

Requested changes have been made

Copy link
Member

@reitermarkus reitermarkus Aug 29, 2017

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).

@MikeMcQuaid MikeMcQuaid merged commit 3bb9871 into Homebrew:master Sep 2, 2017
@MikeMcQuaid
Copy link
Member

Thanks again @mansimarkaur!

@Homebrew Homebrew locked and limited conversation to collaborators May 4, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants