Skip to content

test(tools): auto-patch release CLI helpers in conftest.py#3939

Merged
rickeylev merged 4 commits into
bazel-contrib:mainfrom
rickeylev:patch-release-test-mocks
Jul 22, 2026
Merged

test(tools): auto-patch release CLI helpers in conftest.py#3939
rickeylev merged 4 commits into
bazel-contrib:mainfrom
rickeylev:patch-release-test-mocks

Conversation

@rickeylev

@rickeylev rickeylev commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Add an autouse fixture in conftest.py for tests/tools/private/release that automatically patches run_cmd, Git._run_git, and GitHub._run_gh using pytest-mock. This prevents tests from executing command line tools that could have side-effects.

Add an autouse fixture in conftest.py for tests/tools/private/release that automatically patches run_cmd, Git._run_git, and GitHub._run_gh using pytest-mock. This prevents tests from executing command line tools that could have side-effects.

TAG=agy
CONV=b4972743-3d1e-4e9a-9623-cf1f25cfdd83
@rickeylev
rickeylev requested a review from aignas as a code owner July 20, 2026 17:35

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an autouse fixture auto_patch_cmd_helpers in a new conftest.py file to automatically mock command-line helpers (run_cmd, Git._run_git, and GitHub._run_gh) during testing, along with a corresponding test in gh_test.py to verify the mocks. The review feedback suggests simplifying this setup by only mocking run_cmd, as mocking the internal class methods is redundant and makes writing realistic unit tests more difficult. Code suggestions are provided to simplify both the fixture and the test assertions.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread tests/tools/private/release/conftest.py Outdated
Comment thread tests/tools/private/release/gh_test.py Outdated
@rickeylev

Copy link
Copy Markdown
Collaborator Author

@aignas any thoughts on conftest.py integration? In this PR, a conftest.py is added to a py_library that defines a fixture that should be automatically used, and things just magically work. Which is kind of neat.

Originally, though, I was thinking that pytest_test would glob conftest.py by default. I think that better matches pytest semantics?

@aignas

aignas commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

I agree, maybe just globbing conftest.py is indeed a good idea. Though gazelle has some logic of including the conftest.py, so the two would be clashing. It would be good to ask @dougthor42 about this as well.

@dougthor42 dougthor42 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I was thinking that pytest_test would glob conftest.py by default

Though gazelle has some logic of including the conftest.py, so the two would be clashing

Agreed, gazelle already has python_include_ancestor_conftest so it would be a little strange for pytest_test to glob all of them.


For the record, we (Quantum) have actively been moving away from using pytest's conftest magic precisely because goes against the "explicit dependencies" Bazel idiom.

We set both directives python_include_ancestor_conftest=False and include_pytest_conftest=False because our pre-Bazel conftest files had accumulated loads of cruft, and would pollute the dependency tree: a change in file A would bust the conftest.py cache and then bust the cache of every downstream target, even if those targets didn't use the fixtures defined in that conftest.

The docs for python_include_ancestor_conftest shows an example of 4 different conftest files getting added as dependencies. This mimics what pytest does under the hood, but it also means that my_test.py's cache is much more fragile. If my_test.py doesn't use any of the fixtures defined in //:conftest (even auto-used ones), then why does it depend on //:conftest?


This PR looks reasonable to me. All comments are optional / questions.

Comment thread tests/tools/private/release/conftest.py Outdated
Comment thread tests/tools/private/release/conftest.py Outdated
Comment thread tests/tools/private/release/conftest.py Outdated
Comment thread tests/tools/private/release/gh_test.py Outdated
Separate mock_run_cmd, mock_run_git, and mock_run_gh into individual fixtures, and collect them in the autouse auto_patch_cmd_helpers fixture.

TAG=agy
CONV=b4972743-3d1e-4e9a-9623-cf1f25cfdd83
TAG=agy
CONV=b4972743-3d1e-4e9a-9623-cf1f25cfdd83
TAG=agy
CONV=b4972743-3d1e-4e9a-9623-cf1f25cfdd83
@rickeylev

Copy link
Copy Markdown
Collaborator Author

auto-including conftest and including parent conftest is more idiomatic but makes bazel cache fragile

Hrm, yeah, these are good points. I guess the ideal solution would be to factor the directory structure into a more well-defined tree? Which, well, that's just a fancy way of saying "auto-include; cache fragility is the user's fault"

e.g.

squares/
  conftest.py # fixture_quadralateral, fixture_square
  rectangles/
    conftest.py # fixture_rectangle

-> change to

shapes/
  conftest.py # fixture_quadralateral
  squares/
    conftest.py # fixture_square
  rectangles/
    conftest.py # fixture_rectangle

I wonder if pytest_conftest_library() is needed? (though I guess that's basically just py_library)

Something I'm not clear on is what target conftest.py is supposed to go into. Right now, it all works because conftest.py is in the release_test_helper target, which is a dependency of all (supposedly) the tests. I guess more ideally it should be its own py_library target, and then every test should directly depend on it?

@rickeylev
rickeylev enabled auto-merge July 22, 2026 17:33
@rickeylev
rickeylev added this pull request to the merge queue Jul 22, 2026
Merged via the queue into bazel-contrib:main with commit d21d3f0 Jul 22, 2026
6 checks passed
@rickeylev
rickeylev deleted the patch-release-test-mocks branch July 22, 2026 17:49

@dougthor42 dougthor42 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

factor the directory structure into a more well-defined tree?

Yeah factoring the dir structure is one solution, but IME is typically not very feasible. It's really easy to end up over-defined and not know where to put anything new or where to put something that needs both fixture_square and fixture_rectangle (which is probably a sign you need to refactor your fixtures).

I wonder if pytest_conftest_library() is needed?

I don't think so. As you said, it's just a normal py_library. If it were to exist, how would it be different than py_library? If the only difference is "magic to add the other conftests as deps" then I'd be pretty strongly opposed because that would hide the explicit deps.

Where should conftest.py go?

A py_library as a dependency of any py_test that actually needs it. Old-school gazelle default behavior was to add the dep to any sibling py_test targets, but as mentioned above this leads to extraneous deps. Personally I use the # gazelle:include_dep :conftest annotation instead.

I'm also a big fan of "one file, one target", so I'm partial to a dedicated py_library for conftest. Given that you have autouse=True inside, all sibling and child python test files implicitly depended on it. So I would say yes each py_test target should have it as a direct dependency instead of indirect through release_test_helper. Use Bazel to turn the implicit dep to explicit.

Comment thread tests/tools/private/release/conftest.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants