Files
2026-07-13 13:22:34 +08:00

204 lines
6.5 KiB
Python

from unittest import mock
from click.testing import CliRunner
from mlflow.cli import cli
def test_list_commands_cli():
mock_commands = [
{
"key": "genai/analyze_experiment",
"namespace": "genai",
"description": "Analyzes an MLflow experiment",
},
{
"key": "ml/train",
"namespace": "ml",
"description": "Training helper",
},
]
with mock.patch("mlflow.ai_commands.list_commands", return_value=mock_commands):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "list"])
assert result.exit_code == 0
assert "genai/analyze_experiment: Analyzes an MLflow experiment" in result.output
assert "ml/train: Training helper" in result.output
def test_list_commands_with_namespace_cli():
mock_commands = [
{
"key": "genai/analyze_experiment",
"namespace": "genai",
"description": "Analyzes an MLflow experiment",
},
]
with mock.patch(
"mlflow.cli.ai_commands.list_commands", return_value=mock_commands
) as mock_list:
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "list", "--namespace", "genai"])
assert result.exit_code == 0
mock_list.assert_called_once_with("genai")
assert "genai/analyze_experiment" in result.output
def test_list_commands_empty_cli():
with mock.patch("mlflow.ai_commands.list_commands", return_value=[]):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "list"])
assert result.exit_code == 0
assert "No AI commands found" in result.output
def test_list_commands_empty_namespace_cli():
with mock.patch("mlflow.ai_commands.list_commands", return_value=[]):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "list", "--namespace", "unknown"])
assert result.exit_code == 0
assert "No AI commands found in namespace 'unknown'" in result.output
def test_get_command_cli():
mock_content = """---
namespace: genai
description: Test command
---
Hello! This is test content."""
with mock.patch("mlflow.ai_commands.get_command", return_value=mock_content):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "get", "genai/analyze_experiment"])
assert result.exit_code == 0
assert mock_content == result.output.rstrip("\n")
def test_get_invalid_command_cli():
with mock.patch(
"mlflow.cli.ai_commands.get_command",
side_effect=FileNotFoundError("Command 'invalid/cmd' not found"),
):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "get", "invalid/cmd"])
assert result.exit_code != 0
assert "Error: Command 'invalid/cmd' not found" in result.output
def test_ai_commands_help():
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "--help"])
assert result.exit_code == 0
assert "Manage MLflow AI commands for LLMs" in result.output
assert "list" in result.output
assert "get" in result.output
assert "run" in result.output
def test_get_command_help():
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "get", "--help"])
assert result.exit_code == 0
assert "Get a specific AI command by key" in result.output
assert "KEY" in result.output
def test_list_command_help():
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "list", "--help"])
assert result.exit_code == 0
assert "List all available AI commands" in result.output
assert "--namespace" in result.output
def test_run_command_cli():
mock_content = """---
namespace: genai
description: Test command
---
# Test Command
This is test content."""
with mock.patch("mlflow.ai_commands.get_command", return_value=mock_content):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "run", "genai/analyze_experiment"])
assert result.exit_code == 0
assert "The user has run an MLflow AI command via CLI" in result.output
assert "Start executing the workflow immediately without any preamble" in result.output
assert "# Test Command" in result.output
assert "This is test content." in result.output
# Should not have frontmatter
assert "namespace: genai" not in result.output
assert "description: Test command" not in result.output
assert "---" not in result.output
def test_run_invalid_command_cli():
with mock.patch(
"mlflow.ai_commands.get_command",
side_effect=FileNotFoundError("Command 'invalid/cmd' not found"),
):
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "run", "invalid/cmd"])
assert result.exit_code != 0
assert "Error: Command 'invalid/cmd' not found" in result.output
def test_run_command_help():
runner = CliRunner()
result = runner.invoke(cli, ["ai-commands", "run", "--help"])
assert result.exit_code == 0
assert "Get a command formatted for execution by an AI assistant" in result.output
assert "KEY" in result.output
def test_actual_command_exists():
runner = CliRunner()
# Test list includes our command
result = runner.invoke(cli, ["ai-commands", "list"])
assert result.exit_code == 0
assert "genai/analyze_experiment" in result.output
# Test we can get the command
result = runner.invoke(cli, ["ai-commands", "get", "genai/analyze_experiment"])
assert result.exit_code == 0
assert "# Analyze Experiment" in result.output
assert "Analyzes traces in an MLflow experiment" in result.output
# Test we can run the command
result = runner.invoke(cli, ["ai-commands", "run", "genai/analyze_experiment"])
assert result.exit_code == 0
assert "The user has run an MLflow AI command via CLI" in result.output
assert "Start executing the workflow immediately without any preamble" in result.output
assert "# Analyze Experiment" in result.output
# Should not have frontmatter
assert "namespace: genai" not in result.output
assert "---" not in result.output
# Test filtering by namespace
result = runner.invoke(cli, ["ai-commands", "list", "--namespace", "genai"])
assert result.exit_code == 0
assert "genai/analyze_experiment" in result.output
# Test filtering by wrong namespace excludes it
result = runner.invoke(cli, ["ai-commands", "list", "--namespace", "ml"])
assert result.exit_code == 0
assert "genai/analyze_experiment" not in result.output