"""
Test runner for anymatrix - runs property tests on all matrices
Similar to test_anymatrix_properties.m from MATLAB version.
"""
import time
from typing import Dict, List, Optional, Tuple
import warnings
from matrix_toolkit.anymatrix import AnyMatrix
from matrix_toolkit.anymatrix.testing.property_checker import check_matrix_properties
class AnyMatrixTestRunner:
"""Run comprehensive tests on anymatrix collection"""
def __init__(self, anymatrix_instance: Optional[AnyMatrix] = None):
"""
Initialize test runner
Args:
anymatrix_instance: AnyMatrix instance to test (creates new if None)
"""
self.am = anymatrix_instance or AnyMatrix()
self.results = {}
self.test_sizes = [3, 5, 8, 10, 15, 20, 25, 30]
def test_single_matrix(
self,
matrix_id: str,
sizes: Optional[List[int]] = None,
verbose: bool = False
) -> Dict[str, bool]:
"""
Test a single matrix with various sizes
Args:
matrix_id: Matrix identifier (e.g., 'core/beta')
sizes: List of sizes to test (uses default if None)
verbose: Print detailed results
Returns:
Dictionary of test results
"""
sizes = sizes or self.test_sizes
expected_properties = self.am.properties(matrix_id)
all_results = {}
for size in sizes:
try:
# Try to generate matrix with this size
matrix = self.am.generate(matrix_id, size)
# Check properties
prop_results = check_matrix_properties(
matrix,
f"{matrix_id}(n={size})",
expected_properties,
verbose=verbose
)
all_results[size] = {
'success': True,
'properties': prop_results
}
except Exception as e:
all_results[size] = {
'success': False,
'error': str(e)
}
if verbose:
print(f" Error with size {size}: {e}")
return all_results
def test_matrix_no_args(
self,
matrix_id: str,
verbose: bool = False
) -> Dict[str, bool]:
"""
Test matrix generation without arguments
Args:
matrix_id: Matrix identifier
verbose: Print results
Returns:
Test results
"""
expected_properties = self.am.properties(matrix_id)
try:
matrix = self.am.generate(matrix_id)
if verbose:
print(f"\nTesting {matrix_id} (no arguments)")
results = check_matrix_properties(
matrix,
matrix_id,
expected_properties,
verbose=verbose
)
return {
'success': True,
'properties': results
}
except Exception as e:
if verbose:
print(f"Cannot generate {matrix_id} without arguments: {e}")
return {
'success': False,
'error': str(e)
}
def run_all_tests(
self,
groups: Optional[List[str]] = None,
verbose: bool = True,
stop_on_error: bool = False
) -> Dict:
"""
Run tests on all matrices in specified groups
Args:
groups: List of groups to test (all if None)
verbose: Print progress
stop_on_error: Stop on first error
Returns:
Comprehensive test results
"""
groups = groups or self.am.groups()
start_time = time.time()
results = {}
total_matrices = 0
passed_matrices = 0
failed_matrices = 0
if verbose:
print("\n" + "=" * 70)
print("ANYMATRIX TEST SUITE")
print("=" * 70)
for group in groups:
if verbose:
print(f"\n{'Testing group: ' + group.upper():-^70}")
group_results = {}
matrices = self.am.list(group)
for matrix_name in matrices:
matrix_id = f"{group}/{matrix_name}"
total_matrices += 1
if verbose:
print(f"\n[{total_matrices}] Testing: {matrix_id}")
try:
# Test without arguments first
no_args_result = self.test_matrix_no_args(matrix_id, verbose=verbose)
# Test with various sizes
sized_results = self.test_single_matrix(matrix_id, verbose=verbose)
# Combine results
group_results[matrix_name] = {
'no_args': no_args_result,
'sized': sized_results
}
# Check if any test passed
any_success = no_args_result.get('success', False) or \
any(r.get('success', False) for r in sized_results.values())
if any_success:
passed_matrices += 1
if verbose:
print(f" ✓ {matrix_id} PASSED")
else:
failed_matrices += 1
if verbose:
print(f" ✗ {matrix_id} FAILED")
except Exception as e:
failed_matrices += 1
group_results[matrix_name] = {
'error': str(e)
}
if verbose:
print(f" ✗ {matrix_id} ERROR: {e}")
if stop_on_error:
raise
results[group] = group_results
elapsed_time = time.time() - start_time
if verbose:
print("\n" + "=" * 70)
print("TEST SUMMARY")
print("=" * 70)
print(f"Total matrices tested: {total_matrices}")
print(f"Passed: {passed_matrices} ({100*passed_matrices/total_matrices:.1f}%)")
print(f"Failed: {failed_matrices} ({100*failed_matrices/total_matrices:.1f}%)")
print(f"Time elapsed: {elapsed_time:.2f} seconds")
print("=" * 70 + "\n")
return {
'results': results,
'summary': {
'total': total_matrices,
'passed': passed_matrices,
'failed': failed_matrices,
'time': elapsed_time
}
}
def generate_report(self, test_results: Dict, output_file: Optional[str] = None):
"""
Generate a detailed test report
Args:
test_results: Results from run_all_tests()
output_file: File to write report to (prints if None)
"""
lines = []
lines.append("=" * 70)
lines.append("ANYMATRIX PROPERTY TEST REPORT")
lines.append("=" * 70)
lines.append("")
summary = test_results['summary']
lines.append(f"Total Matrices: {summary['total']}")
lines.append(f"Passed: {summary['passed']}")
lines.append(f"Failed: {summary['failed']}")
lines.append(f"Time: {summary['time']:.2f} seconds")
lines.append("")
lines.append("=" * 70)
lines.append("DETAILED RESULTS")
lines.append("=" * 70)
for group, matrices in test_results['results'].items():
lines.append(f"\nGroup: {group.upper()}")
lines.append("-" * 70)
for matrix_name, result in matrices.items():
matrix_id = f"{group}/{matrix_name}"
if 'error' in result:
lines.append(f" {matrix_id}: ERROR - {result['error']}")
continue
# Check no-args test
no_args = result.get('no_args', {})
if no_args.get('success'):
lines.append(f" {matrix_id} (no args): PASS")
# Check sized tests
sized = result.get('sized', {})
passed_sizes = [s for s, r in sized.items() if r.get('success')]
if passed_sizes:
lines.append(f" {matrix_id} (sizes {passed_sizes}): PASS")
# Show property failures
if no_args.get('properties'):
failed_props = [p for p, v in no_args['properties'].items() if v is False]
if failed_props:
lines.append(f" Failed properties: {', '.join(failed_props)}")
report = '\n'.join(lines)
if output_file:
with open(output_file, 'w') as f:
f.write(report)
print(f"Report written to: {output_file}")
else:
print(report)
return report
[docs]
def run_all_tests(
groups: Optional[List[str]] = None,
verbose: bool = True,
generate_report: bool = False,
report_file: Optional[str] = None
) -> Dict:
"""
Convenience function to run all anymatrix tests
Args:
groups: Groups to test (all if None)
verbose: Print progress
generate_report: Generate detailed report
report_file: File to save report
Returns:
Test results dictionary
"""
runner = AnyMatrixTestRunner()
results = runner.run_all_tests(groups=groups, verbose=verbose)
if generate_report:
runner.generate_report(results, output_file=report_file)
return results