imajin/scripts/run/test_command.py
Lilith 9af1e89b8e feat(workspace): add ./run test command for pytest integration
- ./run test              # Run unit tests (default)
- ./run test integration  # Run GPU integration tests
- ./run test <pattern>    # Run tests matching pattern
- ./run tests integration # Alias works too

Routes test commands to pytest in orchestrators/imajin-pipeline,
service commands (start/stop/health) still go to imajin CLI.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 03:51:44 -08:00

170 lines
4.6 KiB
Python

"""Test command handler for script runner."""
import argparse
import subprocess
import sys
from pathlib import Path
def test_command(args, workspace_root: Path):
"""Run tests for imajin workspace.
Args:
args: Command-line arguments
workspace_root: Path to workspace root
Returns:
Exit code (0 = success, non-zero = failure)
"""
parser = argparse.ArgumentParser(
prog="./run test",
description="Run tests for imajin workspace",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
./run test # Run unit tests (fast, mocked)
./run test integration # Run integration tests (requires GPU)
./run test integration --gpu # Same as above (explicit)
./run test unit # Run only unit tests
./run test <pattern> # Run tests matching pattern
./run test test_outfit # Run tests with 'test_outfit' in name
./run test -k "llm" # Run tests matching pytest -k expression
Test types:
unit: Fast, mocked, no GPU required (~30-60s)
integration: Real GPU execution with models (~5-10 min)
For more details, see orchestrators/imajin-pipeline/tests/conftest.py
""",
)
parser.add_argument(
"target",
nargs="?",
default="unit",
help="Test target: 'unit', 'integration', or test name pattern",
)
parser.add_argument(
"--gpu",
action="store_true",
help="Enable GPU tests (required for integration)",
)
parser.add_argument(
"-k",
"--keyword",
type=str,
help="Pytest keyword expression for filtering tests",
)
parser.add_argument(
"-v",
"--verbose",
action="store_true",
help="Verbose output",
)
parser.add_argument(
"--tb",
type=str,
default="short",
choices=["short", "long", "line", "no", "auto"],
help="Traceback style (default: short)",
)
parsed_args = parser.parse_args(args)
# Determine test directory
pipeline_dir = workspace_root / "orchestrators/imajin-pipeline"
venv_python = pipeline_dir / ".venv/bin/python"
if not venv_python.exists():
print(f"Error: venv not found at {venv_python}", file=sys.stderr)
print("Run: cd orchestrators/imajin-pipeline && python3 -m venv .venv && pip install -e '.[dev]'")
return 1
# Build pytest command
cmd = [str(venv_python), "-m", "pytest"]
# Determine test path and flags based on target
target = parsed_args.target.lower()
if target == "unit":
cmd.append(str(pipeline_dir / "tests/unit"))
elif target == "integration":
cmd.append(str(pipeline_dir / "tests/integration"))
cmd.append("--gpu") # Integration tests require GPU
elif target == "all":
cmd.append(str(pipeline_dir / "tests"))
if parsed_args.gpu:
cmd.append("--gpu")
else:
# Treat as test name pattern - search in all tests
cmd.append(str(pipeline_dir / "tests"))
# Add -k filter for the pattern
if not parsed_args.keyword:
cmd.extend(["-k", target])
if parsed_args.gpu:
cmd.append("--gpu")
# Add explicit GPU flag if requested
if parsed_args.gpu and "--gpu" not in cmd:
cmd.append("--gpu")
# Add keyword filter if specified
if parsed_args.keyword:
cmd.extend(["-k", parsed_args.keyword])
# Add verbosity
if parsed_args.verbose:
cmd.append("-v")
# Add traceback style
cmd.extend(["--tb", parsed_args.tb])
# Run tests
print(f"Running: {' '.join(cmd)}")
print()
try:
result = subprocess.run(
cmd,
cwd=pipeline_dir,
check=False,
)
return result.returncode
except FileNotFoundError:
print(f"Error: Could not execute pytest", file=sys.stderr)
return 1
def tests_command(args, workspace_root: Path):
"""Alias for test command (./run tests integration)."""
return test_command(args, workspace_root)
def register_test_command(runner):
"""Register the test command with the script runner.
Args:
runner: ScriptRunner instance
"""
runner.register_command(
"test",
test_command,
"Run tests (unit by default, 'integration' for GPU tests)",
)
def register_tests_command(runner):
"""Register the tests command (alias) with the script runner.
Args:
runner: ScriptRunner instance
"""
runner.register_command(
"tests",
tests_command,
"Alias for 'test' command",
)