Skip to main content
Glama

TimeLooker MCP Server

test_lambda.py12.6 kB
""" Local testing script for TimeLooker Lambda function. Simulates AWS Lambda invocations for development and testing. """ import json import time import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from scripts.lambda_function import lambda_handler class LambdaTester: """ Simulates AWS Lambda environment for local testing. """ def __init__(self): self.test_results = [] def invoke_lambda(self, event, description=""): """ Invoke lambda function and track results. Args: event: Event dictionary to pass to lambda description: Description of the test """ print(f"\n{'='*60}") print(f"TEST: {description}") print(f"Event: {json.dumps(event, indent=2)}") print(f"{'='*60}") start_time = time.time() try: response = lambda_handler(event, None) execution_time = time.time() - start_time print(f"✓ Lambda executed successfully in {execution_time:.2f}s") print(f"Response: {json.dumps(response, indent=2)}") # Determine if this is an expected failure based on test description expected_failure = any(phrase in description.lower() for phrase in [ 'should fail', 'should return error', 'non-existent', 'invalid', 'missing fields' ]) status_code = response.get('statusCode', 500) # For expected failures, success means getting an error status code (4xx or 5xx) # For normal tests, success means getting a success status code (2xx or 3xx) if expected_failure: success = status_code >= 400 else: success = status_code < 400 self.test_results.append({ 'description': description, 'event': event, 'response': response, 'execution_time': execution_time, 'success': success, 'expected_failure': expected_failure, 'status_code': status_code }) return response except Exception as e: execution_time = time.time() - start_time print(f"✗ Lambda execution failed in {execution_time:.2f}s") print(f"Error: {str(e)}") self.test_results.append({ 'description': description, 'event': event, 'error': str(e), 'execution_time': execution_time, 'success': False, 'expected_failure': False, 'status_code': 500 }) return None def run_full_test_suite(self): """ Run a comprehensive test suite that simulates real usage. """ print("Starting TimeLooker Lambda Test Suite") print("=====================================") # Test 1: List tasks (should be empty initially) self.invoke_lambda( {"action": "list_tasks"}, "List tasks (initial - should be empty)" ) # Test 2: Create a new task create_response = self.invoke_lambda( { "action": "create_task", "task_config": { "task_description": "AI Ethics and Safety openings fit for a PhD in Computer Science", "frequency_minutes": 30, "runtime_minutes": 120, "recipient_email": "user@example.com" } }, "Create new monitoring task" ) # Extract task ID for subsequent tests task_id = None if create_response and create_response.get('statusCode') == 200: body = json.loads(create_response['body']) task_id = body.get('task_id') # Test 3: List tasks (should now show the created task) self.invoke_lambda( {"action": "list_tasks"}, "List tasks (after creating one)" ) if task_id: # Test 4: Execute search for the created task self.invoke_lambda( { "action": "execute_search", "task_id": task_id }, f"Execute search for task {task_id} (first run)" ) # Test 5: Execute search again (should detect duplicates) self.invoke_lambda( { "action": "execute_search", "task_id": task_id }, f"Execute search for task {task_id} (second run - should detect duplicates)" ) # Test 6: Try to execute search for non-existent task self.invoke_lambda( { "action": "execute_search", "task_id": 99999 }, "Execute search for non-existent task (should fail)" ) # Test 7: Invalid action self.invoke_lambda( {"action": "invalid_action"}, "Invalid action (should return error)" ) # Test 8: Create task with missing fields self.invoke_lambda( { "action": "create_task", "task_config": { "task_description": "Incomplete task" # Missing required fields } }, "Create task with missing fields (should fail)" ) # Test 9: Create another task with different parameters self.invoke_lambda( { "action": "create_task", "task_config": { "task_description": "New sneaker releases from Nike and Adidas", "frequency_minutes": 60, "runtime_minutes": 180, "recipient_email": "sneaker.fan@example.com" } }, "Create second task (different domain)" ) # Test 10: Final task list self.invoke_lambda( {"action": "list_tasks"}, "Final task list (should show multiple tasks)" ) self.print_test_summary() def run_frequency_test(self): """ Test the frequency checking mechanism. """ print("\nTesting frequency mechanism...") # Create a task with short frequency for testing create_response = self.invoke_lambda( { "action": "create_task", "task_config": { "task_description": "Test frequency task", "frequency_minutes": 1, # Very short for testing "runtime_minutes": 60, "recipient_email": "test@example.com" } }, "Create task for frequency testing" ) if create_response and create_response.get('statusCode') == 200: body = json.loads(create_response['body']) task_id = body.get('task_id') # First execution should work self.invoke_lambda( {"action": "execute_search", "task_id": task_id}, "First execution (should work)" ) # Immediate second execution should be skipped self.invoke_lambda( {"action": "execute_search", "task_id": task_id}, "Immediate second execution (should be skipped due to frequency)" ) print("Waiting 65 seconds to test frequency mechanism...") time.sleep(65) # Third execution after waiting should work self.invoke_lambda( {"action": "execute_search", "task_id": task_id}, "Third execution after waiting (should work)" ) def print_test_summary(self): """ Print a summary of all test results. """ print(f"\n{'='*60}") print("TEST SUMMARY") print(f"{'='*60}") total_tests = len(self.test_results) successful_tests = sum(1 for result in self.test_results if result['success']) failed_tests = total_tests - successful_tests # Count expected vs unexpected failures unexpected_failures = sum(1 for result in self.test_results if not result['success'] and not result.get('expected_failure', False)) expected_failures = sum(1 for result in self.test_results if result['success'] and result.get('expected_failure', False)) print(f"Total tests: {total_tests}") print(f"Successful: {successful_tests} (including {expected_failures} expected failures)") print(f"Failed: {failed_tests}") print(f"Unexpected failures: {unexpected_failures}") print(f"Success rate: {(successful_tests/total_tests)*100:.1f}%") if unexpected_failures > 0: print(f"\nUnexpected failures:") for result in self.test_results: if not result['success'] and not result.get('expected_failure', False): print(f" ✗ {result['description']}") if 'error' in result: print(f" Error: {result['error']}") else: print(f" Status: {result.get('status_code', 'Unknown')}") if expected_failures > 0: print(f"\nExpected failures (working correctly):") for result in self.test_results: if result['success'] and result.get('expected_failure', False): print(f" ✓ {result['description']} (Status: {result.get('status_code', 'Unknown')})") # Show execution times avg_time = sum(result['execution_time'] for result in self.test_results) / total_tests max_time = max(result['execution_time'] for result in self.test_results) min_time = min(result['execution_time'] for result in self.test_results) print(f"\nExecution times:") print(f" Average: {avg_time:.2f}s") print(f" Max: {max_time:.2f}s") print(f" Min: {min_time:.2f}s") def main(): """ Main function to run tests. """ import argparse parser = argparse.ArgumentParser(description="Test TimeLooker Lambda function locally") parser.add_argument("--full", action="store_true", help="Run full test suite") parser.add_argument("--frequency", action="store_true", help="Run frequency test (takes ~2 minutes)") parser.add_argument("--quick", action="store_true", help="Run quick basic tests") args = parser.parse_args() tester = LambdaTester() if args.full: tester.run_full_test_suite() elif args.frequency: tester.run_frequency_test() elif args.quick: # Quick test - just create and list tester.invoke_lambda({"action": "list_tasks"}, "Quick test - list tasks") create_response = tester.invoke_lambda( { "action": "create_task", "task_config": { "task_description": "Quick test task", "frequency_minutes": 60, "runtime_minutes": 120, "recipient_email": "test@example.com" } }, "Quick test - create task" ) tester.print_test_summary() else: # Default: run basic functionality test print("Running basic functionality test...") print("Use --full for comprehensive testing, --quick for minimal testing") tester.invoke_lambda({"action": "list_tasks"}, "List tasks") tester.invoke_lambda( { "action": "create_task", "task_config": { "task_description": "Test monitoring task", "frequency_minutes": 30, "runtime_minutes": 120, "recipient_email": "test@example.com" } }, "Create test task" ) tester.print_test_summary() if __name__ == "__main__": main()

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/fortnightly-devs/mcp-x402-task-scheduler'

If you have feedback or need assistance with the MCP directory API, please join our Discord server