Skip to content

Commit aa6a72f

Browse files
authored
Merge pull request #118 from Teradata/feature/testing-framework
Implement comprehensive automated testing framework for regression te…
2 parents d72f0bc + 0ece244 commit aa6a72f

24 files changed

+4197
-0
lines changed

docs/TESTING_FRAMEWORK.md

Lines changed: 597 additions & 0 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ test = [
3030
"litellm>=1.68.2",
3131
"nest-asyncio>=1.6.0",
3232
"google-adk>=1.3.0",
33+
"jinja2>=3.1.0",
3334
]
3435

3536
[project.scripts]
3637
teradata-mcp-server = "teradata_mcp_server:main"
38+
teradata-test = "teradata_mcp_server.testing.cli:main"
3739

3840
[build-system]
3941
requires = ["setuptools>=65", "wheel"]

run_tests.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Launcher script for the Teradata MCP Testing Framework.
4+
This script redirects to the main test runner in scripts/testing/
5+
"""
6+
7+
import sys
8+
import subprocess
9+
from pathlib import Path
10+
11+
def main():
12+
"""Launch the main test runner."""
13+
# Path to the main test runner
14+
main_script = Path(__file__).parent / "scripts" / "testing" / "run_tests.py"
15+
16+
if not main_script.exists():
17+
print("❌ Main test runner not found at:", main_script)
18+
return 1
19+
20+
print("🚀 Launching Teradata MCP Testing Framework...")
21+
print(f" Using: {main_script}")
22+
print()
23+
24+
# Execute the main script
25+
try:
26+
result = subprocess.run([sys.executable, str(main_script)] + sys.argv[1:],
27+
cwd=Path(__file__).parent)
28+
return result.returncode
29+
except KeyboardInterrupt:
30+
print("\n⚠ Test execution interrupted by user")
31+
return 130
32+
except Exception as e:
33+
print(f"❌ Error launching test runner: {e}")
34+
return 1
35+
36+
if __name__ == "__main__":
37+
sys.exit(main())

scripts/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Scripts Directory
2+
3+
This directory contains utility scripts for the Teradata MCP Server project.
4+
5+
## 📁 Directory Structure
6+
7+
```
8+
scripts/
9+
└── testing/ # Testing framework scripts
10+
├── README.md # Testing scripts documentation
11+
├── run_tests.py # Main test runner ⭐
12+
└── [other files] # Development and validation scripts
13+
```
14+
15+
## 🚀 Quick Start
16+
17+
### Run Tests
18+
```bash
19+
# From project root - use the launcher
20+
python run_tests.py
21+
22+
# Or directly from scripts directory
23+
python scripts/testing/run_tests.py
24+
```
25+
26+
### Explore Testing Options
27+
```bash
28+
# See testing scripts documentation
29+
cat scripts/testing/README.md
30+
31+
# List all available testing scripts
32+
ls scripts/testing/
33+
```
34+
35+
## 📋 Available Script Categories
36+
37+
- **🧪 Testing Scripts**: `testing/` - Complete testing framework and utilities
38+
- **🔧 Future Extensions**: Additional script categories can be added here
39+
40+
## 📚 Related Documentation
41+
42+
- **Testing Framework**: `docs/TESTING_FRAMEWORK.md`
43+
- **Developer Guide**: `docs/developer_guide/DEVELOPER_GUIDE.md`
44+
- **Project README**: `README.md`

scripts/testing/README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Testing Scripts Directory
2+
3+
This directory contains various scripts for testing and validating the Teradata MCP Testing Framework.
4+
5+
## 🚀 Main Scripts
6+
7+
### `run_tests.py`
8+
**Primary test execution script** - Use this for running the testing framework.
9+
10+
- **Purpose**: Complete testing framework execution with real test discovery
11+
- **Features**: Discovers all test prompts, executes realistic simulations, generates reports
12+
- **Usage**: `python scripts/testing/run_tests.py`
13+
- **Outputs**: Console report + JSON report in `test_results/`
14+
15+
## 🔧 Development & Validation Scripts
16+
17+
### `component_tests.py`
18+
**Component validation** - Tests individual framework components in isolation.
19+
20+
- **Purpose**: Validate core framework components without server dependencies
21+
- **Tests**: Result structures, configuration, basic functionality
22+
- **Usage**: `python scripts/testing/component_tests.py`
23+
24+
### `demo_testing_framework.py`
25+
**Framework demonstration** - Shows framework capabilities and structure.
26+
27+
- **Purpose**: Demonstrate framework features and architecture
28+
- **Features**: Shows test discovery, component loading, usage instructions
29+
- **Usage**: `python scripts/testing/demo_testing_framework.py`
30+
31+
### `framework_demo.py`
32+
**Interactive framework demo** - Comprehensive framework demonstration.
33+
34+
- **Purpose**: Full framework walkthrough with actual test discovery
35+
- **Features**: Real test prompt discovery, simulated execution, reporting
36+
- **Usage**: `python scripts/testing/framework_demo.py`
37+
38+
## 🧪 Legacy & Experimental Scripts
39+
40+
### `execute_tests.py`
41+
**Experimental test runner** - Alternative implementation approach.
42+
43+
- **Purpose**: Alternative test execution implementation
44+
- **Status**: Experimental, may have import issues
45+
- **Usage**: `python scripts/testing/execute_tests.py`
46+
47+
### `run_tests_legacy.py`
48+
**Legacy test runner** - Original test runner attempt.
49+
50+
- **Purpose**: Early framework implementation
51+
- **Status**: Legacy, kept for reference
52+
- **Usage**: Not recommended for use
53+
54+
### `validate_testing_framework.py`
55+
**Full framework validation** - Comprehensive validation including server components.
56+
57+
- **Purpose**: Complete framework validation with database connections
58+
- **Status**: May fail due to database connection requirements
59+
- **Usage**: `python scripts/testing/validate_testing_framework.py`
60+
61+
### `validate_testing_framework_simple.py`
62+
**Simple validation** - Basic framework validation without database.
63+
64+
- **Purpose**: Core component validation without external dependencies
65+
- **Status**: Simplified validation approach
66+
- **Usage**: `python scripts/testing/validate_testing_framework_simple.py`
67+
68+
## 📋 Quick Start Guide
69+
70+
1. **Run the main testing framework**:
71+
```bash
72+
python scripts/testing/run_tests.py
73+
```
74+
75+
2. **Validate framework components**:
76+
```bash
77+
python scripts/testing/component_tests.py
78+
```
79+
80+
3. **See framework demonstration**:
81+
```bash
82+
python scripts/testing/demo_testing_framework.py
83+
```
84+
85+
## 📁 Directory Structure
86+
87+
```
88+
scripts/testing/
89+
├── README.md # This file
90+
├── run_tests.py # Main test runner ⭐
91+
├── component_tests.py # Component validation
92+
├── demo_testing_framework.py # Framework demo
93+
├── framework_demo.py # Interactive demo
94+
├── execute_tests.py # Experimental runner
95+
├── run_tests_legacy.py # Legacy implementation
96+
├── validate_testing_framework.py # Full validation
97+
└── validate_testing_framework_simple.py # Simple validation
98+
```
99+
100+
## 🎯 Recommended Usage
101+
102+
- **For regular testing**: Use `run_tests.py`
103+
- **For development**: Use `component_tests.py` to validate changes
104+
- **For demos**: Use `demo_testing_framework.py` to show capabilities
105+
- **For troubleshooting**: Check `validate_testing_framework_simple.py`
106+
107+
## 📚 Related Files
108+
109+
- **Framework Source**: `src/teradata_mcp_server/testing/`
110+
- **Documentation**: `docs/TESTING_FRAMEWORK.md`
111+
- **Configuration**: `test_config.yml`
112+
- **Reports Output**: `test_results/`

scripts/testing/component_tests.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Test individual framework components without server dependencies.
4+
"""
5+
6+
import sys
7+
from pathlib import Path
8+
9+
# Add the testing package directly to path
10+
testing_path = Path(__file__).parent / "src" / "teradata_mcp_server" / "testing"
11+
sys.path.insert(0, str(testing_path))
12+
13+
def test_result_module():
14+
"""Test the result module."""
15+
print("Testing result module...")
16+
17+
try:
18+
from result import TestResult, TestPhaseResult, TestStatus
19+
from datetime import datetime
20+
21+
# Test TestStatus enum
22+
assert TestStatus.PENDING.value == "pending"
23+
assert TestStatus.PASSED.value == "passed"
24+
print("✓ TestStatus enum works")
25+
26+
# Test TestPhaseResult
27+
phase = TestPhaseResult(
28+
phase_name="Setup Phase",
29+
phase_number=1,
30+
status=TestStatus.RUNNING,
31+
start_time=datetime.now()
32+
)
33+
phase.finish(TestStatus.PASSED, "Setup completed successfully")
34+
assert phase.status == TestStatus.PASSED
35+
assert phase.duration is not None
36+
print("✓ TestPhaseResult works")
37+
38+
# Test TestResult
39+
result = TestResult(
40+
test_name="test_sample",
41+
module_name="base",
42+
status=TestStatus.RUNNING,
43+
start_time=datetime.now()
44+
)
45+
result.add_phase(phase)
46+
result.finish(TestStatus.PASSED, "Test completed")
47+
48+
assert result.total_phases == 1
49+
assert result.passed_phases == 1
50+
assert result.success_rate == 100.0
51+
print("✓ TestResult works")
52+
53+
return True
54+
55+
except Exception as e:
56+
print(f"✗ Result module test failed: {e}")
57+
return False
58+
59+
def test_config_module():
60+
"""Test the config module."""
61+
print("Testing config module...")
62+
63+
try:
64+
from config import TestConfig
65+
import tempfile
66+
import os
67+
68+
# Test default config
69+
config = TestConfig()
70+
assert config.timeout_seconds == 300
71+
assert config.llm_provider == "anthropic"
72+
assert config.generate_html_report == True
73+
print("✓ Default configuration created")
74+
75+
# Test file save/load
76+
with tempfile.NamedTemporaryFile(mode='w', suffix='.yml', delete=False) as f:
77+
temp_path = f.name
78+
79+
try:
80+
config.save_to_file(temp_path)
81+
loaded_config = TestConfig.from_file(temp_path)
82+
assert loaded_config.timeout_seconds == config.timeout_seconds
83+
assert loaded_config.llm_provider == config.llm_provider
84+
print("✓ Configuration file operations work")
85+
finally:
86+
os.unlink(temp_path)
87+
88+
return True
89+
90+
except Exception as e:
91+
print(f"✗ Config module test failed: {e}")
92+
return False
93+
94+
def test_reporter_module():
95+
"""Test the reporter module."""
96+
print("Testing reporter module...")
97+
98+
try:
99+
from reporter import TestReporter
100+
from config import TestConfig
101+
from result import TestResult, TestStatus
102+
from datetime import datetime
103+
import tempfile
104+
import shutil
105+
106+
# Create temp directory for outputs
107+
temp_dir = tempfile.mkdtemp()
108+
109+
try:
110+
# Create config and reporter
111+
config = TestConfig()
112+
config.output_directory = temp_dir
113+
config.generate_json_report = False # Skip file generation for test
114+
config.generate_html_report = False
115+
reporter = TestReporter(config)
116+
117+
# Create sample test result
118+
result = TestResult(
119+
test_name="test_sample",
120+
module_name="base",
121+
status=TestStatus.PASSED,
122+
start_time=datetime.now()
123+
)
124+
result.finish(TestStatus.PASSED, "Test completed successfully")
125+
126+
# Test console report
127+
console_output = reporter.generate_console_report([result])
128+
assert "TERADATA MCP TEST RESULTS" in console_output
129+
assert "test_sample" in console_output
130+
assert "✓" in console_output # Pass indicator
131+
print("✓ Console report generation works")
132+
133+
return True
134+
135+
finally:
136+
shutil.rmtree(temp_dir)
137+
138+
except Exception as e:
139+
print(f"✗ Reporter module test failed: {e}")
140+
return False
141+
142+
def main():
143+
"""Run component tests."""
144+
print("=" * 60)
145+
print("TESTING FRAMEWORK COMPONENTS VALIDATION")
146+
print("=" * 60)
147+
148+
tests = [
149+
test_result_module,
150+
test_config_module,
151+
test_reporter_module,
152+
]
153+
154+
passed = 0
155+
total = len(tests)
156+
157+
for test in tests:
158+
try:
159+
if test():
160+
passed += 1
161+
else:
162+
print(f"Test {test.__name__} failed")
163+
except Exception as e:
164+
print(f"Test {test.__name__} crashed: {e}")
165+
import traceback
166+
traceback.print_exc()
167+
168+
print("\n" + "=" * 60)
169+
print(f"VALIDATION SUMMARY: {passed}/{total} tests passed")
170+
171+
if passed == total:
172+
print("✓ Framework components validation PASSED")
173+
print("\nCore components are working correctly!")
174+
return 0
175+
else:
176+
print("✗ Framework components validation FAILED")
177+
return 1
178+
179+
if __name__ == "__main__":
180+
exit(main())

0 commit comments

Comments
 (0)