#!/usr/bin/env python3 """ End-to-end test script for NeuroSAM 3 app Tests app structure, imports, and function logic without requiring GPU/model """ import sys import os import ast import importlib.util print("=" * 70) print("๐Ÿงช NeuroSAM 3 App - End-to-End Test") print("=" * 70) # Test 1: Check if app.py exists and is readable print("\n[1/8] Checking app.py file...") # Use path relative to this script script_dir = os.path.dirname(os.path.abspath(__file__)) app_path = os.path.join(script_dir, "app.py") if not os.path.exists(app_path): print(f"โŒ ERROR: app.py not found at {app_path}!") sys.exit(1) print(f"โœ… app.py found at {app_path}") # Test 2: Check Python syntax print("\n[2/8] Checking Python syntax...") try: with open(app_path, 'r') as f: code = f.read() ast.parse(code) print("โœ… Python syntax is valid") except SyntaxError as e: print(f"โŒ SYNTAX ERROR: {e}") sys.exit(1) # Test 3: Check required functions exist print("\n[3/8] Checking required functions...") required_functions = [ 'process_medical_image', 'process_with_status', 'process_sequence', 'process_slices_for_viewer', 'navigate_slice', 'extract_subject_id', 'group_images_by_subject', 'compare_with_ground_truth', 'process_with_ground_truth', 'load_demo_file' ] # Optional functions (may have different names) optional_functions = [ 'detect_subjects' # May be defined inline or with different name ] missing_functions = [] for func_name in required_functions: if f"def {func_name}" not in code: missing_functions.append(func_name) if missing_functions: print(f"โŒ Missing functions: {', '.join(missing_functions)}") sys.exit(1) print(f"โœ… All {len(required_functions)} required functions found") # Test 4: Check Gradio components print("\n[4/8] Checking Gradio UI components...") required_components = [ 'gr.Blocks()', 'gr.File(', 'gr.Image(', 'gr.Textbox(', 'gr.Dropdown(', 'gr.Button(', 'gr.Slider(', 'gr.Gallery(', 'gr.Tabs(', 'gr.Tab(' ] missing_components = [] for comp in required_components: if comp not in code: missing_components.append(comp) if missing_components: print(f"โš ๏ธ Missing components: {', '.join(missing_components)}") else: print(f"โœ… All Gradio components found") # Test 5: Check tabs structure print("\n[5/8] Checking UI tabs...") tabs = [ 'Single Image', 'Interactive Slice Viewer', 'Gallery View', 'Compare with Ground Truth' ] found_tabs = [] for tab in tabs: if f'gr.Tab("{tab}")' in code or f"gr.Tab('{tab}')" in code: found_tabs.append(tab) print(f"โœ… Found tabs: {', '.join(found_tabs)}") if len(found_tabs) != len(tabs): print(f"โš ๏ธ Expected {len(tabs)} tabs, found {len(found_tabs)}") # Test 6: Check event handlers print("\n[6/8] Checking event handlers...") required_handlers = [ 'submit_btn.click', 'submit_batch_btn.click', 'submit_gallery_btn.click', 'submit_gt_btn.click', 'detect_subjects_btn.click', 'slice_slider.change', 'prev_btn.click', 'next_btn.click', 'load_demo_btn.click' ] found_handlers = [] for handler in required_handlers: if handler in code: found_handlers.append(handler) print(f"โœ… Found {len(found_handlers)}/{len(required_handlers)} event handlers") if len(found_handlers) < len(required_handlers): missing = [h for h in required_handlers if h not in found_handlers] print(f"โš ๏ธ Missing handlers: {', '.join(missing)}") # Test 7: Check imports print("\n[7/8] Checking imports...") required_imports = [ 'import gradio', 'import torch', 'import pydicom', 'import numpy', 'from PIL import Image', 'from transformers import', 'import matplotlib', 'import tempfile', 'import os' ] missing_imports = [] for imp in required_imports: if imp not in code: missing_imports.append(imp) if missing_imports: print(f"โš ๏ธ Missing imports: {', '.join(missing_imports)}") else: print("โœ… All required imports found") # Test 8: Check for common errors print("\n[8/8] Checking for common errors...") errors_found = [] # Check for undefined variables in function calls if 'processed_results_cache' not in code: errors_found.append("processed_results_cache not defined") # Check if demo.launch() exists if 'demo.launch(' not in code: errors_found.append("demo.launch() call not found") # Check for HF_TOKEN handling if 'HF_TOKEN' not in code: errors_found.append("HF_TOKEN handling not found") elif 'os.getenv("HF_TOKEN")' not in code: errors_found.append("HF_TOKEN not retrieved from environment") if errors_found: print(f"โŒ Errors found: {', '.join(errors_found)}") else: print("โœ… No common errors detected") # Summary print("\n" + "=" * 70) print("๐Ÿ“Š Test Summary") print("=" * 70) all_passed = ( len(missing_functions) == 0 and len(errors_found) == 0 ) if all_passed: print("โœ… All critical tests passed!") print("\n๐Ÿ’ก Next steps:") print(" 1. Set HF_TOKEN environment variable") print(" 2. Test on Hugging Face Space") print(" 3. Upload test DICOM/images to verify functionality") sys.exit(0) else: print("โŒ Some tests failed. Please review the errors above.") sys.exit(1)