test_contrib.pyβ’7.54 kB
#!/usr/bin/env python3
"""
Test Runner for MCP Server for Splunk Contributors
This script runs tests for contrib tools with helpful output and filtering.
"""
import subprocess
import sys
from pathlib import Path
def find_test_files(contrib_dir: Path, category: str | None = None) -> list[Path]:
"""Find test files for contrib tools."""
test_files = []
# Base test directory for contrib
test_base = contrib_dir.parent / "tests" / "contrib"
if not test_base.exists():
return test_files
if category:
# Look for tests in specific category
category_dir = test_base / category
if category_dir.exists():
for test_file in category_dir.iterdir():
if (
test_file.is_file()
and test_file.name.startswith("test_")
and test_file.suffix == ".py"
):
test_files.append(test_file)
else:
# Find all contrib test files
for category_dir in test_base.iterdir():
if category_dir.is_dir() and not category_dir.name.startswith("."):
for test_file in category_dir.iterdir():
if (
test_file.is_file()
and test_file.name.startswith("test_")
and test_file.suffix == ".py"
):
test_files.append(test_file)
return sorted(test_files)
def run_pytest(test_files: list[Path], verbose: bool = False, coverage: bool = False) -> int:
"""Run pytest on the specified test files."""
if not test_files:
print("No test files found to run.")
return 0
# Build pytest command
cmd = ["python", "-m", "pytest"]
if verbose:
cmd.append("-v")
else:
cmd.append("-q")
if coverage:
cmd.extend(["--cov=contrib", "--cov-report=term-missing"])
# Add test files
cmd.extend([str(f) for f in test_files])
print(f"Running: {' '.join(cmd)}")
print("=" * 60)
try:
result = subprocess.run(cmd, cwd=Path.cwd())
return result.returncode
except KeyboardInterrupt:
print("\nTest run interrupted by user")
return 130
except Exception as e:
print(f"Error running tests: {e}")
return 1
def list_test_files(contrib_dir: Path):
"""List available test files."""
test_files = find_test_files(contrib_dir)
if not test_files:
print("No contrib test files found.")
return
print("Available contrib test files:")
print("=" * 50)
# Group by category
by_category = {}
test_base = contrib_dir.parent / "tests" / "contrib"
for test_file in test_files:
# Extract category from path
rel_path = test_file.relative_to(test_base)
category = rel_path.parts[0] if len(rel_path.parts) > 1 else "unknown"
if category not in by_category:
by_category[category] = []
by_category[category].append(test_file)
for category, files in sorted(by_category.items()):
print(f"\nπ {category.upper()}:")
for test_file in files:
print(f" β’ {test_file.name}")
def check_test_environment():
"""Check if the test environment is set up correctly."""
import importlib.util
issues = []
# Check if pytest is available
try:
subprocess.run(["python", "-m", "pytest", "--version"], capture_output=True, check=True)
except (subprocess.CalledProcessError, FileNotFoundError):
issues.append("pytest is not installed or not available")
# Check if we can import required modules
if importlib.util.find_spec("fastmcp") is None:
issues.append("fastmcp module not available")
if importlib.util.find_spec("src.core.base") is None:
issues.append("src.core.base module not available - run from project root")
if issues:
print("β Test environment issues:")
for issue in issues:
print(f" β’ {issue}")
return False
else:
print("β
Test environment looks good")
return True
def main():
"""Main function."""
# Determine project structure
script_dir = Path(__file__).parent
project_root = script_dir.parent.parent
contrib_dir = project_root / "contrib"
if not contrib_dir.exists():
print("Error: contrib directory not found")
sys.exit(1)
# Parse command line arguments
if len(sys.argv) == 1:
# Run all contrib tests
if not check_test_environment():
sys.exit(1)
test_files = find_test_files(contrib_dir)
if not test_files:
print(
"No contrib test files found. Use 'python generate_tool.py' to create tools with tests."
)
sys.exit(0)
exit_code = run_pytest(test_files)
sys.exit(exit_code)
elif len(sys.argv) == 2:
arg = sys.argv[1]
if arg == "--help":
print("Usage:")
print(" python test_contrib.py - Run all contrib tests")
print(" python test_contrib.py --list - List available test files")
print(" python test_contrib.py --verbose - Run tests with verbose output")
print(" python test_contrib.py --coverage - Run tests with coverage report")
print(" python test_contrib.py --check - Check test environment")
print(" python test_contrib.py <category> - Run tests for specific category")
print(" python test_contrib.py --help - Show this help")
elif arg == "--list":
list_test_files(contrib_dir)
elif arg == "--check":
if check_test_environment():
print("Environment is ready for testing.")
else:
sys.exit(1)
elif arg == "--verbose":
if not check_test_environment():
sys.exit(1)
test_files = find_test_files(contrib_dir)
exit_code = run_pytest(test_files, verbose=True)
sys.exit(exit_code)
elif arg == "--coverage":
if not check_test_environment():
sys.exit(1)
test_files = find_test_files(contrib_dir)
exit_code = run_pytest(test_files, coverage=True)
sys.exit(exit_code)
else:
# Assume it's a category name
if not check_test_environment():
sys.exit(1)
category = arg
test_files = find_test_files(contrib_dir, category)
if not test_files:
print(f"No test files found for category: {category}")
print("Available categories:")
all_files = find_test_files(contrib_dir)
test_base = contrib_dir.parent / "tests" / "contrib"
categories = set()
for test_file in all_files:
rel_path = test_file.relative_to(test_base)
if len(rel_path.parts) > 1:
categories.add(rel_path.parts[0])
for cat in sorted(categories):
print(f" β’ {cat}")
sys.exit(1)
exit_code = run_pytest(test_files)
sys.exit(exit_code)
else:
print("Invalid arguments. Use --help for usage information.")
sys.exit(1)
if __name__ == "__main__":
main()