참고소스 수정본
This commit is contained in:
8
참고/guardrails-main/tests/unit_tests/cli/conftest.py
Normal file
8
참고/guardrails-main/tests/unit_tests/cli/conftest.py
Normal file
@@ -0,0 +1,8 @@
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def runner():
|
||||
from typer.testing import CliRunner
|
||||
|
||||
return CliRunner()
|
||||
225
참고/guardrails-main/tests/unit_tests/cli/db/test_downgrade.py
Normal file
225
참고/guardrails-main/tests/unit_tests/cli/db/test_downgrade.py
Normal file
@@ -0,0 +1,225 @@
|
||||
from importlib.metadata import PackageNotFoundError
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from guardrails.cli.db.db import db_command
|
||||
|
||||
|
||||
class TestDowngrade:
|
||||
def test_logs_error_when_guardrails_api_not_installed(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
side_effect=PackageNotFoundError("guardrails_api"),
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.downgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"[ERROR]: 'db downgrade' requires guardrails-api to be installed."
|
||||
)
|
||||
|
||||
def test_logs_error_when_guardrails_api_version_too_old(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.2.5",
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.downgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"[ERROR]: 'db downgrade' is only supported for guardrails-api>=0.3.0."
|
||||
" You have guardrails-api==0.2.5."
|
||||
)
|
||||
|
||||
def test_logs_error_when_minor_version_is_exactly_below_threshold(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.2.99",
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.downgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_error.assert_called_once()
|
||||
|
||||
def test_delegates_to_guardrails_api_with_defaults(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_downgrade.assert_called_once_with("-1", ".env", False)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_custom_revision(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade", "abc123"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_downgrade.assert_called_once_with("abc123", ".env", False)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_custom_env_file(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade", "--env", "/custom/.env"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_downgrade.assert_called_once_with("-1", "/custom/.env", False)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_env_override(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["downgrade", "--env-override"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_downgrade.assert_called_once_with("-1", ".env", True)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_all_options(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="1.0.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
db_command,
|
||||
["downgrade", "base", "--env", "prod.env", "--env-override"],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_downgrade.assert_called_once_with("base", "prod.env", True)
|
||||
|
||||
def test_does_not_delegate_when_major_version_is_non_zero(self, mocker):
|
||||
"""Major version != '0' should pass the version check and delegate."""
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="1.0.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.downgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(db_command, ["downgrade"])
|
||||
|
||||
mock_logger_error.assert_not_called()
|
||||
mock_api_downgrade.assert_called_once()
|
||||
|
||||
def test_default_revision_is_minus_one(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.downgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_downgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.downgrade": MagicMock(
|
||||
downgrade=mock_api_downgrade
|
||||
),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(db_command, ["downgrade"])
|
||||
|
||||
args, _ = mock_api_downgrade.call_args
|
||||
assert args[0] == "-1"
|
||||
234
참고/guardrails-main/tests/unit_tests/cli/db/test_upgrade.py
Normal file
234
참고/guardrails-main/tests/unit_tests/cli/db/test_upgrade.py
Normal file
@@ -0,0 +1,234 @@
|
||||
from importlib.metadata import PackageNotFoundError
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from guardrails.cli.db.db import db_command
|
||||
|
||||
|
||||
class TestUpgrade:
|
||||
def test_logs_error_when_guardrails_api_not_installed(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
side_effect=PackageNotFoundError("guardrails_api"),
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.upgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"[ERROR]: 'db upgrade' requires guardrails-api to be installed."
|
||||
)
|
||||
|
||||
def test_logs_error_when_guardrails_api_version_too_old(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.2.5",
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.upgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"[ERROR]: 'db upgrade' is only supported for guardrails-api>=0.3.0."
|
||||
" You have guardrails-api==0.2.5."
|
||||
)
|
||||
|
||||
def test_logs_error_when_minor_version_is_exactly_below_threshold(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.2.99",
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.upgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_error.assert_called_once()
|
||||
|
||||
def test_delegates_to_guardrails_api_with_defaults(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_upgrade.assert_called_once_with("head", ".env", False)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_custom_revision(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade", "abc123"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_upgrade.assert_called_once_with("abc123", ".env", False)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_custom_env_file(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade", "--env", "/custom/.env"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_upgrade.assert_called_once_with("head", "/custom/.env", False)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_env_override(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(db_command, ["upgrade", "--env-override"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_upgrade.assert_called_once_with("head", ".env", True)
|
||||
|
||||
def test_delegates_to_guardrails_api_with_all_options(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="1.0.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
db_command,
|
||||
["upgrade", "v2", "--env", "prod.env", "--env-override"],
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_api_upgrade.assert_called_once_with("v2", "prod.env", True)
|
||||
|
||||
def test_does_not_log_error_when_major_version_is_non_zero(self, mocker):
|
||||
"""Major version != '0' should pass the version check and delegate."""
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="1.0.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.upgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
mock_logger_error.assert_not_called()
|
||||
mock_api_upgrade.assert_called_once()
|
||||
|
||||
def test_default_revision_is_head(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
args, _ = mock_api_upgrade.call_args
|
||||
assert args[0] == "head"
|
||||
|
||||
def test_version_exactly_030_is_supported(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.db.upgrade.version",
|
||||
return_value="0.3.0",
|
||||
)
|
||||
mock_api_upgrade = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.db": MagicMock(),
|
||||
"guardrails_api.cli.db.upgrade": MagicMock(upgrade=mock_api_upgrade),
|
||||
},
|
||||
)
|
||||
mock_logger_error = mocker.patch("guardrails.cli.db.upgrade.logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(db_command, ["upgrade"])
|
||||
|
||||
mock_logger_error.assert_not_called()
|
||||
mock_api_upgrade.assert_called_once()
|
||||
279
참고/guardrails-main/tests/unit_tests/cli/hub/test_install.py
Normal file
279
참고/guardrails-main/tests/unit_tests/cli/hub/test_install.py
Normal file
@@ -0,0 +1,279 @@
|
||||
from unittest.mock import ANY, MagicMock, call
|
||||
from typer.testing import CliRunner
|
||||
from guardrails.cli.hub.install import hub_command
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestInstall:
|
||||
def test_exits_early_if_uri_is_not_valid(self, mocker):
|
||||
mock_logger_error = mocker.patch("guardrails.hub.install.cli_logger.error")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(hub_command, ["install", "some-invalid-uri"])
|
||||
|
||||
assert result.exit_code == 1
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"Invalid URI! The package URI must start with 'hub://'"
|
||||
)
|
||||
|
||||
def test_install_local_models__false(self, mocker):
|
||||
mock_install = mocker.patch("guardrails.hub.install.install")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command,
|
||||
["install", "hub://guardrails/test-validator", "--no-install-local-models"],
|
||||
)
|
||||
|
||||
mock_install.assert_called_once_with(
|
||||
"hub://guardrails/test-validator",
|
||||
install_local_models=False,
|
||||
quiet=ANY,
|
||||
upgrade=False,
|
||||
install_local_models_confirm=ANY,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_install_local_models__true(self, mocker):
|
||||
mock_install = mocker.patch("guardrails.hub.install.install")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command,
|
||||
["install", "hub://guardrails/test-validator", "--install-local-models"],
|
||||
)
|
||||
mock_install.assert_called_once_with(
|
||||
"hub://guardrails/test-validator",
|
||||
install_local_models=True,
|
||||
quiet=False,
|
||||
upgrade=False,
|
||||
install_local_models_confirm=ANY,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_install_local_models__none(self, mocker):
|
||||
mock_install = mocker.patch("guardrails.hub.install.install")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command,
|
||||
["install", "hub://guardrails/test-validator"],
|
||||
)
|
||||
mock_install.assert_called_once_with(
|
||||
"hub://guardrails/test-validator",
|
||||
install_local_models=None,
|
||||
quiet=False,
|
||||
upgrade=False,
|
||||
install_local_models_confirm=ANY,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_install_quiet(self, mocker):
|
||||
mock_install = mocker.patch("guardrails.hub.install.install")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command, ["install", "hub://guardrails/test-validator", "--quiet"]
|
||||
)
|
||||
|
||||
mock_install.assert_called_once_with(
|
||||
"hub://guardrails/test-validator",
|
||||
install_local_models=None,
|
||||
quiet=True,
|
||||
upgrade=False,
|
||||
install_local_models_confirm=ANY,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_install_multiple_validators(self, mocker):
|
||||
mock_install_multiple = mocker.patch("guardrails.hub.install.install_multiple")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command,
|
||||
[
|
||||
"install",
|
||||
"hub://guardrails/validator1",
|
||||
"hub://guardrails/validator2",
|
||||
"--no-install-local-models",
|
||||
],
|
||||
)
|
||||
|
||||
mock_install_multiple.assert_called_once_with(
|
||||
["hub://guardrails/validator1", "hub://guardrails/validator2"],
|
||||
install_local_models=False,
|
||||
quiet=False,
|
||||
upgrade=False,
|
||||
install_local_models_confirm=ANY,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
def test_install_multiple_validators_with_quiet(self, mocker):
|
||||
mock_install_multiple = mocker.patch("guardrails.hub.install.install_multiple")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command,
|
||||
[
|
||||
"install",
|
||||
"hub://guardrails/validator1",
|
||||
"hub://guardrails/validator2",
|
||||
"--quiet",
|
||||
],
|
||||
)
|
||||
|
||||
mock_install_multiple.assert_called_once_with(
|
||||
["hub://guardrails/validator1", "hub://guardrails/validator2"],
|
||||
install_local_models=None,
|
||||
quiet=True,
|
||||
upgrade=False,
|
||||
install_local_models_confirm=ANY,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
|
||||
class TestPipProcess:
|
||||
def test_no_package_string_format(self, mocker):
|
||||
mocker.patch("guardrails.cli.hub.utils.os.environ", return_value={})
|
||||
mock_logger_debug = mocker.patch("guardrails.cli.hub.utils.logger.debug")
|
||||
|
||||
mock_sys_executable = mocker.patch("guardrails.cli.hub.utils.sys.executable")
|
||||
|
||||
mock_subprocess_run = mocker.patch("guardrails.cli.hub.utils.subprocess.run")
|
||||
subprocess_result_mock = MagicMock()
|
||||
subprocess_result_mock.stdout = "string output"
|
||||
mock_subprocess_run.return_value = subprocess_result_mock
|
||||
|
||||
from guardrails.cli.hub.utils import pip_process
|
||||
|
||||
response = pip_process("inspect", flags=["--path=./install-here"])
|
||||
|
||||
assert mock_logger_debug.call_count == 1
|
||||
debug_calls = [
|
||||
call("running pip inspect --path=./install-here "),
|
||||
]
|
||||
mock_logger_debug.assert_has_calls(debug_calls)
|
||||
|
||||
mock_subprocess_run.assert_called_once_with(
|
||||
[mock_sys_executable, "-m", "pip", "inspect", "--path=./install-here"],
|
||||
env={},
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
assert response == "string output"
|
||||
|
||||
def test_json_format(self, mocker):
|
||||
mocker.patch("guardrails.cli.hub.utils.os.environ", return_value={})
|
||||
mock_logger_debug = mocker.patch("guardrails.cli.hub.utils.logger.debug")
|
||||
|
||||
mock_sys_executable = mocker.patch("guardrails.cli.hub.utils.sys.executable")
|
||||
|
||||
mock_subprocess_run = mocker.patch("guardrails.cli.hub.utils.subprocess.run")
|
||||
subprocess_result_mock = MagicMock()
|
||||
subprocess_result_mock.stdout = "json outout"
|
||||
|
||||
mock_subprocess_run.return_value = subprocess_result_mock
|
||||
|
||||
class MockBytesHeaderParser:
|
||||
def parsebytes(self, *args):
|
||||
return {"output": "json"}
|
||||
|
||||
mock_bytes_parser = mocker.patch("guardrails.cli.hub.utils.BytesHeaderParser")
|
||||
mock_bytes_header_parser = MockBytesHeaderParser()
|
||||
mock_bytes_parser.return_value = mock_bytes_header_parser
|
||||
|
||||
from guardrails.cli.hub.utils import pip_process
|
||||
|
||||
response = pip_process("show", "pip", format="json")
|
||||
|
||||
assert mock_logger_debug.call_count == 2
|
||||
debug_calls = [
|
||||
call("running pip show pip"),
|
||||
call(
|
||||
"JSON parse exception in decoding output from pip show pip. Falling back to accumulating the byte stream" # noqa
|
||||
),
|
||||
]
|
||||
mock_logger_debug.assert_has_calls(debug_calls)
|
||||
|
||||
mock_subprocess_run.assert_called_once_with(
|
||||
[mock_sys_executable, "-m", "pip", "show", "pip"],
|
||||
env={},
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
|
||||
assert response == {"output": "json"}
|
||||
|
||||
def test_called_process_error(self, mocker):
|
||||
mock_logger_error = mocker.patch("guardrails.cli.hub.utils.logger.error")
|
||||
mock_logger_debug = mocker.patch("guardrails.cli.hub.utils.logger.debug")
|
||||
mock_sys_executable = mocker.patch("guardrails.cli.hub.utils.sys.executable")
|
||||
mock_subprocess_check_output = mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.check_output"
|
||||
)
|
||||
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
mock_subprocess_check_output.side_effect = CalledProcessError(1, "something")
|
||||
|
||||
from guardrails.cli.hub.utils import pip_process, sys
|
||||
|
||||
sys_exit_spy = mocker.spy(sys, "exit")
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
pip_process("inspect")
|
||||
|
||||
mock_logger_debug.assert_called_once_with("running pip inspect ")
|
||||
|
||||
mock_subprocess_check_output.assert_called_once_with(
|
||||
[mock_sys_executable, "-m", "pip", "inspect"]
|
||||
)
|
||||
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"Failed to inspect \nExit code: 1\nstdout: "
|
||||
)
|
||||
|
||||
sys_exit_spy.assert_called_once_with(1)
|
||||
|
||||
def test_other_exception(self, mocker):
|
||||
error = ValueError("something went wrong")
|
||||
mock_logger_debug = mocker.patch("guardrails.cli.hub.utils.logger.debug")
|
||||
mock_logger_debug.side_effect = error
|
||||
|
||||
mock_logger_error = mocker.patch("guardrails.cli.hub.utils.logger.error")
|
||||
|
||||
from guardrails.cli.hub.utils import pip_process, sys
|
||||
|
||||
sys_exit_spy = mocker.spy(sys, "exit")
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
pip_process("inspect")
|
||||
|
||||
mock_logger_debug.assert_called_once_with("running pip inspect ")
|
||||
|
||||
mock_logger_error.assert_called_once_with(
|
||||
"An unexpected exception occurred while try to inspect !", error
|
||||
)
|
||||
|
||||
sys_exit_spy.assert_called_once_with(1)
|
||||
|
||||
def test_install_with_upgrade_flag(self, mocker):
|
||||
mock_install = mocker.patch("guardrails.hub.install.install")
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
hub_command, ["install", "--upgrade", "hub://guardrails/test-validator"]
|
||||
)
|
||||
|
||||
mock_install.assert_called_once_with(
|
||||
"hub://guardrails/test-validator",
|
||||
install_local_models=None,
|
||||
quiet=False,
|
||||
install_local_models_confirm=ANY,
|
||||
upgrade=True,
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
@@ -0,0 +1,98 @@
|
||||
import subprocess
|
||||
import sys
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from guardrails.cli.hub.utils import installer_process, PipProcessError
|
||||
|
||||
|
||||
class TestInstallerProcess:
|
||||
def test_pip_installer_builds_correct_command(self, mocker):
|
||||
mock_run = mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.run",
|
||||
return_value=MagicMock(stdout="Success", returncode=0),
|
||||
)
|
||||
|
||||
result = installer_process(
|
||||
"install", "some-package", ["--upgrade"], installer="pip"
|
||||
)
|
||||
|
||||
assert result == "Success"
|
||||
mock_run.assert_called_once()
|
||||
cmd = mock_run.call_args[0][0]
|
||||
assert cmd[0] == sys.executable
|
||||
assert cmd[1:3] == ["-m", "pip"]
|
||||
assert cmd[3] == "install"
|
||||
assert "--upgrade" in cmd
|
||||
assert "some-package" in cmd
|
||||
|
||||
def test_uv_installer_builds_correct_command(self, mocker):
|
||||
mock_run = mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.run",
|
||||
return_value=MagicMock(stdout="Success", returncode=0),
|
||||
)
|
||||
|
||||
result = installer_process(
|
||||
"install", "some-package", ["--upgrade"], installer="uv"
|
||||
)
|
||||
|
||||
assert result == "Success"
|
||||
mock_run.assert_called_once()
|
||||
cmd = mock_run.call_args[0][0]
|
||||
assert cmd[0] == "uv"
|
||||
assert cmd[1] == "pip"
|
||||
assert cmd[2] == "install"
|
||||
assert "--upgrade" in cmd
|
||||
assert "some-package" in cmd
|
||||
|
||||
def test_raises_pip_process_error_on_failure(self, mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.run",
|
||||
side_effect=subprocess.CalledProcessError(
|
||||
1, "pip", output="out", stderr="error msg"
|
||||
),
|
||||
)
|
||||
|
||||
with pytest.raises(PipProcessError) as exc_info:
|
||||
installer_process("install", "bad-package", installer="pip")
|
||||
|
||||
assert exc_info.value.action == "install"
|
||||
assert exc_info.value.package == "bad-package"
|
||||
|
||||
def test_handles_none_stderr_on_failure(self, mocker):
|
||||
exc = subprocess.CalledProcessError(1, "pip", output="out")
|
||||
exc.stderr = None
|
||||
mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.run",
|
||||
side_effect=exc,
|
||||
)
|
||||
|
||||
with pytest.raises(PipProcessError) as exc_info:
|
||||
installer_process("install", "bad-package", installer="uv")
|
||||
|
||||
assert exc_info.value.stderr == ""
|
||||
|
||||
def test_no_color_sets_env_var(self, mocker):
|
||||
mock_run = mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.run",
|
||||
return_value=MagicMock(stdout="Success"),
|
||||
)
|
||||
|
||||
installer_process("install", "some-package", installer="pip", no_color=True)
|
||||
|
||||
env = mock_run.call_args[1]["env"]
|
||||
assert env["NO_COLOR"] == "true"
|
||||
|
||||
@pytest.mark.parametrize("installer", ["uv", "pip"])
|
||||
def test_empty_package_not_appended(self, mocker, installer):
|
||||
mock_run = mocker.patch(
|
||||
"guardrails.cli.hub.utils.subprocess.run",
|
||||
return_value=MagicMock(stdout="Success"),
|
||||
)
|
||||
|
||||
installer_process("install", "", ["--upgrade"], installer=installer)
|
||||
|
||||
cmd = mock_run.call_args[0][0]
|
||||
# Package should not be in command when empty
|
||||
assert cmd[-1] == "--upgrade"
|
||||
144
참고/guardrails-main/tests/unit_tests/cli/hub/test_list.py
Normal file
144
참고/guardrails-main/tests/unit_tests/cli/hub/test_list.py
Normal file
@@ -0,0 +1,144 @@
|
||||
import json
|
||||
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from guardrails.cli.hub.hub import hub_command
|
||||
|
||||
|
||||
runner = CliRunner()
|
||||
|
||||
|
||||
def test_list_from_registry(tmp_path, mocker):
|
||||
registry_path = tmp_path / ".guardrails" / "hub_registry.json"
|
||||
registry_path.parent.mkdir(parents=True)
|
||||
registry = {
|
||||
"version": 1,
|
||||
"validators": {
|
||||
"guardrails/detect-pii": {
|
||||
"import_path": "guardrails_grhub_detect_pii",
|
||||
"exports": ["DetectPII"],
|
||||
"installed_at": "2025-01-01T00:00:00+00:00",
|
||||
"package_name": "guardrails-grhub-detect-pii",
|
||||
},
|
||||
"guardrails/regex-match": {
|
||||
"import_path": "guardrails_grhub_regex_match",
|
||||
"exports": ["RegexMatch"],
|
||||
"installed_at": "2025-01-01T00:00:00+00:00",
|
||||
"package_name": "guardrails-grhub-regex-match",
|
||||
},
|
||||
},
|
||||
}
|
||||
registry_path.write_text(json.dumps(registry))
|
||||
|
||||
mocker.patch(
|
||||
"guardrails.hub.registry.get_registry_path",
|
||||
return_value=registry_path,
|
||||
)
|
||||
|
||||
result = runner.invoke(hub_command, ["list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "Installed Validators:" in result.output
|
||||
assert "guardrails/detect-pii (DetectPII)" in result.output
|
||||
assert "guardrails/regex-match (RegexMatch)" in result.output
|
||||
|
||||
|
||||
def test_list_empty_registry(tmp_path, mocker):
|
||||
registry_path = tmp_path / ".guardrails" / "hub_registry.json"
|
||||
registry_path.parent.mkdir(parents=True)
|
||||
registry_path.write_text(json.dumps({"version": 1, "validators": {}}))
|
||||
|
||||
mocker.patch(
|
||||
"guardrails.hub.registry.get_registry_path",
|
||||
return_value=registry_path,
|
||||
)
|
||||
|
||||
result = runner.invoke(hub_command, ["list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No validators installed." in result.output
|
||||
|
||||
|
||||
def test_list_no_registry_file(tmp_path, mocker):
|
||||
registry_path = tmp_path / ".guardrails" / "hub_registry.json"
|
||||
|
||||
mocker.patch(
|
||||
"guardrails.hub.registry.get_registry_path",
|
||||
return_value=registry_path,
|
||||
)
|
||||
|
||||
result = runner.invoke(hub_command, ["list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No validators installed." in result.output
|
||||
|
||||
|
||||
def test_list_corrupt_registry(tmp_path, mocker):
|
||||
registry_path = tmp_path / ".guardrails" / "hub_registry.json"
|
||||
registry_path.parent.mkdir(parents=True)
|
||||
registry_path.write_text("not valid json{{{")
|
||||
|
||||
mocker.patch(
|
||||
"guardrails.hub.registry.get_registry_path",
|
||||
return_value=registry_path,
|
||||
)
|
||||
|
||||
result = runner.invoke(hub_command, ["list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "No validators installed." in result.output
|
||||
|
||||
|
||||
def test_list_multi_export_validator(tmp_path, mocker):
|
||||
registry_path = tmp_path / ".guardrails" / "hub_registry.json"
|
||||
registry_path.parent.mkdir(parents=True)
|
||||
registry = {
|
||||
"version": 1,
|
||||
"validators": {
|
||||
"guardrails/test-package": {
|
||||
"import_path": "guardrails_grhub_test_package",
|
||||
"exports": ["Validator", "Helper"],
|
||||
"installed_at": "2025-01-01T00:00:00+00:00",
|
||||
"package_name": "guardrails-grhub-test-package",
|
||||
},
|
||||
},
|
||||
}
|
||||
registry_path.write_text(json.dumps(registry))
|
||||
|
||||
mocker.patch(
|
||||
"guardrails.hub.registry.get_registry_path",
|
||||
return_value=registry_path,
|
||||
)
|
||||
|
||||
result = runner.invoke(hub_command, ["list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "guardrails/test-package (Validator, Helper)" in result.output
|
||||
|
||||
|
||||
def test_list_entry_without_exports_key(tmp_path, mocker):
|
||||
"""Entry missing exports key should not crash."""
|
||||
registry_path = tmp_path / ".guardrails" / "hub_registry.json"
|
||||
registry_path.parent.mkdir(parents=True)
|
||||
registry = {
|
||||
"version": 1,
|
||||
"validators": {
|
||||
"guardrails/test": {
|
||||
"import_path": "guardrails_grhub_test",
|
||||
"installed_at": "2025-01-01T00:00:00+00:00",
|
||||
"package_name": "guardrails-grhub-test",
|
||||
"exports": [],
|
||||
}
|
||||
},
|
||||
}
|
||||
registry_path.write_text(json.dumps(registry))
|
||||
|
||||
mocker.patch(
|
||||
"guardrails.hub.registry.get_registry_path",
|
||||
return_value=registry_path,
|
||||
)
|
||||
|
||||
result = runner.invoke(hub_command, ["list"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "guardrails/test ()" in result.output
|
||||
38
참고/guardrails-main/tests/unit_tests/cli/hub/test_submit.py
Normal file
38
참고/guardrails-main/tests/unit_tests/cli/hub/test_submit.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import pytest
|
||||
from typer.testing import CliRunner
|
||||
from guardrails.cli.hub import hub_command
|
||||
import os
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_post_validator_submit(mocker):
|
||||
return mocker.patch(
|
||||
"guardrails.cli.hub.submit.post_validator_submit",
|
||||
new=lambda *args, **kwargs: None,
|
||||
)
|
||||
|
||||
|
||||
def test_submit_command_success(mock_post_validator_submit):
|
||||
runner = CliRunner()
|
||||
package_name = "test_validator"
|
||||
|
||||
with runner.isolated_filesystem():
|
||||
package_path = f"{package_name}.py"
|
||||
|
||||
# Create a temporary file with the package name
|
||||
with open(package_path, "w+") as file:
|
||||
file.write("# Test validator content")
|
||||
|
||||
result = runner.invoke(hub_command, ["submit", package_name])
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
os.remove(package_path)
|
||||
|
||||
|
||||
def test_submit_command_failure(mock_post_validator_submit):
|
||||
runner = CliRunner()
|
||||
package_name = "test_validator"
|
||||
|
||||
result = runner.invoke(hub_command, ["submit", package_name])
|
||||
assert result.exit_code != 0
|
||||
@@ -0,0 +1,99 @@
|
||||
from unittest.mock import mock_open, call
|
||||
|
||||
import pytest
|
||||
|
||||
from guardrails_hub_types import Manifest
|
||||
from guardrails.cli.hub.uninstall import remove_from_hub_inits
|
||||
|
||||
manifest_mock = Manifest.from_dict(
|
||||
{
|
||||
"id": "guardrails/test_package",
|
||||
"name": "test_module",
|
||||
"author": {"name": "Author Name", "email": "author@example.com"},
|
||||
"maintainers": [{"name": "Maintainer Name", "email": "maintainer@example.com"}],
|
||||
"repository": {"url": "https://github.com/example/repo"},
|
||||
"packageName": "test_package",
|
||||
"moduleName": "test_module",
|
||||
"namespace": "guardrails",
|
||||
"description": "Test module",
|
||||
"exports": ["Validator", "Helper"],
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def test_remove_from_hub_inits(mocker):
|
||||
mock_remove_line = mocker.patch("guardrails.cli.hub.uninstall.remove_line")
|
||||
|
||||
remove_from_hub_inits(manifest_mock, "/site-packages")
|
||||
|
||||
expected_calls = [
|
||||
call(
|
||||
"/site-packages/guardrails/hub/__init__.py",
|
||||
"from guardrails_grhub_test_package import Validator, Helper",
|
||||
),
|
||||
]
|
||||
|
||||
mock_remove_line.assert_has_calls(expected_calls, any_order=True)
|
||||
|
||||
|
||||
def test_uninstall_invalid_uri(mocker):
|
||||
with pytest.raises(SystemExit):
|
||||
mock_logger_error = mocker.patch("guardrails.cli.hub.uninstall.logger.error")
|
||||
mocker.patch(
|
||||
"guardrails.cli.hub.uninstall.get_validator_manifest",
|
||||
return_value=manifest_mock,
|
||||
)
|
||||
mocker.patch(
|
||||
"guardrails.cli.hub.utils.pip_process",
|
||||
return_value={"Location": "/fake/site-packages"},
|
||||
)
|
||||
|
||||
m_open = mock_open(read_data="import something")
|
||||
mocker.patch("builtins.open", m_open)
|
||||
mocker.patch("os.path.exists", return_value=True)
|
||||
|
||||
mocker.patch("subprocess.check_call")
|
||||
from guardrails.cli.hub.uninstall import uninstall
|
||||
|
||||
uninstall("not a hub uri")
|
||||
|
||||
mock_logger_error.assert_called_once_with("Invalid URI!")
|
||||
|
||||
m_open.assert_called()
|
||||
|
||||
mock_subprocess_check_call = mocker.patch("subprocess.check_call")
|
||||
mock_subprocess_check_call.assert_not_called()
|
||||
|
||||
|
||||
def test_uninstall_valid_uri(mocker):
|
||||
mocker.patch(
|
||||
"guardrails.cli.hub.uninstall.get_validator_manifest",
|
||||
return_value=manifest_mock,
|
||||
)
|
||||
|
||||
mock_uninstall_hub_module = mocker.patch(
|
||||
"guardrails.cli.hub.uninstall.uninstall_hub_module"
|
||||
)
|
||||
mocker.patch("guardrails.cli.hub.uninstall.console")
|
||||
|
||||
mock_unregister = mocker.patch(
|
||||
"guardrails.hub.validator_package_service.ValidatorPackageService.unregister_validator"
|
||||
)
|
||||
|
||||
from guardrails.cli.hub.uninstall import uninstall
|
||||
|
||||
uninstall("hub://guardrails/test-validator")
|
||||
|
||||
mock_uninstall_hub_module.assert_called_once_with(manifest_mock)
|
||||
mock_unregister.assert_called_once_with("guardrails/test-validator")
|
||||
|
||||
|
||||
def test_uninstall_hub_module(mocker):
|
||||
mock_pip_process = mocker.patch("guardrails.cli.hub.uninstall.pip_process")
|
||||
from guardrails.cli.hub.uninstall import uninstall_hub_module
|
||||
|
||||
uninstall_hub_module(manifest_mock)
|
||||
|
||||
mock_pip_process.assert_called_once_with(
|
||||
"uninstall", "guardrails-grhub-test-package", flags=["-y"], quiet=True
|
||||
)
|
||||
@@ -0,0 +1,7 @@
|
||||
import pytest
|
||||
|
||||
|
||||
# TODO
|
||||
@pytest.mark.skip()
|
||||
def test_get_auth_token():
|
||||
assert 1 == 1
|
||||
@@ -0,0 +1,72 @@
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
import jwt
|
||||
from datetime import timezone
|
||||
|
||||
|
||||
from guardrails.classes.rc import RC
|
||||
from guardrails.cli.server.hub_client import (
|
||||
TOKEN_EXPIRED_MESSAGE,
|
||||
TOKEN_INVALID_MESSAGE,
|
||||
InvalidTokenError,
|
||||
ExpiredTokenError,
|
||||
get_jwt_token,
|
||||
)
|
||||
|
||||
|
||||
# TODO
|
||||
@pytest.mark.skip()
|
||||
def test_fetch():
|
||||
assert 1 == 1
|
||||
|
||||
|
||||
# TODO
|
||||
@pytest.mark.skip()
|
||||
def test_fetch_module_manifest():
|
||||
assert 1 == 1
|
||||
|
||||
|
||||
# TODO
|
||||
@pytest.mark.skip()
|
||||
def test_fetch_module():
|
||||
assert 1 == 1
|
||||
|
||||
|
||||
# TODO
|
||||
@pytest.mark.skip()
|
||||
def test_get_validator_manifest():
|
||||
assert 1 == 1
|
||||
|
||||
|
||||
# TODO
|
||||
@pytest.mark.skip()
|
||||
def test_get_auth():
|
||||
assert 1 == 1
|
||||
|
||||
|
||||
def test_get_jwt_token():
|
||||
# Create a JWT that expires in the future
|
||||
secret_key = "secret"
|
||||
timedelta = datetime.timedelta(seconds=1000)
|
||||
expiration = datetime.datetime.now(tz=timezone.utc) + timedelta
|
||||
valid_jwt = jwt.encode({"exp": expiration}, secret_key, algorithm="HS256")
|
||||
rc = RC.from_dict({"token": valid_jwt})
|
||||
|
||||
# Test valid token
|
||||
assert get_jwt_token(rc) == valid_jwt
|
||||
|
||||
# Test with an expired JWT
|
||||
with pytest.raises(ExpiredTokenError) as e:
|
||||
expired = datetime.datetime.now(tz=timezone.utc) - timedelta
|
||||
expired_jwt = jwt.encode({"exp": expired}, secret_key, algorithm="HS256")
|
||||
get_jwt_token(RC.from_dict({"token": expired_jwt}))
|
||||
|
||||
assert str(e.value) == TOKEN_EXPIRED_MESSAGE
|
||||
|
||||
# Test with an invalid token format
|
||||
with pytest.raises(InvalidTokenError) as e:
|
||||
invalid_jwt = "invalid"
|
||||
get_jwt_token(RC.from_dict({"token": invalid_jwt}))
|
||||
|
||||
assert str(e.value) == TOKEN_INVALID_MESSAGE
|
||||
102
참고/guardrails-main/tests/unit_tests/cli/test_configure.py
Normal file
102
참고/guardrails-main/tests/unit_tests/cli/test_configure.py
Normal file
@@ -0,0 +1,102 @@
|
||||
from unittest.mock import call, patch
|
||||
|
||||
import pytest
|
||||
from tests.unit_tests.mocks.mock_file import MockFile
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"expected_token, enable_metrics, clear_token",
|
||||
[
|
||||
("mock_token", True, False),
|
||||
("mock_token", False, False),
|
||||
("", True, True),
|
||||
("", False, True),
|
||||
],
|
||||
)
|
||||
def test_configure(mocker, runner, expected_token, enable_metrics, clear_token):
|
||||
mock_save_configuration_file = mocker.patch(
|
||||
"guardrails.cli.configure.save_configuration_file"
|
||||
)
|
||||
mock_logger_info = mocker.patch("guardrails.cli.configure.logger.info")
|
||||
mock_get_auth = mocker.patch("guardrails.cli.configure.get_auth")
|
||||
|
||||
CLI_COMMAND = ["configure"]
|
||||
CLI_COMMAND_ARGS = []
|
||||
CLI_COMMAND_INPUTS = ["mock_token", "mock_input"]
|
||||
|
||||
# Patch sys.stdin with a StringIO object
|
||||
from guardrails.cli.guardrails import guardrails
|
||||
|
||||
if enable_metrics:
|
||||
CLI_COMMAND_ARGS.append("y")
|
||||
else:
|
||||
CLI_COMMAND_ARGS.append("n")
|
||||
|
||||
if clear_token:
|
||||
CLI_COMMAND.append("--clear-token")
|
||||
|
||||
with patch("typer.prompt", side_effect=CLI_COMMAND_INPUTS):
|
||||
result = runner.invoke(
|
||||
guardrails,
|
||||
CLI_COMMAND,
|
||||
input="".join([f"{arg}\n" for arg in CLI_COMMAND_ARGS]),
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
|
||||
expected_calls = [call("Configuration saved.")]
|
||||
|
||||
if clear_token:
|
||||
expected_calls.append(call("No token provided. Skipping authentication."))
|
||||
assert mock_get_auth.call_count == 0
|
||||
else:
|
||||
expected_calls.append(call("Validating credentials..."))
|
||||
assert mock_get_auth.call_count == 1
|
||||
|
||||
assert mock_logger_info.call_count == 2
|
||||
mock_logger_info.assert_has_calls(expected_calls)
|
||||
mock_save_configuration_file.assert_called_once_with(
|
||||
expected_token, enable_metrics, True
|
||||
)
|
||||
|
||||
|
||||
def test_save_configuration_file(mocker):
|
||||
expanduser_mock = mocker.patch("guardrails.cli.configure.expanduser")
|
||||
expanduser_mock.return_value = "/Home"
|
||||
|
||||
rcexpanduser_mock = mocker.patch("guardrails.classes.rc.expanduser")
|
||||
rcexpanduser_mock.return_value = "/Home"
|
||||
|
||||
import os
|
||||
|
||||
join_spy = mocker.spy(os.path, "join")
|
||||
|
||||
mock_file = MockFile()
|
||||
mock_open = mocker.patch("guardrails.cli.configure.open")
|
||||
mock_open.return_value = mock_file
|
||||
|
||||
mock_uuid = mocker.patch("guardrails.cli.configure.uuid.uuid4")
|
||||
mock_uuid.return_value = "f49354e0-80c7-4591-81db-cc2f945e5f1e"
|
||||
|
||||
writelines_spy = mocker.spy(mock_file, "writelines")
|
||||
close_spy = mocker.spy(mock_file, "close")
|
||||
|
||||
from guardrails.cli.configure import save_configuration_file
|
||||
|
||||
save_configuration_file("token", True)
|
||||
|
||||
assert expanduser_mock.called is True
|
||||
assert rcexpanduser_mock.called is True
|
||||
join_spy.assert_called_with("/Home", ".guardrailsrc")
|
||||
assert join_spy.call_count == 2
|
||||
|
||||
assert mock_open.call_count == 1
|
||||
writelines_spy.assert_called_once_with(
|
||||
[
|
||||
f"id=f49354e0-80c7-4591-81db-cc2f945e5f1e{os.linesep}",
|
||||
f"token=token{os.linesep}",
|
||||
"enable_metrics=true\n",
|
||||
"use_remote_inferencing=true",
|
||||
]
|
||||
)
|
||||
assert close_spy.call_count == 1
|
||||
203
참고/guardrails-main/tests/unit_tests/cli/test_start.py
Normal file
203
참고/guardrails-main/tests/unit_tests/cli/test_start.py
Normal file
@@ -0,0 +1,203 @@
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from typer.testing import CliRunner
|
||||
|
||||
from guardrails.cli.guardrails import guardrails
|
||||
|
||||
|
||||
class TestStart:
|
||||
def _make_start_api_mock(self, mocker, api_version="0.3.0"):
|
||||
"""Set up the common mocks needed for start command tests."""
|
||||
mocker.patch("guardrails.cli.start.api_is_installed", return_value=True)
|
||||
mocker.patch("guardrails.cli.start.version", return_value=api_version)
|
||||
mocker.patch("guardrails.cli.start.version_warnings_if_applicable")
|
||||
mocker.patch("guardrails.cli.start.trace_if_enabled")
|
||||
|
||||
mock_start_api = MagicMock()
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.start": MagicMock(start=mock_start_api),
|
||||
},
|
||||
)
|
||||
return mock_start_api
|
||||
|
||||
def test_installs_guardrails_api_if_not_present(self, mocker):
|
||||
mocker.patch("guardrails.cli.start.api_is_installed", return_value=False)
|
||||
mock_installer = mocker.patch("guardrails.cli.start.installer_process")
|
||||
mocker.patch("guardrails.cli.start.version", return_value="0.3.0")
|
||||
mocker.patch("guardrails.cli.start.version_warnings_if_applicable")
|
||||
mocker.patch("guardrails.cli.start.trace_if_enabled")
|
||||
mocker.patch.dict(
|
||||
"sys.modules",
|
||||
{
|
||||
"guardrails_api": MagicMock(),
|
||||
"guardrails_api.cli": MagicMock(),
|
||||
"guardrails_api.cli.start": MagicMock(start=MagicMock()),
|
||||
},
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start"])
|
||||
|
||||
mock_installer.assert_called_once_with("install", "guardrails-api>=0.2.1")
|
||||
|
||||
def test_skips_install_when_guardrails_api_already_present(self, mocker):
|
||||
mock_installer = mocker.patch("guardrails.cli.start.installer_process")
|
||||
self._make_start_api_mock(mocker, "0.3.0")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start"])
|
||||
|
||||
mock_installer.assert_not_called()
|
||||
|
||||
def test_calls_start_api_without_env_override_for_old_api(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.2.9")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("", "", 8000)
|
||||
|
||||
def test_calls_start_api_with_env_override_for_new_api(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.3.0")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("", "", 8000, False)
|
||||
|
||||
def test_passes_env_override_true_to_new_api(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.3.0")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start", "--env-override"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("", "", 8000, True)
|
||||
|
||||
def test_warns_and_ignores_env_override_for_old_api(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.2.9")
|
||||
mock_logger_warning = mocker.patch("guardrails.cli.start.logger.warning")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start", "--env-override"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_warning.assert_called_once()
|
||||
warning_msg = mock_logger_warning.call_args[0][0]
|
||||
assert (
|
||||
"'env_override' is only supported for guardrails-api>=0.3.0" in warning_msg
|
||||
)
|
||||
assert "0.2.9" in warning_msg
|
||||
# env_override is NOT passed to the old API
|
||||
mock_start_api.assert_called_once_with("", "", 8000)
|
||||
|
||||
def test_no_warning_when_env_override_false_with_old_api(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.2.9")
|
||||
mock_logger_warning = mocker.patch("guardrails.cli.start.logger.warning")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_logger_warning.assert_not_called()
|
||||
mock_start_api.assert_called_once_with("", "", 8000)
|
||||
|
||||
def test_passes_custom_env_file(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.3.0")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start", "--env", "custom.env"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("custom.env", "", 8000, False)
|
||||
|
||||
def test_passes_custom_config(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.3.0")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
guardrails, ["start", "--config", "guardrails.config.py"]
|
||||
)
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("", "guardrails.config.py", 8000, False)
|
||||
|
||||
def test_passes_custom_port(self, mocker):
|
||||
mock_start_api = self._make_start_api_mock(mocker, "0.3.0")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start", "--port", "9000"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("", "", 9000, False)
|
||||
|
||||
def test_watch_mode_enables_setting(self, mocker):
|
||||
from guardrails.settings import settings
|
||||
|
||||
self._make_start_api_mock(mocker, "0.3.0")
|
||||
settings._watch_mode_enabled = False
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start", "--watch"])
|
||||
|
||||
assert settings._watch_mode_enabled is True
|
||||
# Cleanup
|
||||
settings._watch_mode_enabled = False
|
||||
|
||||
def test_watch_mode_not_set_without_flag(self, mocker):
|
||||
from guardrails.settings import settings
|
||||
|
||||
self._make_start_api_mock(mocker, "0.3.0")
|
||||
settings._watch_mode_enabled = False
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start"])
|
||||
|
||||
assert settings._watch_mode_enabled is False
|
||||
|
||||
def test_version_check_major_non_zero_uses_new_signature(self, mocker):
|
||||
"""A major version != '0' should always use the new API signature."""
|
||||
mock_start_api = self._make_start_api_mock(mocker, "1.0.0")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(guardrails, ["start", "--env-override"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
mock_start_api.assert_called_once_with("", "", 8000, True)
|
||||
|
||||
def test_calls_trace_if_enabled(self, mocker):
|
||||
self._make_start_api_mock(mocker, "0.3.0")
|
||||
mock_trace = mocker.patch("guardrails.cli.start.trace_if_enabled")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start"])
|
||||
|
||||
mock_trace.assert_called_once_with("start")
|
||||
|
||||
def test_calls_version_warnings(self, mocker):
|
||||
from guardrails.cli.hub.console import console
|
||||
|
||||
self._make_start_api_mock(mocker, "0.3.0")
|
||||
mock_version_warnings = mocker.patch(
|
||||
"guardrails.cli.start.version_warnings_if_applicable"
|
||||
)
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start"])
|
||||
|
||||
mock_version_warnings.assert_called_once_with(console)
|
||||
|
||||
def test_logs_starting_server_info(self, mocker):
|
||||
self._make_start_api_mock(mocker, "0.3.0")
|
||||
mock_logger_info = mocker.patch("guardrails.cli.start.logger.info")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(guardrails, ["start"])
|
||||
|
||||
mock_logger_info.assert_any_call("[INFO]: Starting Guardrails server")
|
||||
63
참고/guardrails-main/tests/unit_tests/cli/test_validate.py
Normal file
63
참고/guardrails-main/tests/unit_tests/cli/test_validate.py
Normal file
@@ -0,0 +1,63 @@
|
||||
from tests.unit_tests.mocks.mock_file import MockFile
|
||||
|
||||
|
||||
def test_validate(mocker):
|
||||
mock_validate_llm_output = mocker.patch(
|
||||
"guardrails.cli.validate.validate_llm_output"
|
||||
)
|
||||
mock_validate_llm_output.return_value = "validated output"
|
||||
|
||||
mock_file = MockFile()
|
||||
mock_open = mocker.patch("guardrails.cli.validate.open")
|
||||
mock_open.return_value = mock_file
|
||||
write_spy = mocker.spy(mock_file, "write")
|
||||
|
||||
mock_json_dump = mocker.patch("json.dump")
|
||||
|
||||
import builtins
|
||||
|
||||
print_spy = mocker.spy(builtins, "print")
|
||||
|
||||
from guardrails.cli.validate import validate
|
||||
|
||||
response = validate("my_spec.rail", "output", out="somewhere")
|
||||
|
||||
mock_validate_llm_output.assert_called_once_with("my_spec.rail", "output")
|
||||
|
||||
print_spy.assert_called_once_with("validated output")
|
||||
mock_open.assert_called_once_with("somewhere", "w")
|
||||
mock_json_dump.assert_called_once_with("validated output", mock_file)
|
||||
write_spy.assert_called_once_with("\n")
|
||||
|
||||
assert response == "validated output"
|
||||
|
||||
|
||||
def test_validate_llm_output(mocker):
|
||||
class MockGuard:
|
||||
def parse(self, *args):
|
||||
pass
|
||||
|
||||
from guardrails import Guard
|
||||
from guardrails.classes import ValidationOutcome
|
||||
|
||||
mock_guard = MockGuard()
|
||||
for_rail_mock = mocker.patch.object(Guard, "for_rail")
|
||||
for_rail_mock.return_value = mock_guard
|
||||
|
||||
parse_mock = mocker.patch.object(mock_guard, "parse")
|
||||
parse_mock.return_value = ValidationOutcome(
|
||||
call_id="mock-call",
|
||||
raw_llm_output="output",
|
||||
validated_output="validated output",
|
||||
validation_passed=True,
|
||||
)
|
||||
|
||||
from guardrails.cli.validate import validate_llm_output
|
||||
|
||||
rail = "my_spec.rail"
|
||||
response = validate_llm_output(rail, "output")
|
||||
|
||||
for_rail_mock.assert_called_once_with(rail)
|
||||
parse_mock.assert_called_once_with("output")
|
||||
|
||||
assert response == "validated output"
|
||||
Reference in New Issue
Block a user