test(tools): auto-patch release CLI helpers in conftest.py#3939
Conversation
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
There was a problem hiding this comment.
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.
|
@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? |
|
I agree, maybe just globbing |
dougthor42
left a comment
There was a problem hiding this comment.
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.
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
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. I wonder if Something I'm not clear on is what target |
dougthor42
left a comment
There was a problem hiding this comment.
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.
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.