185 lines
5.6 KiB
Python
185 lines
5.6 KiB
Python
import json
|
|
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
import mlflow
|
|
from mlflow.cli.datasets import commands
|
|
from mlflow.genai.datasets import create_dataset
|
|
|
|
|
|
@pytest.fixture
|
|
def runner():
|
|
return CliRunner(catch_exceptions=False)
|
|
|
|
|
|
@pytest.fixture
|
|
def experiment():
|
|
exp_id = mlflow.create_experiment("test_datasets_cli")
|
|
yield exp_id
|
|
mlflow.delete_experiment(exp_id)
|
|
|
|
|
|
@pytest.fixture
|
|
def dataset_a(experiment):
|
|
return create_dataset(
|
|
name="dataset_a",
|
|
experiment_id=experiment,
|
|
tags={"env": "production"},
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def dataset_b(experiment):
|
|
return create_dataset(
|
|
name="dataset_b",
|
|
experiment_id=experiment,
|
|
tags={"env": "staging"},
|
|
)
|
|
|
|
|
|
def test_commands_group_exists():
|
|
assert commands.name == "datasets"
|
|
assert commands.help is not None
|
|
|
|
|
|
def test_list_command_params():
|
|
list_cmd = next((cmd for cmd in commands.commands.values() if cmd.name == "list"), None)
|
|
assert list_cmd is not None
|
|
param_names = {p.name for p in list_cmd.params}
|
|
expected_params = {
|
|
"experiment_id",
|
|
"filter_string",
|
|
"max_results",
|
|
"order_by",
|
|
"page_token",
|
|
"output",
|
|
}
|
|
assert param_names == expected_params
|
|
|
|
|
|
def test_list_datasets_table_output(runner: CliRunner, experiment: str, dataset_a):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment])
|
|
|
|
assert result.exit_code == 0
|
|
assert dataset_a.dataset_id in result.output
|
|
assert "dataset_a" in result.output
|
|
|
|
|
|
def test_list_datasets_json_output(runner: CliRunner, experiment: str, dataset_a):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment, "--output", "json"])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
expected = {
|
|
"datasets": [
|
|
{
|
|
"dataset_id": dataset_a.dataset_id,
|
|
"name": "dataset_a",
|
|
"digest": dataset_a.digest,
|
|
"created_time": dataset_a.created_time,
|
|
"last_update_time": dataset_a.last_update_time,
|
|
"created_by": dataset_a.created_by,
|
|
"last_updated_by": dataset_a.last_updated_by,
|
|
"tags": dataset_a.tags,
|
|
}
|
|
],
|
|
"next_page_token": None,
|
|
}
|
|
assert json.loads(result.output) == expected
|
|
|
|
|
|
def test_list_datasets_empty_results(runner: CliRunner, experiment: str):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment])
|
|
|
|
assert result.exit_code == 0
|
|
|
|
|
|
def test_list_datasets_json_empty_results(runner: CliRunner, experiment: str):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment, "--output", "json"])
|
|
|
|
assert result.exit_code == 0
|
|
output_json = json.loads(result.output)
|
|
assert output_json == {"datasets": [], "next_page_token": None}
|
|
|
|
|
|
def test_list_datasets_with_experiment_id_env_var(runner: CliRunner, experiment: str, dataset_a):
|
|
result = runner.invoke(commands, ["list"], env={"MLFLOW_EXPERIMENT_ID": experiment})
|
|
|
|
assert result.exit_code == 0
|
|
assert dataset_a.dataset_id in result.output
|
|
|
|
|
|
def test_list_datasets_missing_experiment_id(runner: CliRunner):
|
|
result = runner.invoke(commands, ["list"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "Missing option '--experiment-id' / '-x'" in result.output
|
|
|
|
|
|
def test_list_datasets_invalid_output_format(runner: CliRunner, experiment: str):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment, "--output", "invalid"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "'invalid' is not one of 'table', 'json'" in result.output
|
|
|
|
|
|
def test_list_datasets_with_filter_string(runner: CliRunner, experiment: str, dataset_a, dataset_b):
|
|
result = runner.invoke(
|
|
commands,
|
|
["list", "--experiment-id", experiment, "--filter-string", "name = 'dataset_a'"],
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
assert "dataset_a" in result.output
|
|
assert "dataset_b" not in result.output
|
|
|
|
|
|
def test_list_datasets_with_max_results(runner: CliRunner, experiment: str, dataset_a, dataset_b):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment, "--max-results", "1"])
|
|
|
|
assert result.exit_code == 0
|
|
output_lines = [line for line in result.output.split("\n") if "dataset_" in line]
|
|
assert len(output_lines) == 1
|
|
|
|
|
|
def test_list_datasets_with_order_by(runner: CliRunner, experiment: str, dataset_a, dataset_b):
|
|
result = runner.invoke(
|
|
commands, ["list", "--experiment-id", experiment, "--order-by", "name ASC"]
|
|
)
|
|
|
|
assert result.exit_code == 0
|
|
a_pos = result.output.find("dataset_a")
|
|
b_pos = result.output.find("dataset_b")
|
|
assert a_pos < b_pos
|
|
|
|
|
|
def test_list_datasets_short_option_x(runner: CliRunner, experiment: str, dataset_a):
|
|
result = runner.invoke(commands, ["list", "-x", experiment])
|
|
|
|
assert result.exit_code == 0
|
|
assert dataset_a.dataset_id in result.output
|
|
|
|
|
|
def test_list_datasets_multiple_datasets(runner: CliRunner, experiment: str, dataset_a, dataset_b):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment])
|
|
|
|
assert result.exit_code == 0
|
|
assert dataset_a.dataset_id in result.output
|
|
assert "dataset_a" in result.output
|
|
assert dataset_b.dataset_id in result.output
|
|
assert "dataset_b" in result.output
|
|
|
|
|
|
def test_list_datasets_json_multiple_datasets(
|
|
runner: CliRunner, experiment: str, dataset_a, dataset_b
|
|
):
|
|
result = runner.invoke(commands, ["list", "--experiment-id", experiment, "--output", "json"])
|
|
|
|
assert result.exit_code == 0
|
|
output_json = json.loads(result.output)
|
|
assert len(output_json["datasets"]) == 2
|
|
|
|
names = {d["name"] for d in output_json["datasets"]}
|
|
assert names == {"dataset_a", "dataset_b"}
|