diff --git a/test-multi-path/integration_test.py b/test-multi-path/integration_test.py index 20c4274d..aec0184e 100755 --- a/test-multi-path/integration_test.py +++ b/test-multi-path/integration_test.py @@ -25,6 +25,63 @@ from codewiki.src.be.dependency_analyzer import DependencyGraphBuilder +class TestResults: + """Standardized accumulator for integration test results""" + + def __init__(self): + self.tests = [] + + def add_test(self, name: str, passed: bool, details: str = "") -> None: + """Record a single test result""" + self.tests.append({ + "name": name, + "passed": passed, + "details": details + }) + + def print_summary(self) -> None: + """Print final validation summary""" + print("\n" + "="*80) + print("VALIDATION SUMMARY") + print("="*80) + + total = len(self.tests) + passed_tests = [t for t in self.tests if t["passed"]] + failed_tests = [t for t in self.tests if not t["passed"]] + warning_tests = [t for t in self.tests if t["passed"] and t["details"]] + + passed = len(passed_tests) + failed = len(failed_tests) + + print(f"\nTotal Assertions: {total}") + print(f" ✓ Passed: {passed}") + if failed > 0: + print(f" ✗ Failed: {failed}") + + if failed > 0: + print("\nFailed Assertions:") + for t in failed_tests: + msg = f" ✗ {t['name']}" + if t["details"]: + msg += f" - {t['details']}" + print(msg) + + if warning_tests: + print("\nWarnings:") + for t in warning_tests: + print(f" ⚠ {t['details']}") + + print("\n" + "="*80) + if failed == 0: + print("✅ INTEGRATION TEST PASSED") + else: + print("❌ INTEGRATION TEST FAILED") + print("="*80) + + def all_passed(self) -> bool: + return all(t["passed"] for t in self.tests) + + class IntegrationTestRunner: """Manages end-to-end integration test execution""" @@ -37,11 +94,7 @@ def __init__(self): self.builder = None self.components = None self.leaf_nodes = None - self.results = { - "passed": [], - "failed": [], - "warnings": [] - } + self.results = TestResults() def setup_test_environment(self) -> None: """Create test directory structure with sample files""" @@ -75,7 +128,7 @@ def setup_test_environment(self) -> None: # Create sample files in vendor/ self._create_vendor_files() - self._assert("Test directories created", True) + self.results.add_test("Test directories created", True) def _create_main_files(self) -> None: """Create sample Python files in main/ directory""" @@ -273,7 +326,7 @@ def create_config(self) -> None: for i, path in enumerate(self.config.additional_source_paths, 1): print(f" {i}. {path}") - self._assert("Config created with 3 source paths", True) + self.results.add_test("Config created with 3 source paths", True) def validate_paths(self) -> None: """Validate all configured paths exist""" @@ -292,7 +345,7 @@ def validate_paths(self) -> None: print(f"{'✓' if exists else '✗'} Additional path exists: {path}") all_valid = all_valid and exists - self._assert("All paths validated successfully", all_valid) + self.results.add_test("All paths validated successfully", all_valid) def execute_dependency_parser(self) -> None: """Run DependencyGraphBuilder with all configured paths""" @@ -305,7 +358,7 @@ def execute_dependency_parser(self) -> None: # Check if multi-path mode was detected is_multi = self.config.is_multi_path_mode() print(f"{'✓' if is_multi else '✗'} Multi-path mode detected: {is_multi}") - self._assert("Multi-path mode detected", is_multi) + self.results.add_test("Multi-path mode detected", is_multi) # Build dependency graph print("\nBuilding dependency graph...") @@ -345,14 +398,14 @@ def verify_namespaces(self) -> None: if missing: print(f"\n✗ Missing namespaces: {missing}") - self._assert("All expected namespaces present", False) + self.results.add_test("All expected namespaces present", False) else: print(f"\n✓ All expected namespaces present: {expected}") - self._assert("All expected namespaces present", True) + self.results.add_test("All expected namespaces present", True) if unexpected: print(f"⚠ Unexpected namespaces: {unexpected}") - self.results["warnings"].append(f"Unexpected namespaces: {unexpected}") + self.results.add_test("No unexpected namespaces", True, f"Unexpected namespaces: {unexpected}") # Verify component counts self._verify_namespace_counts(namespaces) @@ -379,7 +432,7 @@ def _verify_namespace_counts(self, namespaces: Dict[str, List[str]]) -> None: print(f" Found components: {sorted(namespaces.get(namespace, []))}") all_match = all_match and match - self._assert("Component counts match expectations", all_match) + self.results.add_test("Component counts match expectations", all_match) def verify_cross_path_dependencies(self) -> None: """Verify cross-path dependencies are correctly resolved""" @@ -413,11 +466,11 @@ def verify_cross_path_dependencies(self) -> None: # but not resolved to specific components across namespaces if len(cross_deps) > 0: print(f"\n✓ Cross-path dependencies detected: {len(cross_deps)} found") - self._assert("Cross-path dependencies detected", True) + self.results.add_test("Cross-path dependencies detected", True) else: print(f"\n✓ No cross-path dependencies detected (expected - not implemented in AST parser yet)") print(f" Note: Import statements are parsed but not resolved across namespaces") - self._assert("Multi-path mode working (dependencies optional)", True) + self.results.add_test("Multi-path mode working (dependencies optional)", True) def verify_no_warnings(self) -> None: """Verify no 'not found' warnings were generated""" @@ -430,7 +483,7 @@ def verify_no_warnings(self) -> None: if not has_warnings: print("✓ No warning tracking mechanism (expected behavior)") - self._assert("No warnings generated", True) + self.results.add_test("No warnings generated", True) return warnings = getattr(self.builder, 'warnings', []) @@ -439,10 +492,10 @@ def verify_no_warnings(self) -> None: print(f"⚠ Found {len(warnings)} warnings:") for warning in warnings: print(f" - {warning}") - self._assert("No warnings generated", False) + self.results.add_test("No warnings generated", False) else: print("✓ No warnings generated") - self._assert("No warnings generated", True) + self.results.add_test("No warnings generated", True) def verify_file_counts(self) -> None: """Verify expected number of components were analyzed""" @@ -469,7 +522,7 @@ def verify_file_counts(self) -> None: print(f"Expected: {expected_total}") match = total == expected_total - self._assert("Component counts match expectations", match) + self.results.add_test("Component counts match expectations", match) def print_detailed_output(self) -> None: """Print comprehensive analysis output""" @@ -509,54 +562,12 @@ def print_detailed_output(self) -> None: for namespace, count in sorted(namespaces.items()): print(f" {namespace}: {count} components") - def print_validation_summary(self) -> None: - """Print final validation summary""" - print("\n" + "="*80) - print("VALIDATION SUMMARY") - print("="*80) - - total = len(self.results["passed"]) + len(self.results["failed"]) - passed = len(self.results["passed"]) - failed = len(self.results["failed"]) - warnings = len(self.results["warnings"]) - - print(f"\nTotal Assertions: {total}") - print(f" ✓ Passed: {passed}") - if failed > 0: - print(f" ✗ Failed: {failed}") - if warnings > 0: - print(f" ⚠ Warnings: {warnings}") - - if failed > 0: - print("\nFailed Assertions:") - for msg in self.results["failed"]: - print(f" ✗ {msg}") - - if warnings > 0: - print("\nWarnings:") - for msg in self.results["warnings"]: - print(f" ⚠ {msg}") - - print("\n" + "="*80) - if failed == 0: - print("✅ INTEGRATION TEST PASSED") - else: - print("❌ INTEGRATION TEST FAILED") - print("="*80) - def cleanup(self) -> None: """Clean up test directory""" if self.test_dir and self.test_dir.exists(): shutil.rmtree(self.test_dir) print(f"\n🧹 Cleaned up test directory: {self.test_dir}") - def _assert(self, message: str, condition: bool) -> None: - """Record assertion result""" - if condition: - self.results["passed"].append(message) - else: - self.results["failed"].append(message) - def run(self) -> int: """Execute complete integration test""" try: @@ -569,9 +580,9 @@ def run(self) -> int: self.verify_no_warnings() self.verify_file_counts() self.print_detailed_output() - self.print_validation_summary() + self.results.print_summary() - return 0 if len(self.results["failed"]) == 0 else 1 + return 0 if self.results.all_passed() else 1 except Exception as e: print(f"\n❌ INTEGRATION TEST CRASHED: {e}") diff --git a/test-multi-path/test_multi_path.py b/test-multi-path/test_multi_path.py index 7ef83bef..fb8cb9fd 100755 --- a/test-multi-path/test_multi_path.py +++ b/test-multi-path/test_multi_path.py @@ -42,6 +42,48 @@ class Colors: END = '\033[0m' +class TestResults: + """Accumulates test results across the suite and prints a summary.""" + + def __init__(self): + self.results = {} + + def add_test(self, name: str, passed: bool): + """Record the result of a single test. + + Args: + name: Test name + passed: Whether the test passed + """ + self.results[name] = passed + + def print_summary(self) -> int: + """Print formatted summary of all recorded test results. + + Returns: + Exit code: 0 if all tests passed, 1 otherwise + """ + print_header("Test Results Summary") + + passed = sum(1 for r in self.results.values() if r) + total = len(self.results) + + for test_name, result in self.results.items(): + if result: + print_success(f"{test_name}") + else: + print_error(f"{test_name}") + + print(f"\n{Colors.BOLD}Total: {passed}/{total} tests passed{Colors.END}") + + if passed == total: + print(f"{Colors.GREEN}{Colors.BOLD}✓ All tests passed!{Colors.END}\n") + return 0 + else: + print(f"{Colors.RED}{Colors.BOLD}✗ Some tests failed{Colors.END}\n") + return 1 + + def print_header(text: str): """Print formatted test header.""" print(f"\n{Colors.BOLD}{Colors.BLUE}{'='*70}{Colors.END}") @@ -485,38 +527,19 @@ def run_all_tests(): ("Relative vs Absolute Paths", test_relative_vs_absolute_paths), ] - results = {} + test_results = TestResults() for test_name, test_func in tests: try: result = test_func() - results[test_name] = result + test_results.add_test(test_name, result) except Exception as e: print_error(f"Test '{test_name}' crashed: {str(e)}") import traceback traceback.print_exc() - results[test_name] = False - - # Print summary - print_header("Test Results Summary") - - passed = sum(1 for r in results.values() if r) - total = len(results) - - for test_name, result in results.items(): - if result: - print_success(f"{test_name}") - else: - print_error(f"{test_name}") - - print(f"\n{Colors.BOLD}Total: {passed}/{total} tests passed{Colors.END}") + test_results.add_test(test_name, False) - if passed == total: - print(f"{Colors.GREEN}{Colors.BOLD}✓ All tests passed!{Colors.END}\n") - return 0 - else: - print(f"{Colors.RED}{Colors.BOLD}✗ Some tests failed{Colors.END}\n") - return 1 + return test_results.print_summary() if __name__ == "__main__": diff --git a/test_id_based_clustering.py b/test_id_based_clustering.py index e28c7f49..57cd5c4e 100644 --- a/test_id_based_clustering.py +++ b/test_id_based_clustering.py @@ -11,6 +11,37 @@ import sys from typing import Dict + +class TestResults: + """Accumulator for standalone integration test scripts.""" + + def __init__(self): + self.tests = [] + + def add_test(self, name: str, passed: bool): + self.tests.append((name, passed)) + + def print_summary(self) -> bool: + print("=" * 60) + print("TEST SUMMARY") + print("=" * 60) + + all_passed = True + for test_name, passed in self.tests: + status = "✅ PASS" if passed else "❌ FAIL" + print(f"{status}: {test_name}") + if not passed: + all_passed = False + + print() + if all_passed: + print("✅ ALL TESTS PASSED") + else: + print("❌ SOME TESTS FAILED") + + return all_passed + + # Test 1: Verify json.loads() works with integer IDs def test_json_parsing(): print("Test 1: JSON parsing with integer IDs") @@ -227,27 +258,15 @@ def test_normalization(): print("=" * 60) print() - results = [] - results.append(("JSON parsing", test_json_parsing())) - results.append(("Return types", test_return_types())) - results.append(("ID validation", test_id_validation())) - results.append(("Normalization", test_normalization())) + results = TestResults() + results.add_test("JSON parsing", test_json_parsing()) + results.add_test("Return types", test_return_types()) + results.add_test("ID validation", test_id_validation()) + results.add_test("Normalization", test_normalization()) - print("=" * 60) - print("TEST SUMMARY") - print("=" * 60) - - all_passed = True - for test_name, passed in results: - status = "✅ PASS" if passed else "❌ FAIL" - print(f"{status}: {test_name}") - if not passed: - all_passed = False + all_passed = results.print_summary() - print() if all_passed: - print("✅ ALL TESTS PASSED") sys.exit(0) else: - print("❌ SOME TESTS FAILED") sys.exit(1)