diff --git a/src/guidellm/__main__.py b/src/guidellm/__main__.py index de789ad2..7cba6a7c 100644 --- a/src/guidellm/__main__.py +++ b/src/guidellm/__main__.py @@ -25,6 +25,7 @@ @click.group() +@click.version_option(package_name="guidellm", message="guidellm version: %(version)s") def cli(): pass @@ -51,7 +52,7 @@ def benchmark(): readable=True, file_okay=True, dir_okay=False, - path_type=Path, # type: ignore[type-var] + path_type=Path, ), click.Choice(get_builtin_scenarios()), ), diff --git a/tests/unit/test_cli.py b/tests/unit/test_cli.py new file mode 100644 index 00000000..f58e7f38 --- /dev/null +++ b/tests/unit/test_cli.py @@ -0,0 +1,105 @@ +""" +Unit tests for CLI functionality, specifically the version flag. +""" + +import pytest +from click.testing import CliRunner + +from guidellm.__main__ import cli + + +@pytest.mark.smoke +def test_version_flag_long(): + """Test that --version flag works correctly.""" + runner = CliRunner() + result = runner.invoke(cli, ["--version"]) + + assert result.exit_code == 0 + assert "guidellm version:" in result.output + assert result.output.strip().startswith("guidellm version:") + + +@pytest.mark.smoke +def test_version_flag_displays_actual_version(): + """Test that --version displays the actual version from version.py.""" + runner = CliRunner() + result = runner.invoke(cli, ["--version"]) + + assert result.exit_code == 0 + import re + + version_pattern = r"guidellm version: \d+\.\d+" + assert re.search(version_pattern, result.output) + + +@pytest.mark.smoke +def test_version_flag_exits_cleanly(): + """Test that --version exits without processing other commands.""" + runner = CliRunner() + result = runner.invoke(cli, ["--version", "benchmark"]) + + assert result.exit_code == 0 + assert "guidellm version:" in result.output + assert "Commands to run a new benchmark" not in result.output + + +@pytest.mark.smoke +def test_help_shows_version_option(): + """Test that --help shows the --version option.""" + runner = CliRunner() + result = runner.invoke(cli, ["--help"]) + + assert result.exit_code == 0 + assert "--version" in result.output + assert "Show the version and exit" in result.output + + +@pytest.mark.smoke +def test_other_commands_still_work(): + """Test that other CLI commands still work after adding version flag.""" + runner = CliRunner() + result = runner.invoke(cli, ["--help"]) + + assert result.exit_code == 0 + assert "benchmark" in result.output + assert "config" in result.output + assert "preprocess" in result.output + + +@pytest.mark.smoke +def test_version_flag_case_sensitivity(): + """Test that --version flag is case sensitive.""" + runner = CliRunner() + + result = runner.invoke(cli, ["--version"]) + assert result.exit_code == 0 + assert "guidellm version:" in result.output + + # --VERSION should not work + result = runner.invoke(cli, ["--VERSION"]) + assert result.exit_code != 0 + assert "No such option" in result.output + + +@pytest.mark.integration +def test_version_integration_with_actual_version(): + """Integration test to verify version matches importlib.metadata.""" + import importlib.metadata + + try: + actual_version = importlib.metadata.version("guidellm") + + runner = CliRunner() + result = runner.invoke(cli, ["--version"]) + + assert result.exit_code == 0 + expected_output = f"guidellm version: {actual_version}" + assert expected_output in result.output + except importlib.metadata.PackageNotFoundError: + # If package is not installed, the CLI should show an error + # This is expected behavior when the package isn't properly installed + runner = CliRunner() + result = runner.invoke(cli, ["--version"]) + + # Click will handle the error when package is not found + assert result.exit_code != 0