Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion tests/tools/private/release/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ load("//tests/support/pytest_test:pytest_test.bzl", "pytest_test")

py_library(
name = "release_test_helper",
srcs = ["release_test_helper.py"],
srcs = [
"conftest.py",
"release_test_helper.py",
],
target_compatible_with = SUPPORTS_BZLMOD,
deps = [
"//tools/private/release:mock_gh",
Expand Down
50 changes: 50 additions & 0 deletions tests/tools/private/release/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import dataclasses
from unittest.mock import MagicMock

import pytest

pytest_plugins = ["tests.tools.private.release.release_test_helper"]


@dataclasses.dataclass
class AutoPatchCmdHelpers:
"""Dataclass holding mocked command helpers."""

run_cmd: MagicMock
run_git: MagicMock
run_gh: MagicMock


@pytest.fixture(name="mock_run_cmd")
def fixture_mock_run_cmd(mocker):
"""Fixture to patch shell.run_cmd and its imports in git and gh modules."""
mock = mocker.patch("tools.private.release.shell.run_cmd")
mocker.patch("tools.private.release.git.run_cmd", mock)
mocker.patch("tools.private.release.gh.run_cmd", mock)
return mock


@pytest.fixture(name="mock_run_git")
def fixture_mock_run_git(mocker):
"""Fixture to patch Git._run_git."""
return mocker.patch("tools.private.release.git.Git._run_git")


@pytest.fixture(name="mock_run_gh")
def fixture_mock_run_gh(mocker):
"""Fixture to patch GitHub._run_gh."""
return mocker.patch("tools.private.release.gh.GitHub._run_gh")


@pytest.fixture(name="auto_patch_cmd_helpers", autouse=True)
def fixture_auto_patch_cmd_helpers(mock_run_cmd, mock_run_git, mock_run_gh):
"""Automatically patches run_cmd, Git, and GitHub CLI helpers.

This prevents tests from executing command line tools that could have
side-effects.
"""
return AutoPatchCmdHelpers(
run_cmd=mock_run_cmd,
run_git=mock_run_git,
run_gh=mock_run_gh,
)
18 changes: 18 additions & 0 deletions tests/tools/private/release/gh_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pytest

from tools.private.release import shell
from tools.private.release.gh import GitHub
from tools.private.release.git import Git

pytest_plugins = ["tests.tools.private.release.release_test_helper"]

Expand Down Expand Up @@ -59,3 +61,19 @@ def test_resolve_pr_number_invalid(mocker, gh):
with pytest.raises(ValueError, match="Could not resolve PR reference"):
gh.resolve_pr_number("invalid-ref")
mock_run_cmd.assert_not_called()


def test_auto_patched_helpers_prevent_real_execution(auto_patch_cmd_helpers):
# Calling run_cmd directly hits the mock
shell.run_cmd("echo", "test")
auto_patch_cmd_helpers.run_cmd.assert_called_with("echo", "test")

# Git._run_git hits the mock
git = Git(".")
git._run_git("status")
auto_patch_cmd_helpers.run_git.assert_called_with("status")

# GitHub._run_gh hits the mock
gh_obj = GitHub("foo/bar")
gh_obj._run_gh("issue", "list")
auto_patch_cmd_helpers.run_gh.assert_called_with("issue", "list")