#!/usr/bin/env python3 """Comprehensive test runner for the MCP Name Cheap server.""" import sys import subprocess import argparse from pathlib import Path def run_command(cmd: list[str], description: str) -> bool: """Run a command and return success status.""" print(f"\n{'='*60}") print(f"Running: {description}") print(f"Command: {' '.join(cmd)}") print('='*60) try: result = subprocess.run(cmd, check=True, cwd=Path(__file__).parent) print(f"✓ {description} passed") return True except subprocess.CalledProcessError as e: print(f"✗ {description} failed with exit code {e.returncode}") return False except FileNotFoundError: print(f"✗ Command not found: {cmd[0]}") return False def main(): """Main test runner.""" parser = argparse.ArgumentParser(description="Run MCP Name Cheap tests") parser.add_argument("--unit", action="store_true", help="Run only unit tests") parser.add_argument("--integration", action="store_true", help="Run only integration tests") parser.add_argument("--mcp", action="store_true", help="Run only MCP tests") parser.add_argument("--slow", action="store_true", help="Include slow tests") parser.add_argument("--coverage", action="store_true", help="Run with coverage") parser.add_argument("--lint", action="store_true", help="Run linting only") parser.add_argument("--format", action="store_true", help="Run formatting only") parser.add_argument("--typecheck", action="store_true", help="Run type checking only") parser.add_argument("--all", action="store_true", help="Run all checks and tests") parser.add_argument("--fix", action="store_true", help="Auto-fix formatting issues") args = parser.parse_args() if not any([args.unit, args.integration, args.mcp, args.lint, args.format, args.typecheck, args.all]): # Default: run all tests but not linting/formatting args.unit = args.integration = args.mcp = True success = True # Code formatting if args.format or args.all: if args.fix: success &= run_command( ["python", "-m", "ruff", "format", "src/", "tests/", "run_tests.py"], "Code formatting (ruff) - fixing" ) success &= run_command( ["python", "-m", "ruff", "check", "--fix", "src/", "tests/"], "Code linting (ruff) - fixing" ) success &= run_command( ["python", "-m", "black", "src/", "tests/", "run_tests.py"], "Code formatting (black) - fixing" ) success &= run_command( ["python", "-m", "isort", "src/", "tests/", "run_tests.py"], "Import sorting (isort) - fixing" ) else: success &= run_command( ["python", "-m", "black", "--check", "src/", "tests/", "run_tests.py"], "Code formatting (black)" ) success &= run_command( ["python", "-m", "isort", "--check-only", "src/", "tests/", "run_tests.py"], "Import sorting (isort)" ) # Linting with Ruff if args.lint or args.all: success &= run_command( ["python", "-m", "ruff", "check", "src/", "tests/"], "Code linting (ruff)" ) success &= run_command( ["python", "-m", "ruff", "format", "--check", "src/", "tests/"], "Code formatting check (ruff)" ) # Type checking if args.typecheck or args.all: success &= run_command( ["python", "-m", "mypy", "src/mcp_namecheap/"], "Type checking (mypy)" ) # Test execution pytest_cmd = ["python", "-m", "pytest"] if args.coverage: pytest_cmd.extend(["--cov=src/mcp_namecheap", "--cov-report=term-missing", "--cov-report=html"]) # Add verbosity pytest_cmd.extend(["-v", "--tb=short"]) # Test selection markers = [] if args.unit: markers.append("unit") if args.integration: markers.append("integration") if args.mcp: markers.append("mcp") if markers: marker_expr = " or ".join(markers) pytest_cmd.extend(["-m", marker_expr]) if not args.slow: if markers: pytest_cmd.extend(["-m", f"({marker_expr}) and not slow"]) else: pytest_cmd.extend(["-m", "not slow"]) if any([args.unit, args.integration, args.mcp, args.all]) or not any([args.lint, args.format, args.typecheck]): success &= run_command(pytest_cmd, "Running tests") # Summary print(f"\n{'='*60}") if success: print("🎉 All checks passed!") print("="*60) sys.exit(0) else: print("💥 Some checks failed!") print("="*60) sys.exit(1) if __name__ == "__main__": main()