Unverified Commit 4a55fa99 authored by KrishnanPrash's avatar KrishnanPrash Committed by GitHub
Browse files

ci: Pass CLI Arguments to workers with a pytest fixture (#3605)


Signed-off-by: default avatarKrishnan Prashanth <kprashanth@nvidia.com>
parent fa1d6517
...@@ -8,6 +8,9 @@ frameworks are not installed in the current container. ...@@ -8,6 +8,9 @@ frameworks are not installed in the current container.
""" """
import importlib.util import importlib.util
import sys
import pytest
def pytest_ignore_collect(collection_path, config): def pytest_ignore_collect(collection_path, config):
...@@ -30,3 +33,45 @@ def pytest_ignore_collect(collection_path, config): ...@@ -30,3 +33,45 @@ def pytest_ignore_collect(collection_path, config):
return True # Module not available, skip this file return True # Module not available, skip this file
return None # Not a backend test or module available return None # Not a backend test or module available
def make_cli_args_fixture(module_name: str):
"""Create a pytest fixture for mocking CLI arguments for a backend.
The returned fixture supports two call styles:
1. Explicit:
mock_vllm_cli("--model", "gpt-2", "--custom-jinja-template", "path.jinja")
2. Kwargs (auto-converts underscores to hyphens):
mock_vllm_cli(model="gpt-2", custom_jinja_template="path.jinja")
Both produce: ["dynamo.vllm", "--model", "gpt-2", "--custom-jinja-template", "path.jinja"]
Args:
module_name: Module identifier for argv[0] (e.g., "dynamo.vllm")
Returns:
Pytest fixture that mocks sys.argv via monkeypatch
"""
@pytest.fixture
def mock_cli_args(monkeypatch):
"""Mock sys.argv with CLI arguments (explicit or kwargs style)."""
def set_args(*args, **kwargs):
if args:
# Explicit style: pass argv elements directly
argv = [module_name, *args]
else:
# Kwargs style: convert python arg to CLI arg
argv = [module_name]
for param_name, param_value in kwargs.items():
cli_flag = f"--{param_name.replace('_', '-')}"
argv.extend([cli_flag, str(param_value)])
monkeypatch.setattr(sys, "argv", argv)
return set_args
return mock_cli_args
...@@ -10,6 +10,7 @@ from pathlib import Path ...@@ -10,6 +10,7 @@ from pathlib import Path
import pytest import pytest
from dynamo.sglang.args import parse_args from dynamo.sglang.args import parse_args
from tests.unit.conftest import make_cli_args_fixture
# Get path relative to this test file # Get path relative to this test file
TEST_DIR = Path(__file__).parent.parent TEST_DIR = Path(__file__).parent.parent
...@@ -23,19 +24,16 @@ pytestmark = [ ...@@ -23,19 +24,16 @@ pytestmark = [
] ]
def test_custom_jinja_template_invalid_path(monkeypatch): # Create SGLang-specific CLI args fixture
# This will use monkeypatch to write to argv
mock_sglang_cli = make_cli_args_fixture("dynamo.sglang")
def test_custom_jinja_template_invalid_path(mock_sglang_cli):
"""Test that invalid file path raises FileNotFoundError.""" """Test that invalid file path raises FileNotFoundError."""
invalid_path = "/nonexistent/path/to/template.jinja" invalid_path = "/nonexistent/path/to/template.jinja"
monkeypatch.setattr( mock_sglang_cli(
sys, "--model", "Qwen/Qwen3-0.6B", "--custom-jinja-template", invalid_path
"argv",
[
"dynamo.sglang",
"--model-path",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
invalid_path,
],
) )
with pytest.raises( with pytest.raises(
...@@ -45,19 +43,9 @@ def test_custom_jinja_template_invalid_path(monkeypatch): ...@@ -45,19 +43,9 @@ def test_custom_jinja_template_invalid_path(monkeypatch):
parse_args(sys.argv[1:]) parse_args(sys.argv[1:])
def test_custom_jinja_template_valid_path(monkeypatch): def test_custom_jinja_template_valid_path(mock_sglang_cli):
"""Test that valid absolute path is stored correctly.""" """Test that valid absolute path is stored correctly."""
monkeypatch.setattr( mock_sglang_cli(model="Qwen/Qwen3-0.6B", custom_jinja_template=JINJA_TEMPLATE_PATH)
sys,
"argv",
[
"dynamo.sglang",
"--model-path",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
JINJA_TEMPLATE_PATH,
],
)
config = parse_args(sys.argv[1:]) config = parse_args(sys.argv[1:])
...@@ -67,23 +55,13 @@ def test_custom_jinja_template_valid_path(monkeypatch): ...@@ -67,23 +55,13 @@ def test_custom_jinja_template_valid_path(monkeypatch):
) )
def test_custom_jinja_template_env_var_expansion(monkeypatch): def test_custom_jinja_template_env_var_expansion(monkeypatch, mock_sglang_cli):
"""Test that environment variables in paths are expanded by Python code.""" """Test that environment variables in paths are expanded by Python code."""
jinja_dir = str(TEST_DIR / "serve" / "fixtures") jinja_dir = str(TEST_DIR / "serve" / "fixtures")
monkeypatch.setenv("JINJA_DIR", jinja_dir) monkeypatch.setenv("JINJA_DIR", jinja_dir)
cli_path = "$JINJA_DIR/custom_template.jinja" cli_path = "$JINJA_DIR/custom_template.jinja"
monkeypatch.setattr( mock_sglang_cli(model="Qwen/Qwen3-0.6B", custom_jinja_template=cli_path)
sys,
"argv",
[
"dynamo.sglang",
"--model-path",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
cli_path,
],
)
config = parse_args(sys.argv[1:]) config = parse_args(sys.argv[1:])
......
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
"""Unit tests for TRTLLM backend components.""" """Unit tests for TRTLLM backend components."""
import re import re
import sys
from pathlib import Path from pathlib import Path
import pytest import pytest
from dynamo.trtllm.utils.trtllm_utils import cmd_line_args from dynamo.trtllm.utils.trtllm_utils import cmd_line_args
from tests.unit.conftest import make_cli_args_fixture
# Get path relative to this test file # Get path relative to this test file
TEST_DIR = Path(__file__).parent.parent TEST_DIR = Path(__file__).parent.parent
...@@ -23,42 +23,28 @@ pytestmark = [ ...@@ -23,42 +23,28 @@ pytestmark = [
] ]
def test_custom_jinja_template_invalid_path(monkeypatch): # Create TRTLLM-specific CLI args fixture
# This will use monkeypatch to write to argv
mock_trtllm_cli = make_cli_args_fixture("dynamo.trtllm")
def test_custom_jinja_template_invalid_path(mock_trtllm_cli):
"""Test that invalid file path raises FileNotFoundError.""" """Test that invalid file path raises FileNotFoundError."""
invalid_path = "/nonexistent/path/to/template.jinja" invalid_path = "/nonexistent/path/to/template.jinja"
monkeypatch.setattr( mock_trtllm_cli(
sys, "--model", "Qwen/Qwen3-0.6B", "--custom-jinja-template", invalid_path
"argv",
[
"dynamo.trtllm",
"--model-path",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
invalid_path,
],
) )
with pytest.raises( with pytest.raises(
FileNotFoundError, FileNotFoundError,
match=re.escape(f"Custom Jinja template file not found: {invalid_path}"), match=re.escape(f"Custom Jinja template file not found: {invalid_path}"),
): ):
cmd_line_args() cmd_line_args() # This will read in from argv
def test_custom_jinja_template_valid_path(monkeypatch): def test_custom_jinja_template_valid_path(mock_trtllm_cli):
"""Test that valid absolute path is stored correctly.""" """Test that valid absolute path is stored correctly."""
monkeypatch.setattr( mock_trtllm_cli(model="Qwen/Qwen3-0.6B", custom_jinja_template=JINJA_TEMPLATE_PATH)
sys,
"argv",
[
"dynamo.trtllm",
"--model-path",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
JINJA_TEMPLATE_PATH,
],
)
config = cmd_line_args() config = cmd_line_args()
assert config.custom_jinja_template == JINJA_TEMPLATE_PATH, ( assert config.custom_jinja_template == JINJA_TEMPLATE_PATH, (
...@@ -67,23 +53,13 @@ def test_custom_jinja_template_valid_path(monkeypatch): ...@@ -67,23 +53,13 @@ def test_custom_jinja_template_valid_path(monkeypatch):
) )
def test_custom_jinja_template_env_var_expansion(monkeypatch): def test_custom_jinja_template_env_var_expansion(monkeypatch, mock_trtllm_cli):
"""Test that environment variables in paths are expanded by Python code.""" """Test that environment variables in paths are expanded by Python code."""
jinja_dir = str(TEST_DIR / "serve" / "fixtures") jinja_dir = str(TEST_DIR / "serve" / "fixtures")
monkeypatch.setenv("JINJA_DIR", jinja_dir) monkeypatch.setenv("JINJA_DIR", jinja_dir)
cli_path = "$JINJA_DIR/custom_template.jinja" cli_path = "$JINJA_DIR/custom_template.jinja"
monkeypatch.setattr( mock_trtllm_cli(model="Qwen/Qwen3-0.6B", custom_jinja_template=cli_path)
sys,
"argv",
[
"dynamo.trtllm",
"--model-path",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
cli_path,
],
)
config = cmd_line_args() config = cmd_line_args()
......
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
"""Unit tests for vLLM backend components.""" """Unit tests for vLLM backend components."""
import re import re
import sys
from pathlib import Path from pathlib import Path
import pytest import pytest
from dynamo.vllm.args import parse_args from dynamo.vllm.args import parse_args
from tests.unit.conftest import make_cli_args_fixture
# Get path relative to this test file # Get path relative to this test file
TEST_DIR = Path(__file__).parent.parent TEST_DIR = Path(__file__).parent.parent
...@@ -23,20 +23,16 @@ pytestmark = [ ...@@ -23,20 +23,16 @@ pytestmark = [
] ]
def test_custom_jinja_template_invalid_path(monkeypatch): # Create vLLM-specific CLI args fixture
# This will use monkeypatch to write to argv
mock_vllm_cli = make_cli_args_fixture("dynamo.vllm")
def test_custom_jinja_template_invalid_path(mock_vllm_cli):
"""Test that invalid file path raises FileNotFoundError.""" """Test that invalid file path raises FileNotFoundError."""
invalid_path = "/nonexistent/path/to/template.jinja" invalid_path = "/nonexistent/path/to/template.jinja"
monkeypatch.setattr(
sys, mock_vllm_cli("--model", "Qwen/Qwen3-0.6B", "--custom-jinja-template", invalid_path)
"argv",
[
"dynamo.vllm",
"--model",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
invalid_path,
],
)
with pytest.raises( with pytest.raises(
FileNotFoundError, FileNotFoundError,
...@@ -45,19 +41,9 @@ def test_custom_jinja_template_invalid_path(monkeypatch): ...@@ -45,19 +41,9 @@ def test_custom_jinja_template_invalid_path(monkeypatch):
parse_args() parse_args()
def test_custom_jinja_template_valid_path(monkeypatch): def test_custom_jinja_template_valid_path(mock_vllm_cli):
"""Test that valid absolute path is stored correctly.""" """Test that valid absolute path is stored correctly."""
monkeypatch.setattr( mock_vllm_cli(model="Qwen/Qwen3-0.6B", custom_jinja_template=JINJA_TEMPLATE_PATH)
sys,
"argv",
[
"dynamo.vllm",
"--model",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
JINJA_TEMPLATE_PATH,
],
)
config = parse_args() config = parse_args()
...@@ -67,23 +53,13 @@ def test_custom_jinja_template_valid_path(monkeypatch): ...@@ -67,23 +53,13 @@ def test_custom_jinja_template_valid_path(monkeypatch):
) )
def test_custom_jinja_template_env_var_expansion(monkeypatch): def test_custom_jinja_template_env_var_expansion(monkeypatch, mock_vllm_cli):
"""Test that environment variables in paths are expanded by Python code.""" """Test that environment variables in paths are expanded by Python code."""
jinja_dir = str(TEST_DIR / "serve" / "fixtures") jinja_dir = str(TEST_DIR / "serve" / "fixtures")
monkeypatch.setenv("JINJA_DIR", jinja_dir) monkeypatch.setenv("JINJA_DIR", jinja_dir)
cli_path = "$JINJA_DIR/custom_template.jinja" cli_path = "$JINJA_DIR/custom_template.jinja"
monkeypatch.setattr( mock_vllm_cli(model="Qwen/Qwen3-0.6B", custom_jinja_template=cli_path)
sys,
"argv",
[
"dynamo.vllm",
"--model",
"Qwen/Qwen3-0.6B",
"--custom-jinja-template",
cli_path,
],
)
config = parse_args() config = parse_args()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment