copilot-swe-agent[bot]
Address code review: use single .to() call and improve test precision
833b39a
| #!/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) | |