1+ #!/usr/bin/env python3
2+ """Test runner script for MCP Sequential Thinking Server.
3+
4+ This script provides a convenient way to run tests with different
5+ configurations and options.
6+ """
7+
8+ import argparse
9+ import subprocess
10+ import sys
11+ from pathlib import Path
12+
13+
14+ def run_command (cmd : list [str ], description : str ) -> int :
15+ """Run a command and return its exit code."""
16+ print (f"\n 🔍 { description } " )
17+ print (f"Running: { ' ' .join (cmd )} " )
18+ print ("-" * 50 )
19+
20+ result = subprocess .run (cmd , capture_output = False )
21+
22+ if result .returncode == 0 :
23+ print (f"✅ { description } completed successfully" )
24+ else :
25+ print (f"❌ { description } failed with exit code { result .returncode } " )
26+
27+ return result .returncode
28+
29+
30+ def main ():
31+ """Main test runner function."""
32+ parser = argparse .ArgumentParser (
33+ description = "Test runner for MCP Sequential Thinking Server" ,
34+ formatter_class = argparse .RawDescriptionHelpFormatter ,
35+ epilog = """
36+ Examples:
37+ python run_tests.py # Run all tests
38+ python run_tests.py --unit # Run only unit tests
39+ python run_tests.py --integration # Run only integration tests
40+ python run_tests.py --security # Run only security tests
41+ python run_tests.py --coverage # Run tests with coverage report
42+ python run_tests.py --fast # Run tests without coverage
43+ python run_tests.py --debug # Run tests in debug mode
44+ """
45+ )
46+
47+ # Test selection options
48+ parser .add_argument (
49+ "--unit" , action = "store_true" ,
50+ help = "Run only unit tests"
51+ )
52+ parser .add_argument (
53+ "--integration" , action = "store_true" ,
54+ help = "Run only integration tests"
55+ )
56+ parser .add_argument (
57+ "--security" , action = "store_true" ,
58+ help = "Run only security tests"
59+ )
60+ parser .add_argument (
61+ "--config" , action = "store_true" ,
62+ help = "Run only configuration tests"
63+ )
64+
65+ # Test execution options
66+ parser .add_argument (
67+ "--coverage" , action = "store_true" ,
68+ help = "Generate coverage report"
69+ )
70+ parser .add_argument (
71+ "--fast" , action = "store_true" ,
72+ help = "Run tests without coverage (faster)"
73+ )
74+ parser .add_argument (
75+ "--debug" , action = "store_true" ,
76+ help = "Run tests in debug mode with verbose output"
77+ )
78+ parser .add_argument (
79+ "--parallel" , action = "store_true" ,
80+ help = "Run tests in parallel"
81+ )
82+ parser .add_argument (
83+ "--html" , action = "store_true" ,
84+ help = "Generate HTML coverage report"
85+ )
86+
87+ # Output options
88+ parser .add_argument (
89+ "--quiet" , action = "store_true" ,
90+ help = "Reduce output verbosity"
91+ )
92+ parser .add_argument (
93+ "--junit" , action = "store_true" ,
94+ help = "Generate JUnit XML report"
95+ )
96+
97+ args = parser .parse_args ()
98+
99+ # Build pytest command
100+ cmd = ["uv" , "run" , "pytest" ]
101+
102+ # Test selection
103+ if args .unit :
104+ cmd .append ("tests/unit" )
105+ elif args .integration :
106+ cmd .append ("tests/integration" )
107+ elif args .security :
108+ cmd .extend (["-m" , "security" ])
109+ elif args .config :
110+ cmd .extend (["-m" , "config" ])
111+ else :
112+ cmd .append ("tests" )
113+
114+ # Coverage options
115+ if args .coverage or (not args .fast and not args .debug ):
116+ cmd .extend ([
117+ "--cov=src/mcp_server_mas_sequential_thinking" ,
118+ "--cov-report=term-missing"
119+ ])
120+
121+ if args .html :
122+ cmd .append ("--cov-report=html" )
123+
124+ # Output options
125+ if args .debug :
126+ cmd .extend (["-v" , "-s" , "--tb=long" ])
127+ elif args .quiet :
128+ cmd .extend (["-q" , "--tb=short" ])
129+ else :
130+ cmd .extend (["-v" , "--tb=short" ])
131+
132+ # Parallel execution
133+ if args .parallel :
134+ cmd .extend (["-n" , "auto" ])
135+
136+ # JUnit reporting
137+ if args .junit :
138+ cmd .append ("--junit-xml=test-results.xml" )
139+
140+ # Run the tests
141+ description = "Running tests"
142+ if args .unit :
143+ description = "Running unit tests"
144+ elif args .integration :
145+ description = "Running integration tests"
146+ elif args .security :
147+ description = "Running security tests"
148+ elif args .config :
149+ description = "Running configuration tests"
150+
151+ exit_code = run_command (cmd , description )
152+
153+ # Additional commands based on options
154+ if args .coverage and exit_code == 0 :
155+ print ("\n 📊 Coverage report generated!" )
156+ if args .html :
157+ print ("📄 HTML coverage report: htmlcov/index.html" )
158+
159+ if exit_code == 0 :
160+ print ("\n 🎉 All tests completed successfully!" )
161+
162+ # Run additional quality checks if all tests pass
163+ print ("\n 🔍 Running additional quality checks..." )
164+
165+ # Type checking
166+ type_check_result = run_command (
167+ ["uv" , "run" , "mypy" , "src" , "--ignore-missing-imports" ],
168+ "Type checking with mypy"
169+ )
170+
171+ # Linting
172+ lint_result = run_command (
173+ ["uv" , "run" , "ruff" , "check" , "src" , "tests" ],
174+ "Linting with ruff"
175+ )
176+
177+ if type_check_result == 0 and lint_result == 0 :
178+ print ("\n ✨ All quality checks passed!" )
179+ else :
180+ print ("\n ⚠️ Some quality checks failed" )
181+ exit_code = max (exit_code , type_check_result , lint_result )
182+
183+ sys .exit (exit_code )
184+
185+
186+ if __name__ == "__main__" :
187+ main ()
0 commit comments